symtab.c 5.45 KB
/*
 * Copyright (C) 1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * Copyright (C) 1998 Digital Equipment Corporation
 *
 * This file is part of the SimOS distribution.
 * See LICENSE file for terms of the license.
 *
 */


/*
 * Routines for reading the object file feader information
 */


#include <stdio.h>
#include <filehdr.h>
#include <aouthdr.h>
#include <scnhdr.h>
#include <syms.h>
#include <ldfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#undef SUCCESS
#undef FAILURE

#include "gamma.h"
#include "globals.h"
#include "protos.h"

#define FAILURE 0
#define SUCCESS 1

extern FILE *executable_fp;		/* file descriptor for object file */
struct filehdr file_header;

/* some work needs to be done here to compute the correct data_size */
void
read_hdrs (char *exec_filename, thread_ptr pthread)
{
    int i, magic;
    struct aouthdr ahdr;
    struct scnhdr shdr;
    struct stat file_status;
    
    executable_fp = fopen (exec_filename, "r");
    if (executable_fp == NULL) {
	perror (exec_filename);
	exit (1);
    }

    /* set the uid, gid of the thread */
    if (stat(exec_filename, &file_status) == -1)
	perror("stat");

#ifdef ORACLE
    /* is the setuid bit set ? */
    if (file_status.st_mode & S_ISUID)
	pthread->uid = file_status.st_uid;
    else
	/* user Rob's uid */
	pthread->uid = DEFAULT_UID;
    /* is the setgid bit set ? */
    if (file_status.st_mode & S_ISGID)
	pthread->gid = file_status.st_gid;
    else
	pthread->gid = DEFAULT_GID;
#endif
    
    fseek (executable_fp, 0, SEEK_SET);
    if (fread (&file_header, sizeof (struct filehdr), 1, executable_fp) < 1)
	  fatal ("read_hdrs: could not read file header\n");

    fseek (executable_fp, sizeof (struct filehdr), SEEK_SET);
    if (fread (&ahdr, sizeof (struct aouthdr), 1, executable_fp) < 1)
	  fatal ("read_hdrs: could not read optional header\n");

    magic = ahdr.magic;
    if (magic != OMAGIC && magic != NMAGIC && magic != ZMAGIC) {
	fprintf (stderr, "\n\"%s\" is not an alpha COFF executable file.\n",
		 exec_filename);
	fatal ("read_hdrs: bad magic number (0%o)\n", ahdr.magic);
    }

    /* allocate memory for the header */
    pthread->headerp = (struct header *) malloc(sizeof(struct header));
    /* zero out the data pointers */
    bzero((char *) (pthread->headerp), sizeof(struct header));
    
    pthread->headerp->data_start = ahdr.data_start;
    pthread->headerp->data_size = ahdr.dsize;

    pthread->headerp->bss_start = ahdr.bss_start;
    pthread->headerp->bss_size = ahdr.bsize;
    
    pthread->headerp->gp = ahdr.gp_value;

    /*
     * Seek to the beginning of the first section header.
     * The file header comes first, followed by the optional header
     * (This is the aouthdr). The size of the aouthdr is giben in
     * file_header.f_opthdr.
     */

    fseek (executable_fp, sizeof (struct filehdr)
	   + file_header.f_opthdr, SEEK_SET);

    /* loop through the section headers */
    for (i = 0; i < file_header.f_nscns; i++) {
	if (fread (&shdr, sizeof (struct scnhdr), 1, executable_fp) < 1)
	      fatal ("read_hdrs: could not read section header %d\n", i);

	switch (shdr.s_flags) {
	    case STYP_TEXT:
		pthread->headerp->text_seek = shdr.s_scnptr;
		pthread->headerp->text_start = shdr.s_vaddr;
		/* there is a null routine after the supposed end of text */
		pthread->headerp->text_size = shdr.s_size / 4 + 10;
		break;

	    case STYP_PDATA:
		pthread->headerp->pdata_start = shdr.s_vaddr;
		pthread->headerp->pdata_size = shdr.s_size;
		pthread->headerp->pdata_seek = shdr.s_scnptr;
		break;

	    case STYP_RDATA:
		/* the .rdata section is sometimes placed before the text
		 * section instead of being contiguous with the .data section
		 */
		pthread->headerp->rdata_start = shdr.s_vaddr;
		pthread->headerp->rdata_size = shdr.s_size;
		pthread->headerp->rdata_seek = shdr.s_scnptr;
		break;

	    case STYP_RCONST:
		pthread->headerp->rconst_start = shdr.s_vaddr;
		pthread->headerp->rconst_size = shdr.s_size;
		pthread->headerp->rconst_seek = shdr.s_scnptr;
		break;

	    case STYP_DATA:
		pthread->headerp->data_size = shdr.s_size;
		pthread->headerp->data_seek = shdr.s_scnptr;
		break;

	    case STYP_SDATA:
		pthread->headerp->data_size += shdr.s_size;
		pthread->headerp->sdata_seek = shdr.s_scnptr;
		break;

	    case STYP_LITA:
	    case STYP_LIT8:
	    case STYP_LIT4:
	    case STYP_XDATA:
		pthread->headerp->data_size += shdr.s_size;
		break;

	    case STYP_BSS:
		pthread->headerp->bss_start = shdr.s_vaddr;
		pthread->headerp->bss_size = shdr.s_size;
		break;

	    case STYP_SBSS:
		break;
	}
    }
    /* Read linenum and symtab information now */
}


/*
 * We store the program address for the function "sim_user"
 * in this variable
 */
unsigned long
find_proc_addr (char *objfile, char *symbol_name)
{
    static LDFILE *ldptr = NULL;
    int symindex;

    if (ldptr == NULL) {
	ldptr = ldopen (objfile, NULL);
	if (ldptr == NULL) {
	    perror ("ldopen");
	    exit (1);
	}
    }

    if (ldtbseek (ldptr) != SUCCESS) {
	perror ("ldtbseek");
	exit (1);
    }

    for (symindex = 0;; symindex++) {
	int status;
	SYMR duh_symbol;
	pSYMR symbol = &duh_symbol;
	status = ldtbread (ldptr, symindex, symbol);

	if (status != SUCCESS) {
	    return 0;
	}
	else {
	    char *name = ldgetname (ldptr, symbol);
	    if (strcmp (name, symbol_name) == 0) {
		if (symbol->sc == scText && symbol->st == stProc) {
#if VERBOSE
		    fprintf (stderr,
			     "*** Found sim_user function, addr = %lx !\n",
			     symbol->value);
#endif
		    return (symbol->value);
		}
	    }
	}
    }
}