Esempio n. 1
0
    /*
     * Read in symbol table
     */
static void
getsymtab(FILE *nfile, const char *filename)
{
    register long	i;
    int			askfor;
    struct nlist	nbuf;

    /* pass1 - count symbols */
    fseek(nfile, (long)N_SYMOFF(xbuf), 0);
    nname = 0;
    for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
	fread(&nbuf, sizeof(nbuf), 1, nfile);
	if ( ! funcsymbol( &nbuf ) ) {
	    continue;
	}
	nname++;
    }
    if (nname == 0)
	errx( 1 , "%s: no symbols" , filename );
    askfor = nname + 1;
    nl = (nltype *) calloc( askfor , sizeof(nltype) );
    if (nl == 0)
	errx( 1 , "no room for %d bytes of symbol table" ,
		askfor * sizeof(nltype) );

    /* pass2 - read symbols */
    fseek(nfile, (long)N_SYMOFF(xbuf), 0);
    npe = nl;
    nname = 0;
    for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
	fread(&nbuf, sizeof(nbuf), 1, nfile);
	if ( ! funcsymbol( &nbuf ) ) {
#	    ifdef DEBUG
		if ( debug & AOUTDEBUG ) {
		    printf( "[getsymtab] rejecting: 0x%x %s\n" ,
			    nbuf.n_type , strtab + nbuf.n_un.n_strx );
		}
#	    endif /* DEBUG */
	    continue;
	}
	npe->value = nbuf.n_value;
	npe->name = strtab+nbuf.n_un.n_strx;
#	ifdef DEBUG
	    if ( debug & AOUTDEBUG ) {
		printf( "[getsymtab] %d %s 0x%08lx\n" ,
			nname , npe -> name , npe -> value );
	    }
#	endif /* DEBUG */
	npe++;
	nname++;
    }
    npe->value = -1;
}
Esempio n. 2
0
/* Set parameters about this a.out file that are machine-dependent.
   This routine is called from some_aout_object_p just before it returns.  */
static const bfd_target *
MY (callback) (bfd *abfd)
{
  struct internal_exec *execp = exec_hdr (abfd);

  /* Calculate the file positions of the parts of a newly read aout header */
  obj_textsec (abfd)->size = N_TXTSIZE (*execp);

  /* The virtual memory addresses of the sections */
  obj_textsec (abfd)->vma = N_TXTADDR (*execp);
  obj_datasec (abfd)->vma = N_DATADDR (*execp);
  obj_bsssec (abfd)->vma = N_BSSADDR (*execp);

  obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
  obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
  obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;

  /* The file offsets of the sections */
  obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
  obj_datasec (abfd)->filepos = N_DATOFF (*execp);

  /* The file offsets of the relocation info */
  obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
  obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);

  /* The file offsets of the string table and symbol table.  */
  obj_sym_filepos (abfd) = N_SYMOFF (*execp);
  obj_str_filepos (abfd) = N_STROFF (*execp);

  /* Determine the architecture and machine type of the object file.  */
#ifdef SET_ARCH_MACH
  SET_ARCH_MACH (abfd, *execp);
#else
  bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
#endif

  if (obj_aout_subformat (abfd) == gnu_encap_format)
    {
      /* The file offsets of the relocation info */
      obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
      obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);

      /* The file offsets of the string table and symbol table.  */
      obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
      obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);

      abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
      bfd_get_symcount (abfd) = execp->a_syms / 12;
      obj_symbol_entry_size (abfd) = 12;
      obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
    }

  return abfd->xvec;
}
Esempio n. 3
0
static struct nlist *
load_sym(int fd, struct exec *hdrp, long disp)
{
    struct nlist * buffer;
    struct nlist * sym;
    struct nlist * end;
    long displ;
    int size;

    lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0);
    if (read(fd, &size, sizeof(int)) != sizeof(int)) {
	goto err_noexec;
    }

    buffer = (struct nlist*)xmalloc(hdrp->a_syms + size);
    if (buffer == NULL) {
	dln_errno = errno;
	return NULL;
    }

    lseek(fd, disp + N_SYMOFF(*hdrp), 0);
    if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) {
	free(buffer);
	goto err_noexec;
    }

    sym = buffer;
    end = sym + hdrp->a_syms / sizeof(struct nlist);
    displ = (long)buffer + (long)(hdrp->a_syms);

    while (sym < end) {
	sym->n_un.n_name = (char*)sym->n_un.n_strx + displ;
	sym++;
    }
    return buffer;

  err_noexec:
    dln_errno = DLN_ENOEXEC;
    return NULL;
}
Esempio n. 4
0
int read_nlist(char *systemfile)
{
    int fd;
    struct exec hdr;
    unsigned symsize, size;

    if ((fd = open(systemfile, O_RDONLY)) < 0) {
	perror(systemfile);
	exit(1);
    }
    if (read(fd, (char *) &hdr, sizeof(hdr)) != sizeof(hdr)) {
	perror(systemfile);
	exit(1);
    }
    if (N_BADMAG(hdr)) {
	fprintf(stderr, "%s: bad magic number\n", systemfile);
	exit(1);
    }
    if (N_STROFF(hdr) == 0) {
	fprintf(stderr, "%s has no symbols\n", systemfile);
	exit(1);
    }
    lseek(fd, N_STROFF(hdr), SEEK_SET);
    read(fd, (char *) &stringsize, sizeof(stringsize));
    symsize = N_STROFF(hdr) - N_SYMOFF(hdr);
    size = symsize + stringsize;
    namelist = (struct nlist *) xmalloc(size);
    lseek(fd, N_SYMOFF(hdr), SEEK_SET);
    if (read(fd, (char *) namelist, size) != size) {
	perror(systemfile);
	exit(1);
    }
    close(fd);

    strings = ((char *) namelist) + symsize;
    nsym = symsize / sizeof(struct nlist);
    if (Debug > 1)
	fprintf(stderr, "read %d symbols from %s\n", nsym, systemfile);
    return(0);
}
Esempio n. 5
0
static void
getstrtab(FILE *nfile, const char *filename)
{

    fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0);
    if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0)
	errx( 1 , "%s: no string table (old format?)" , filename );
    strtab = calloc(ssiz, 1);
    if (strtab == NULL)
	errx( 1 , "%s: no room for %ld bytes of string table", filename , ssiz);
    if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1)
	errx( 1 , "%s: error reading string table" , filename );
}
Esempio n. 6
0
/* build the new symbol and string tables
*/
static void buildNewTables(const HDR *x, long nsyms)
{
	long remaining = nsyms;  // total number of symbol table entries remaining to process
#if FAST_NONPORTABLE_STRUCT_ARRAY_READ
	const int bunch = 1024;  // number of symbol table entries to process at a time	
#else
	const int bunch = 1;
#endif
	char *syms = new char[bunch*SYMSZ];	// buffer of old symbol table entries
	fseek(sym, N_SYMOFF(*x), 0);		// go to old symbol table
						// fill the buffer
	int numInBuffer = xfread(syms, SYMSZ, min(bunch, remaining), sym);  
	int symsi = 0;				// index in buffer
	char *thisSym = syms;			// pointer to entry symsi in buffer
	int auxEntries = 0;			// number of aux entries still to skip over
	while (remaining)
	{
		if (auxEntries)  // skip over them
		{
			if (auxEntries < 0)
				fatalError("Bad symbol table");
			int skip = min(numInBuffer-symsi, auxEntries);
			if (remaining < skip)
				fatalError("Bad symbol table (missing auxiliary entries)");
			auxEntries -= skip;
			remaining -= skip;
			symsi += skip;
			thisSym += skip*SYMSZ;
		}
		else
		{
			transformSymEntry((SYM*)thisSym);
			auxEntries = N_AUX(*(SYM*)thisSym);
			remaining--;
			symsi++;
			thisSym += SYMSZ;
		}
		assert (symsi <= bunch);
		if (symsi == bunch)  // write and then refill the buffer
		{
			xfwrite(syms, SYMSZ, numInBuffer, newSym);
			numInBuffer = xfread(syms, SYMSZ, min(bunch, remaining), sym);
			symsi = 0;
			thisSym = syms;
		}	
	}
	xfwrite(syms, SYMSZ, numInBuffer, newSym);
	delete syms;  
}
Esempio n. 7
0
static void overwriteOldTables(const HDR *x)
{
	// write the new symbol table to the original a.out,
	// beginning at the beginning of the original symbol table
	fseek(sym, N_SYMOFF(*x), 0);
	overwrite(newSym, sym);

	// write the new string table to the original a.out,
	// beginning right after the new symbol table
	long len = ftell(newSng) + 4;
	xfwrite(&len, 4, 1, sym);
	overwrite(newSng, sym);

	// rem: truncate, but probably doesn't need it.
}
Esempio n. 8
0
SYMTAB *Snarf_Symbols (FILE *f, struct exec *ep) {
    SYMTAB *tab;
    register SYM *sp, **nextp;
    int nsyms, strsiz;
    struct nlist nl;

    tab = (SYMTAB *)Safe_Malloc (sizeof (SYMTAB));
    tab->first = 0;
    tab->strings = 0;
    nextp = &tab->first;
    (void)fseek (f, (long)N_SYMOFF(*ep), 0);
    for (nsyms = ep->a_syms / sizeof (nl); nsyms > 0; nsyms--) {
        if (fread ((char *)&nl, sizeof (nl), 1, f) != 1) {
            Free_Symbols (tab);
            (void)fclose (f);
            Primitive_Error ("corrupt symbol table in object file");
        }
        if (nl.n_un.n_strx == 0 || nl.n_type & N_STAB)
            continue;
#ifndef ibm023
        if ((nl.n_type & N_TYPE) != N_TEXT)
            continue;
#endif
        sp = (SYM *)Safe_Malloc (sizeof (SYM));
        sp->name = (char *)nl.n_un.n_strx;
        sp->value = nl.n_value;
        *nextp = sp;
        nextp = &sp->next;
        *nextp = 0;
    }
    if (fread ((char *)&strsiz, sizeof (strsiz), 1, f) != 1) {
strerr:
        Free_Symbols (tab);
        (void)fclose (f);
        Primitive_Error ("corrupt string table in object file");
    }
    if (strsiz <= 4)
        goto strerr;
    tab->strings = Safe_Malloc (strsiz);
    strsiz -= 4;
    if (fread (tab->strings+4, 1, strsiz, f) != strsiz)
        goto strerr;
    for (sp = tab->first; sp; sp = sp->next)
        sp->name = tab->strings + (long)sp->name;
    return tab;
}
Esempio n. 9
0
void
a_out_mod_symload(int strtablen)
{
	struct lmc_loadbuf ldbuf;
	char buf[MODIOBUF];
	int bytesleft, sz;

	/*
	 * Seek to the symbol table to start loading it...
	 */
	if (lseek(modfd, N_SYMOFF(sinfo_buf), SEEK_SET) == -1)
		err(12, "lseek");

	/*
	 * we've fixed the symbol table entries, now load them
	 */
	for (bytesleft = sinfo_buf.a_syms; bytesleft > 0; bytesleft -= sz) {
		sz = MIN(bytesleft, MODIOBUF);
		if (read(modfd, buf, sz) != sz)
			err(14, "read");
		ldbuf.cnt = sz;
		ldbuf.data = buf;
		if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
			err(11, "error transferring sym buffer");
	}

	/* and now read the string table and load it. */
	for (bytesleft = strtablen; bytesleft > 0; bytesleft -= sz) {
		sz = MIN(bytesleft, MODIOBUF);
		if (read(modfd, buf, sz) != sz)
			err(14, "read");
		ldbuf.cnt = sz;
		ldbuf.data = buf;
		if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
			err(11, "error transferring stringtable buffer");
	}
}
Esempio n. 10
0
void 
hide_syms(char *filename)
{
	int             inf, outf, rc;
	struct stat     infstat;
	struct relocation_info *relp;
	struct nlist   *symp;
	char           *buf;
	u_char          zero = 0;

	/*
         * Open the file and do some error checking.
         */

	if ((inf = open(filename, O_RDWR)) == -1) {
		perror(filename);
		return;
	}
	if (fstat(inf, &infstat) == -1) {
		perror(filename);
		close(inf);
		return;
	}
	if (infstat.st_size < sizeof(struct exec)) {
		fprintf(stderr, "%s: short file\n", filename);
		close(inf);
		return;
	}
	if ((buf = mmap(NULL, infstat.st_size, PROT_READ | PROT_WRITE,
	    MAP_FILE | MAP_SHARED, inf, 0)) == MAP_FAILED) {
		fprintf(stderr, "%s: cannot map\n", filename);
		close(inf);
		return;
	}

#ifdef _NLIST_DO_ELF
	if (buf[0] == 0x7f && (buf[1] == 'E' || buf[1] == 'O') &&
	    buf[2] == 'L' && buf[3] == 'F') {
		elf_hide(inf, buf);
		return;
	}
#endif				/* _NLIST_DO_ELF */

#ifdef _NLIST_DO_ECOFF
	if (!ECOFF_BADMAG((struct ecoff_exechdr *) buf)) {
		ecoff_hide(inf, buf);
		return;
	}
#endif				/* _NLIST_DO_ECOFF */

#ifdef DO_AOUT
	aoutdata = buf;

	/*
         * Check the header and calculate offsets and sizes from it.
         */
	hdrp = (struct exec *) aoutdata;

	if (N_BADMAG(*hdrp)) {
		fprintf(stderr, "%s: bad magic: not an a.out, ecoff or elf  file\n",
		    filename);
		close(inf);
		return;
	}
	textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp));
	datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp));
	symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp));
	strbase = (char *) (aoutdata + N_STROFF(*hdrp));

	ntextrel = hdrp->a_trsize / sizeof(struct relocation_info);
	ndatarel = hdrp->a_drsize / sizeof(struct relocation_info);
	nsyms = hdrp->a_syms / sizeof(struct nlist);

	/*
         * Zap the type field of all globally-defined symbols.  The linker will
         * subsequently ignore these entries.  Don't zap any symbols in the
         * keep list.
         */
	for (symp = symbase; symp < symbase + nsyms; symp++)
		if (IS_GLOBAL_DEFINED(symp) && !in_keep_list(SYMSTR(symp))) {
			/*
		         * XXX Our VM system has some problems, so
		         * avoid the VM system....
		         */
			lseek(inf, (off_t) ((void *) &symp->n_type -
			    (void *) buf), SEEK_SET);
			write(inf, &zero, sizeof zero);
			symp->n_type = 0;
		}
	/*
         * Check whether the relocation entries reference any symbols that we
         * just zapped.  I don't know whether ld can handle this case, but I
         * haven't encountered it yet.  These checks are here so that the program
         * doesn't fail silently should such symbols be encountered.
         */
	for (relp = textrel; relp < textrel + ntextrel; relp++)
		check_reloc(filename, relp);
	for (relp = datarel; relp < datarel + ndatarel; relp++)
		check_reloc(filename, relp);

	msync(buf, infstat.st_size, MS_SYNC);
	munmap(buf, infstat.st_size);
	close(inf);
#endif				/* DO_AOUT */
}
Esempio n. 11
0
int
__fdnlist_aout(int fd, struct nlist *list)
{
	struct nlist *p, *s;
	char *strtab;
	off_t stroff, symoff;
	int nent;
	size_t strsize, symsize, cc;
	struct nlist nbuf[1024];
	struct exec exec;
	struct stat st;
	char *scoreboard, *scored;

	_DIAGASSERT(fd != -1);
	_DIAGASSERT(list != NULL);

	if (pread(fd, &exec, sizeof(exec), (off_t)0) != sizeof(exec) ||
	    N_BADMAG(exec) || fstat(fd, &st) < 0)
		return (-1);

	symoff = N_SYMOFF(exec);
	symsize = (size_t)exec.a_syms;
	stroff = symoff + symsize;

	/* Check for files too large to mmap. */
	if ((uintmax_t)(st.st_size - stroff) > (uintmax_t)SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}
	/*
	 * Map string table into our address space.  This gives us
	 * an easy way to randomly access all the strings, without
	 * making the memory allocation permanent as with malloc/free
	 * (i.e., munmap will return it to the system).
	 */
	strsize = (size_t)(st.st_size - stroff);
	strtab = mmap(NULL, strsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
	    fd, stroff);
	if (strtab == (char *)-1)
		return (-1);
	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * XXX clearing anything other than n_type and n_value violates
	 * the semantics given in the man page.
	 */
	nent = 0;
	for (p = list; !ISLAST(p); ++p) {
		p->n_type = 0;
		p->n_other = 0;
		p->n_desc = 0;
		p->n_value = 0;
		++nent;
	}
	if (lseek(fd, symoff, SEEK_SET) == -1)
		return (-1);
#if defined(__SSP__) || defined(__SSP_ALL__)
	scoreboard = malloc((size_t)nent);
#else
	scoreboard = alloca((size_t)nent);
#endif
	if (scoreboard == NULL)
		return (-1);
	(void)memset(scoreboard, 0, (size_t)nent);

	while (symsize > 0) {
		cc = MIN(symsize, sizeof(nbuf));
		if (read(fd, nbuf, cc) != (ssize_t) cc)
			break;
		symsize -= cc;
		for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
			long soff = s->n_un.n_strx;

			if (soff == 0 || (s->n_type & N_STAB) != 0)
				continue;
			for (p = list, scored = scoreboard; !ISLAST(p);
			    p++, scored++)
				if (*scored == 0 &&
				    !strcmp(&strtab[(size_t)soff],
				    p->n_un.n_name)) {
					p->n_value = s->n_value;
					p->n_type = s->n_type;
					p->n_desc = s->n_desc;
					p->n_other = s->n_other;
					*scored = 1;
					if (--nent <= 0)
						break;
				}
		}
	}
	munmap(strtab, strsize);
#if defined(__SSP__) || defined(__SSP_ALL__)
	free(scoreboard);
#endif
	return (nent);
}
Esempio n. 12
0
File: nm.c Progetto: McIkye/tools
/*
 * show_file()
 *	show symbols from the object file pointed to by fp.  The current
 *	file pointer for fp is expected to be at the beginning of an object
 *	file header.
 */
int
show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
{
	u_long text, data, bss, total;
	struct nlist *np, *names, **snames;
	char *stab;
	int i, aout, nnames;
	size_t stabsize;
	off_t staboff;

	aout = 0;
	if (!elf32_chk_header(&head->elf32)) {
		struct elf_symtab es;

		es.name = name;
		es.ehdr = &head->elf32;
		if (head->elf32.e_ehsize < sizeof head->elf32) {
			warnx("%s: ELF header is too short", name);
			return 1;
		}

		if (!(es.shdr = elf32_load_shdrs(name, fp, foff, es.ehdr)))
			return (1);
		elf32_fix_shdrs(es.ehdr, es.shdr);
		es.shstr = NULL;

		if (issize)
			i = elf32_size(es.ehdr, es.shdr, &text, &data, &bss);
		else {
			nrawnames = 0;
			names = NULL;
			i = elf32_symload(&es, fp, foff, elf_symadd, &names);
			stab = es.stab;
			stabsize = es.stabsz;
		}
		free(es.shstr);
		free(es.shdr);
		if (i)
			return (i);

	} else if (!elf64_chk_header(&head->elf64)) {
		struct elf_symtab es;

		es.name = name;
		es.ehdr = &head->elf64;
		if (head->elf64.e_ehsize < sizeof head->elf64) {
			warnx("%s: ELF header is too short", name);
			return 1;
		}
		if (!(es.shdr = elf64_load_shdrs(name, fp, foff, es.ehdr)))
			return (1);
		elf64_fix_shdrs(es.ehdr, es.shdr);
		es.shstr = NULL;

		if (issize)
			i = elf64_size(es.ehdr, es.shdr, &text, &data, &bss);
		else {
			nrawnames = 0;
			names = NULL;
			i = elf64_symload(&es, fp, foff, elf_symadd, &names);
			stab = es.stab;
			stabsize = es.stabsz;
		}
		free(es.shstr);
		free(es.shdr);
		if (i)
			return (i);

	} else if (BAD_OBJECT(head->aout)) {
		if (warn_fmt)
			warnx("%s: bad format", name);
		return (1);
	} else do {
		u_int32_t w;

		aout++;

		fix_header_order(&head->aout);

		if (issize) {
			text = head->aout.a_text;
			data = head->aout.a_data;
			bss = head->aout.a_bss;
			break;
		}

		/* stop if the object file contains no symbol table */
		if (!head->aout.a_syms) {
			warnx("%s: no name list", name);
			return(1);
		}

		if (fseeko(fp, foff + N_SYMOFF(head->aout), SEEK_SET)) {
			warn("%s", name);
			return(1);
		}

#ifdef __LP64__
		nrawnames = head->aout.a_syms / sizeof(struct nlist32);
#else
		nrawnames = head->aout.a_syms / sizeof(*names);
#endif
		/* get memory for the symbol table */
		if ((names = calloc(nrawnames, sizeof(struct nlist))) == NULL) {
			warn("%s: malloc names", name);
			return (1);
		}

#ifdef __LP64__
		for (np = names, i = nrawnames; i--; np++) {
			struct nlist32 nl32;

			if (fread(&nl32, sizeof(nl32), 1, fp) != 1) {
				warnx("%s: cannot read symbol table", name);
				free(names);
				return (1);
			}
			np->n_type = nl32.type;
			np->n_other = nl32.other;
			if (byte_sex(N_GETMID(head->aout)) != BYTE_ORDER) {
				np->n_un.n_strx = swap32(nl32.strx);
				np->n_desc = swap16(nl32.desc);
				np->n_value = swap32(nl32.value);
			} else {
				np->n_un.n_strx = nl32.strx;
				np->n_desc = nl32.desc;
				np->n_value = nl32.value;
			}
		}
#else
		if (fread(names, head->aout.a_syms, 1, fp) != 1) {
			warnx("%s: cannot read symbol table", name);
			free(names);
			return (1);
		}
		fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
#endif

		staboff = ftello(fp);
		/*
		 * Following the symbol table comes the string table.
		 * The first 4-byte-integer gives the total size of the
		 * string table _including_ the size specification itself.
		 */
		if (fread(&w, sizeof(w), (size_t)1, fp) != 1) {
			warnx("%s: cannot read stab size", name);
			free(names);
			return(1);
		}

		stabsize = fix_32_order(w, N_GETMID(head->aout));
		if ((stab = malloc(stabsize)) == NULL) {
			warn("%s: malloc", name);
			return 1;
		}

		if (pread(fileno(fp), stab, stabsize, staboff) != stabsize) {
			free(stab);
			warn("%s: pread", name);
			return 1;
		}

		stabsize -= 4;		/* we already have the size */
		for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
			/*
			 * make n_un.n_name a character pointer by adding
			 * the string table's base to n_un.n_strx
			 *
			 * don't mess with zero offsets
			 */
			if (np->n_un.n_strx)
				np->n_un.n_name = stab + np->n_un.n_strx;
			else
				np->n_un.n_name = "";
		}
	} while (0);

	if (issize) {
		static int first = 1;

		if (first) {
			first = 0;
			printf("text\tdata\tbss\tdec\thex\n");
		}

		total = text + data + bss;
		printf("%lu\t%lu\t%lu\t%lu\t%lx",
		    text, data, bss, total, total);
		if (count > 1)
			(void)printf("\t%s", name);

		total_text += text;
		total_data += data;
		total_bss += bss;
		total_total += total;

		printf("\n");
		return (0);
	}
	/* else we are nm */

	/*
	 * it seems that string table is sequential
	 * relative to the symbol table order
	 */
	if ((snames = calloc(nrawnames, sizeof *snames)) == NULL) {
		warn("%s: malloc snames", name);
		free(names);
		return (1);
	}

	/*
	 * fix up the symbol table and filter out unwanted entries
	 *
	 * common symbols are characterized by a n_type of N_UNDF and a
	 * non-zero n_value -- change n_type to N_COMM for all such
	 * symbols to make life easier later.
	 *
	 * filter out all entries which we don't want to print anyway
	 */
	for (np = names, i = nnames = 0; i < nrawnames; np++, i++) {
		if (aout && SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
			np->n_type = N_COMM | (np->n_type & N_EXT);
		if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type))
			continue;
		if (print_only_external_symbols && !IS_EXTERNAL(np->n_type))
			continue;
		if (print_only_undefined_symbols &&
		    SYMBOL_TYPE(np->n_type) != N_UNDF)
			continue;

		snames[nnames++] = np;
	}

	/* sort the symbol table if applicable */
	if (sfunc)
		qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);

	if (count > 1)
		(void)printf("\n%s:\n", name);

	/* print out symbols */
	for (i = 0; i < nnames; i++) {
		if (show_extensions && snames[i] != names &&
		    SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)
			continue;
		print_symbol(name, snames[i], aout);
	}

	free(snames);
	free(names);
	free(stab);
	return(0);
}
Esempio n. 13
0
/*
 * rexec
 *	Read the exec structure; ignore any files that don't look
 *	exactly right. Return MID.
 * 	return -1 for files that don't look right.
 *	XXX it's hard to be sure when to ignore files, and when to error
 *	out.
 */
static int
rexec(int rfd, int wfd)
{
	RLIB *rp;
	long nsyms;
	int nr, symlen;
	char *strtab = 0;
	char *sym;
	struct exec ebuf;
	struct nlist nl;
	off_t r_off, w_off;
	long strsize;
	int result = -1;

	/* Get current offsets for original and tmp files. */
	r_off = lseek(rfd, (off_t)0, SEEK_CUR);
	w_off = lseek(wfd, (off_t)0, SEEK_CUR);

	/* Read in exec structure. */
	nr = read(rfd, (char *)&ebuf, sizeof(struct exec));
	if (nr != sizeof(struct exec))
		goto bad;

	/* Check magic number and symbol count. */
	if (BAD_OBJECT(ebuf) || ebuf.a_syms == 0)
		goto bad;
	fix_header_order(&ebuf);

	/* Seek to string table. */
	if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) {
		if (errno == EINVAL)
			goto bad;
		else
			error(archive);
	}

	/* Read in size of the string table. */
	nr = read(rfd, (char *)&strsize, sizeof(strsize));
	if (nr != sizeof(strsize))
		goto bad;

	strsize = fix_32_order(strsize, N_GETMID(ebuf));

	/* Read in the string table. */
	strsize -= sizeof(strsize);
	strtab = (char *)emalloc(strsize);
	nr = read(rfd, strtab, strsize);
	if (nr != strsize) 
		goto bad;

	/* Seek to symbol table. */
	if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1)
		goto bad;

	result = N_GETMID(ebuf);
	/* For each symbol read the nlist entry and save it as necessary. */
	nsyms = ebuf.a_syms / sizeof(struct nlist);
	while (nsyms--) {
		if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) {
			if (feof(fp))
				badfmt();
			error(archive);
		}
		fix_nlist_order(&nl, N_GETMID(ebuf));

		/* Ignore if no name or local. */
		if (!nl.n_un.n_strx || !(nl.n_type & N_EXT))
			continue;

		/*
		 * If the symbol is an undefined external and the n_value
		 * field is non-zero, keep it.
		 */
		if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value)
			continue;

		/* First four bytes are the table size. */
		sym = strtab + nl.n_un.n_strx - sizeof(long);
		symlen = strlen(sym) + 1;

		rp = (RLIB *)emalloc(sizeof(RLIB));
		rp->sym = (char *)emalloc(symlen);
		bcopy(sym, rp->sym, symlen);
		rp->symlen = symlen;
		rp->pos = w_off;

		/* Build in forward order for "ar -m" command. */
		*pnext = rp;
		pnext = &rp->next;

		++symcnt;
		tsymlen += symlen;
	}

bad: 	if (nr < 0)
		error(archive);
	free(strtab);
	(void)lseek(rfd, (off_t)r_off, SEEK_SET);
	return result;
}
Esempio n. 14
0
int
main(int argc, char **argv)
{
	struct nlist *p, *symp;
	FILE *f, *xfile;
	int i;
	char *start, *t, *xfilename;
	int ch, n, o;

	xfilename = NULL;
	while ((ch = getopt(argc, argv, "cmtx:")) != -1)
		switch(ch) {
		case 'c':
			clean = 1;
			break;
		case 'm':
			missing = 1;
			break;
		case 't':
			small = 1;
			break;
		case 'x':
			if (xfilename != NULL)
				usage();
			xfilename = optarg;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc != 2)
		usage();

	if ((f = fopen(argv[0], "r")) == NULL)
		err(ERREXIT, "%s", argv[0]);

	for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
		for (t = asym; isspace(*t); ++t);
		if (!*(start = t))
			continue;
		while (*++t);
		if (*--t == '\n')
			*t = '\0';
		p->n_un.n_name = strdup(start);
		++p;
		if (++nsym >= sizeof order / sizeof order[0])
			break;
	}
	(void)fclose(f);

	if (xfilename != NULL) {
		if ((xfile = fopen(xfilename, "r")) == NULL)
			err(ERREXIT, "%s", xfilename);
		for (; fgets(asym, sizeof(asym), xfile) != NULL;) {
			for (t = asym; isspace(*t); ++t);
			if (!*(start = t))
				continue;
			while (*++t);
			if (*--t == '\n')
				*t = '\0';
			exclude[nexclude] = strdup(start);
			if (++nexclude >= sizeof exclude / sizeof exclude[0])
				break;
		}
		(void)fclose(xfile);
	}

	kfile = argv[1];
	if ((f = fopen(kfile, "r")) == NULL)
		err(ERREXIT, "%s", kfile);
	if ((o = open(kfile, O_WRONLY)) < 0)
		err(ERREXIT, "%s", kfile);

	/* read exec header */
	if ((fread(&exec, sizeof(exec), 1, f)) != 1)
		badfmt("no exec header");
	if (N_BADMAG(exec))
		badfmt("bad magic number");
	if (exec.a_syms == 0)
		badfmt("stripped");
	(void)fstat(fileno(f), &stb);
	if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
		badfmt("no string table");

	/* seek to and read the symbol table */
	sa = N_SYMOFF(exec);
	(void)fseek(f, sa, SEEK_SET);
	n = exec.a_syms;
	if (!(symtab = (struct nlist *)malloc(n)))
		err(ERREXIT, NULL);
	if (fread((void *)symtab, 1, n, f) != n)
		badfmt("corrupted symbol table");

	/* read string table size and string table */
	if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 ||
	    strtabsize <= 0)
		badfmt("corrupted string table");
	strings = malloc(strtabsize);
	if (strings == NULL)
		err(ERREXIT, NULL);
	/*
	 * Subtract four from strtabsize since strtabsize includes itself,
	 * and we've already read it.
	 */
	if (fread(strings, 1, strtabsize - sizeof(int), f) !=
	    strtabsize - sizeof(int))
		badfmt("corrupted string table");

	i = n / sizeof(struct nlist);
	if (!clean) {
		newtab = (struct nlist *)malloc(n);
		if (newtab == NULL)
			err(ERREXIT, NULL);
		memset(newtab, 0, n);

		reorder(symtab, newtab, i);
		free((void *)symtab);
		symtab = newtab;
	} else {
		symkept = i;
	}

	newstrings = malloc(strtabsize);
	if (newstrings == NULL)
		err(ERREXIT, NULL);
	t = newstrings;
	for (symp = symtab; --i >= 0; symp++) {
		if (symp->n_un.n_strx == 0)
			continue;
		if (inlist(symp) < 0) {
			if (small)
				continue;
			if (clean && !savesymb(symp))
				symp->n_type &= ~N_EXT;
		} else if (clean)
			symfound++;
		symp->n_un.n_strx -= sizeof(int);
		(void)strcpy(t, &strings[symp->n_un.n_strx]);
		symp->n_un.n_strx = (t - newstrings) + sizeof(int);
		t += strlen(t) + 1;
	}

	/* update shrunk sizes */
	strtabsize = t - newstrings + sizeof(int);
	n = symkept * sizeof(struct nlist);

	/* fix exec sym size */
	(void)lseek(o, (off_t)0, SEEK_SET);
	exec.a_syms = n;
	if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec))
		err(ERREXIT, "%s", kfile);

	(void)lseek(o, sa, SEEK_SET);
	if (write(o, (void *)symtab, n) != n)
		err(ERREXIT, "%s", kfile);
	if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int))
		err(ERREXIT, "%s", kfile);
	if (write(o, newstrings, strtabsize - sizeof(int)) !=
	    strtabsize - sizeof(int))
		err(ERREXIT, "%s", kfile);

	ftruncate(o, lseek(o, (off_t)0, SEEK_CUR));

	if ((i = nsym - symfound) > 0) {
		(void)printf("symorder: %d symbol%s not found:\n",
		    i, i == 1 ? "" : "s");
		for (i = 0; i < nsym; i++)
			if (order[i].n_value == 0)
				printf("%s\n", order[i].n_un.n_name);
		if (!missing)
			exit(NOTFOUNDEXIT);
	}
	exit(OKEXIT);
}
Esempio n. 15
0
int
__aout_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p, *s;
	char *strtab;
	off_t symoff, stroff;
	u_long symsize;
	int nent, cc;
	int strsize, usemalloc = 0;
	struct nlist nbuf[1024];
	struct exec exec;

	if (pread(fd, &exec, sizeof(exec), (off_t)0) != sizeof(exec) ||
	    N_BADMAG(exec) || exec.a_syms == NULL)
		return (-1);

	stroff = N_STROFF(exec);
	symoff = N_SYMOFF(exec);
	symsize = exec.a_syms;

	/* Read in the size of the string table. */
	if (pread(fd, (void *)&strsize, sizeof(strsize), stroff) !=
	    sizeof(strsize))
		return (-1);
	else
		stroff += sizeof(strsize);

	/*
	 * Read in the string table.  We try mmap, but that will fail
	 * for /dev/ksyms so fall back on malloc.  Since OpenBSD's malloc(3)
	 * returns memory to the system on free this does not cause bloat.
	 */
	strsize -= sizeof(strsize);
	strtab = mmap(NULL, (size_t)strsize, PROT_READ, MAP_SHARED|MAP_FILE,
	    fd, stroff);
	if (strtab == MAP_FAILED) {
		usemalloc = 1;
		if ((strtab = (char *)malloc(strsize)) == NULL)
			return (-1);
		errno = EIO;
		if (pread(fd, strtab, strsize, stroff) != strsize) {
			nent = -1;
			goto aout_done;
		}
	}

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * XXX clearing anything other than n_type and n_value violates
	 * the semantics given in the man page.
	 */
	nent = 0;
	for (p = list; !ISLAST(p); ++p) {
		p->n_type = 0;
		p->n_other = 0;
		p->n_desc = 0;
		p->n_value = 0;
		++nent;
	}

	while (symsize > 0) {
		cc = MIN(symsize, sizeof(nbuf));
		if (pread(fd, nbuf, cc, symoff) != cc)
			break;
		symsize -= cc;
		symoff += cc;
		for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
			char *sname = strtab + s->n_un.n_strx - sizeof(int);

			if (s->n_un.n_strx == 0 || (s->n_type & N_STAB) != 0)
				continue;
			for (p = list; !ISLAST(p); p++) {
				char *pname = p->n_un.n_name;

				if (*sname != '_' && *pname == '_')
					pname++;
				if (!strcmp(sname, pname)) {
					p->n_value = s->n_value;
					p->n_type = s->n_type;
					p->n_desc = s->n_desc;
					p->n_other = s->n_other;
					if (--nent <= 0)
						break;
				}
			}
		}
	}
aout_done:
	if (usemalloc)
		free(strtab);
	else
		munmap(strtab, strsize);
	return (nent);
}
Esempio n. 16
0
/*
 * read_exec
 *	Read the exec structure; ignore any files that don't look
 *	exactly right. Return MID.
 *	return -1 for files that don't look right.
 *	XXX it's hard to be sure when to ignore files, and when to error
 *	out.
 */
int
read_exec(FILE *rfp, FILE *wfp, long *symcnt, long *tsymlen)
{
	union {
		struct exec exec;
		Elf32_Ehdr elf32;
		Elf64_Ehdr elf64;
	} eh;
	struct nlist nl;
	off_t r_off, w_off;
	char *strtab = NULL;
	long strsize, nsyms;
	int i;

	/* Get current offsets for original and tmp files. */
	r_off = ftello(rfp);
	w_off = ftello(wfp);

	/* Read in exec structure. */
	if (fread(&eh, sizeof(eh), 1, rfp) != 1)
		err(1, "fread: %s", archive);

	if (!elf32_chk_header(&eh.elf32)) {
		Elf32_Sym sbuf;
		char *shstr;
		Elf32_Shdr *shdr;
		size_t stabsize;

		elf32_fix_header(&eh.elf32);
		if (eh.elf32.e_ehsize < sizeof eh.elf32) {
			warnx("%s: ELF header is too short", archive);
			goto bad;
		}

		if (!(shdr = elf32_load_shdrs(archive, rfp, r_off, &eh.elf32)))
			goto bad;
		elf32_fix_shdrs(&eh.elf32, shdr);

		if (!(shstr = elf32_shstrload(archive, rfp, r_off, &eh.elf32,
		    shdr))) {
			free(shdr);
			goto bad;
		}

		if (!(strtab = elf32_strload(archive, rfp, r_off, &eh.elf32,
		    shdr, shstr, ELF_STRTAB, &stabsize))) {
			free(shstr);
			free(shdr);
			goto bad;
		}

		/* find the symtab section */
		for (i = 0; i < eh.elf32.e_shnum; i++)
			if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {
				nsyms = shdr[i].sh_size / sizeof(Elf32_Sym);
				break;
			}

		if (i == eh.elf32.e_shnum) {
			free(shstr);
			free(shdr);
			goto bad;
		}

		if (fseeko(rfp, r_off + shdr[i].sh_offset, SEEK_SET))
			err(1, "fseeko: %s", archive);

		for (i = 0; i < nsyms; i++) {
			if (fread(&sbuf, sizeof(sbuf), 1, rfp) != 1)
				err(1, "fread: %s", archive);

			elf32_fix_sym(&eh.elf32, &sbuf);
			if (!sbuf.st_name || sbuf.st_name > stabsize)
				continue;

			if (elf32_2nlist(&sbuf, &eh.elf32, shdr, shstr, &nl))
				continue;

			addsym(&nl, strtab, r_off - r_fuzz -
			    sizeof(struct ar_hdr), symcnt, tsymlen, archive);
		}

		free(strtab);
		free(shstr);
		free(shdr);
		(void)fseeko(rfp, r_off, SEEK_SET);
		return MID_ELFFL | eh.elf32.e_machine;

	} else if (!elf64_chk_header(&eh.elf64)) {
		Elf64_Sym sbuf;
		char *shstr;
		Elf64_Shdr *shdr;
		size_t stabsize;

		elf64_fix_header(&eh.elf64);
		if (eh.elf64.e_ehsize < sizeof eh.elf64) {
			warnx("%s: ELF header is too short", archive);
			goto bad;
		}

		if (!(shdr = elf64_load_shdrs(archive, rfp, r_off, &eh.elf64)))
			goto bad;
		elf64_fix_shdrs(&eh.elf64, shdr);

		if (!(shstr = elf64_shstrload(archive, rfp, r_off, &eh.elf64,
		    shdr))) {
			free(shdr);
			goto bad;
		}

		if (!(strtab = elf64_strload(archive, rfp, r_off, &eh.elf64,
		    shdr, shstr, ELF_STRTAB, &stabsize))) {
			free(shstr);
			free(shdr);
			goto bad;
		}

		/* find the symtab section */
		for (i = 0; i < eh.elf64.e_shnum; i++)
			if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {
				nsyms = shdr[i].sh_size / sizeof(Elf64_Sym);
				break;
			}

		if (i == eh.elf64.e_shnum) {
			free(shstr);
			free(shdr);
			goto bad;
		}

		if (fseeko(rfp, r_off + shdr[i].sh_offset, SEEK_SET))
			err(1, "fseeko: %s", archive);

		for (i = 0; i < nsyms; i++) {
			if (fread(&sbuf, sizeof(sbuf), 1, rfp) != 1)
				err(1, "fread: %s", archive);

			elf64_fix_sym(&eh.elf64, &sbuf);
			if (!sbuf.st_name || sbuf.st_name > stabsize)
				continue;

			if (elf64_2nlist(&sbuf, &eh.elf64, shdr, shstr, &nl))
				continue;

			addsym(&nl, strtab, r_off - r_fuzz -
			    sizeof(struct ar_hdr), symcnt, tsymlen, archive);
		}

		free(strtab);
		free(shstr);
		free(shdr);
		(void)fseeko(rfp, r_off, SEEK_SET);
		return MID_ELFFL | eh.elf64.e_machine;

	} else if (BAD_OBJECT(eh.exec) || eh.exec.a_syms == 0)
		goto bad;

	fix_header_order(&eh.exec);

	/* Seek to string table. */
	if (fseeko(rfp, N_STROFF(eh.exec) + r_off, SEEK_SET) == -1) {
		if (errno == EINVAL)
			goto bad;
		else
			err(1, "lseek: %s", archive);
	}

	/* Read in size of the string table. */
	if (fread((char *)&strsize, sizeof(strsize), 1, rfp) != 1)
		err(1, "fread: %s", archive);

	strsize = fix_32_order(strsize, N_GETMID(eh.exec));

	/* Read in the string table. */
	strsize -= sizeof(strsize);
	strtab = malloc(strsize);
	if (!strtab)
		err(1, "malloc: %s", archive);
	if (fread(strtab, strsize, 1, rfp) != 1)
		err(1, "fread: %s", archive);

	/* Seek to symbol table. */
	if (fseek(rfp, N_SYMOFF(eh.exec) + r_off, SEEK_SET) == (off_t)-1)
		err(1, "fseeko: %s", archive);

	/* For each symbol read the nlist entry and save it as necessary. */
	nsyms = eh.exec.a_syms / sizeof(struct nlist);
	while (nsyms--) {
		if (!fread((char *)&nl, sizeof(struct nlist), 1, rfp)) {
			if (feof(rfp))
				badfmt();
			err(1, "fread: %s", archive);
		}
		fix_nlist_order(&nl, N_GETMID(eh.exec));

		addsym(&nl, strtab - sizeof(long), r_off - r_fuzz -
		    sizeof(struct ar_hdr), symcnt, tsymlen, archive);
	}

bad:
	free(strtab);
	(void)fseeko(rfp, r_off, SEEK_SET);
	return N_GETMID(eh.exec);
}
Esempio n. 17
0
static const bfd_target *
aout_adobe_callback (bfd *abfd)
{
  struct internal_exec *execp = exec_hdr (abfd);
  asection *sect;
  struct external_segdesc ext[1];
  char *section_name;
  char try_again[30];	/* Name and number.  */
  char *newname;
  int trynum;
  flagword flags;

  /* Architecture and machine type -- unknown in this format.  */
  bfd_set_arch_mach (abfd, bfd_arch_unknown, 0L);

  /* The positions of the string table and symbol table.  */
  obj_str_filepos (abfd) = N_STROFF (*execp);
  obj_sym_filepos (abfd) = N_SYMOFF (*execp);

  /* Suck up the section information from the file, one section at a time.  */
  for (;;)
    {
      bfd_size_type amt = sizeof (*ext);
      if (bfd_bread ( ext, amt, abfd) != amt)
	{
	  if (bfd_get_error () != bfd_error_system_call)
	    bfd_set_error (bfd_error_wrong_format);

	  return NULL;
	}
      switch (ext->e_type[0])
	{
	case N_TEXT:
	  section_name = ".text";
	  flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
	  break;

	case N_DATA:
	  section_name = ".data";
	  flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
	  break;

	case N_BSS:
	  section_name = ".bss";
	  flags = SEC_DATA | SEC_HAS_CONTENTS;
	  break;

	case 0:
	  goto no_more_sections;

	default:
	  (*_bfd_error_handler)
	    (_("%B: Unknown section type in a.out.adobe file: %x\n"),
	     abfd, ext->e_type[0]);
	  goto no_more_sections;
	}

      /* First one is called ".text" or whatever; subsequent ones are
	 ".text1", ".text2", ...  */
      bfd_set_error (bfd_error_no_error);
      sect = bfd_make_section_with_flags (abfd, section_name, flags);
      trynum = 0;

      while (!sect)
	{
	  if (bfd_get_error () != bfd_error_no_error)
	    /* Some other error -- slide into the sunset.  */
	    return NULL;
	  sprintf (try_again, "%s%d", section_name, ++trynum);
	  sect = bfd_make_section_with_flags (abfd, try_again, flags);
	}

      /* Fix the name, if it is a sprintf'd name.  */
      if (sect->name == try_again)
	{
	  amt = strlen (sect->name);
	  newname = bfd_zalloc (abfd, amt);
	  if (newname == NULL)
	    return NULL;
	  strcpy (newname, sect->name);
	  sect->name = newname;
	}

      /* Assumed big-endian.  */
      sect->size = ((ext->e_size[0] << 8)
		    | ext->e_size[1] << 8
		    | ext->e_size[2]);
      sect->vma = H_GET_32 (abfd, ext->e_virtbase);
      sect->filepos = H_GET_32 (abfd, ext->e_filebase);
      /* FIXME XXX alignment?  */

      /* Set relocation information for first section of each type.  */
      if (trynum == 0)
	switch (ext->e_type[0])
	  {
	  case N_TEXT:
	    sect->rel_filepos = N_TRELOFF (*execp);
	    sect->reloc_count = execp->a_trsize;
	    break;

	  case N_DATA:
	    sect->rel_filepos = N_DRELOFF (*execp);
	    sect->reloc_count = execp->a_drsize;
	    break;

	  default:
	    break;
	  }
    }
 no_more_sections:

  adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
  adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
  adata (abfd).page_size = 1; /* Not applicable.  */
  adata (abfd).segment_size = 1; /* Not applicable.  */
  adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;

  return abfd->xvec;
}
Esempio n. 18
0
int main (int argc, char *argv[]) {
  register struct nlist *s;
  register caddr_t strtab;
  register off_t stroff, symoff;
  register u_long symsize;
  register int cc;
  size_t strsize;
  struct nlist nbuf[1024];
  struct exec exec;
  struct stat st;
  int fd;
  int pageOffset;

  if ((fd = open (argv[1], O_RDONLY)) < 0) {
    fprintf (stderr, "could not open %s\n", argv[1]);
    return -1;
  }
  if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
      read(fd, &exec, sizeof(exec)) != sizeof(exec) ||
      fstat(fd, &st) < 0) {
    fprintf (stderr, "Invalid binary file\n");
    return -1;
  }
  if (N_BADMAG (exec) || N_GETMID (exec) != MID_I386) {
    fprintf (stderr, "invalid executable file N_BADMAG(exec) %d N_GETMID (exec) %d MID_I386 %d\n", N_BADMAG(exec), N_GETMID(exec), MID_I386);
    exit (1);
  }
  if (N_GETFLAG (exec) & EX_DYNAMIC) {
    fprintf (stderr, "are you giving me a dynamically linked executable??\n");
    return -1;
  }
  symoff = N_SYMOFF(exec);
  symsize = exec.a_syms;
  stroff = symoff + symsize;

#ifndef __linux__
  /* Check for files too large to mmap. */
  if (st.st_size - stroff > SIZE_T_MAX) {
    fprintf (stderr, "file too large\n");
    return -1;
  }
#endif

  /*
   * Map string table into our address space.  This gives us
   * an easy way to randomly access all the strings, without
   * making the memory allocation permanent as with malloc/free
   * (i.e., munmap will return it to the system).
   */
  strsize = st.st_size - stroff;
  pageOffset = stroff % 4096;
  stroff -= pageOffset;
  strsize += pageOffset;

  strtab = mmap(NULL, (size_t)strsize, PROT_READ, MAP_SHARED, fd, stroff);
  if (strtab == (char *)-1) {
    warn ("could not mmap string table");
    return -1;
  }
  strtab += pageOffset;
  strsize -= pageOffset;

  if (lseek(fd, symoff, SEEK_SET) == -1) {
    fprintf (stderr, "could not lseek to symbol table\n");
    return -1;
  }

  while (symsize > 0) {
    int i;
    cc = my_min(symsize, sizeof(nbuf));
    if (read(fd, nbuf, cc) != cc)
      break;
    symsize -= cc;
    for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
      register int soff = s->n_un.n_strx;

      if (soff == 0 || (s->n_type & N_STAB) != 0)
        continue;
      for (i = 0; exclude[i]; i++) {
        if (!strcmp (&strtab[soff], exclude[i]))
          goto skip;
      }
      /* hack to avoid symbol with name equal to tmp filename used
         to build us */
      if (strchr (&strtab[soff], '.') || strchr (&strtab[soff], '/'))
        goto skip;
      if (s->n_type & N_EXT) {
        printf ("\t.globl\t%s\n\t.set\t%s,0x%lx\n\t.weak\t%s\n\n",
                &strtab[soff], &strtab[soff], s->n_value, &strtab[soff]);
      }
    skip:
      ;
    }
  }
  munmap(strtab, strsize);
  return 0;
}
Esempio n. 19
0
main(int ac,char *av[])
{	const char *aoutfile;
	FILE *aout;
	struct exec exec;
	struct nlist nlist;
	int nsyms,si,soff;
	int nrels;

	if( ac < 2 ){
		fprintf(stderr,"Usage: %s a.out-filename\n",av[0]);
		exit(1);
	}
	aoutfile = av[1];
	aout = fopen(aoutfile,"r+");
	if( aout == NULL ){
		fprintf(stderr,"Cannot open %s\n",aoutfile);
		exit(1);
	}
	fread(&exec,1,sizeof(exec),aout);
	if( N_BADMAG(exec) ){
		fprintf(stderr,"%s: not a a.out file\n",aoutfile);
		exit(1);
	}
	if( exec.a_text != 0 ){
		if( exec.a_data )
			fprintf(stderr,"cannot move data to text.\n");
		else	fprintf(stderr,"no data segment.\n");
		exit(1);
	}

	fprintf(stderr,"%6d text\n",exec.a_text);
	fprintf(stderr,"%6d data\n",exec.a_data);
	nsyms = exec.a_syms/sizeof(struct nlist);
	fprintf(stderr,"%6d syms\n",nsyms);
	fprintf(stderr,"%6d drels\n",exec.a_drsize);
	if( exec.a_drsize ){
		fprintf(stderr,"cannot move data with relocation.\n");
		exit(1);
	}

	fseek(aout,N_SYMOFF(exec),0);
	for( si = 0; si < nsyms; si++ ){
		soff = ftell(aout);
		fread(&nlist,1,sizeof(struct nlist),aout);
		if( nlist.n_type & N_DATA ){
			nlist.n_type = (nlist.n_type & ~N_DATA) | N_TEXT;
			fseek(aout,soff,0);
			fwrite(&nlist,1,sizeof(struct nlist),aout);
			fflush(aout);
		}
	}

	exec.a_text = exec.a_data;
	exec.a_data = 0;
	fseek(aout,0,0);
	fwrite(&exec,1,sizeof(exec),aout);
	fflush(aout);

	fclose(aout);
	fprintf(stderr,"%d bytes of data moved to text segment.\n",exec.a_text);
	exit(0);
}
Esempio n. 20
0
int
__aout_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p, *symtab;
	caddr_t strtab, a_out_mmap;
	off_t stroff, symoff;
	u_long symsize;
	int nent;
	struct exec * exec;
	struct stat st;

	/* check that file is at least as large as struct exec! */
	if ((_fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec)))
		return (-1);

	/* Check for files too large to mmap. */
	if (st.st_size > SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}

	/*
	 * Map the whole a.out file into our address space.
	 * We then find the string table withing this area.
	 * We do not just mmap the string table, as it probably
	 * does not start at a page boundary - we save ourselves a
	 * lot of nastiness by mmapping the whole file.
	 *
	 * This gives us an easy way to randomly access all the strings,
	 * without making the memory allocation permanent as with
	 * malloc/free (i.e., munmap will return it to the system).
	 */
	a_out_mmap = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0);
	if (a_out_mmap == MAP_FAILED)
		return (-1);

	exec = (struct exec *)a_out_mmap;
	if (N_BADMAG(*exec)) {
		munmap(a_out_mmap, (size_t)st.st_size);
		return (-1);
	}

	symoff = N_SYMOFF(*exec);
	symsize = exec->a_syms;
	stroff = symoff + symsize;

	/* find the string table in our mmapped area */
	strtab = a_out_mmap + stroff;
	symtab = (struct nlist *)(a_out_mmap + symoff);

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * XXX clearing anything other than n_type and n_value violates
	 * the semantics given in the man page.
	 */
	nent = 0;
	for (p = list; !ISLAST(p); ++p) {
		p->n_type = 0;
		p->n_other = 0;
		p->n_desc = 0;
		p->n_value = 0;
		++nent;
	}

	while (symsize > 0) {
		int soff;

		symsize-= sizeof(struct nlist);
		soff = symtab->n_un.n_strx;


		if (soff != 0 && (symtab->n_type & N_STAB) == 0)
			for (p = list; !ISLAST(p); p++)
				if (!strcmp(&strtab[soff], p->n_un.n_name)) {
					p->n_value = symtab->n_value;
					p->n_type = symtab->n_type;
					p->n_desc = symtab->n_desc;
					p->n_other = symtab->n_other;
					if (--nent <= 0)
						break;
				}
		symtab++;
	}
	munmap(a_out_mmap, (size_t)st.st_size);
	return (nent);
}
Esempio n. 21
0
setsym()
{
	off_t loc;
	struct exec hdr;
	register struct nlist *sp;
	int ssiz;
	char *strtab;

	fsym = getfile(symfil, 1);
	txtmap.ufd = fsym;
	if (read(fsym, (char *)&hdr, sizeof hdr) != sizeof hdr ||
	    N_BADMAG(hdr)) {
		txtmap.e1 = MAXFILE;
		return;
	}
	filhdr = hdr;
	loc = filhdr.a_text+filhdr.a_data;
	txtmap.f1 = txtmap.f2 = N_TXTOFF(filhdr);
	txtmap.b1 = 0;
	switch (filhdr.a_magic) {

	case OMAGIC:
		txtmap.b1 = txtmap.e1 = 0;
		txtmap.b2 = datbas = 0;
		txtmap.e2 = loc;
		break;

	case ZMAGIC:
	case NMAGIC:
		txtmap.e1 = filhdr.a_text;
		txtmap.b2 = datbas = round(filhdr.a_text, PAGSIZ);
		txtmap.e2 = datbas + filhdr.a_data;
		txtmap.f2 += txtmap.e1;
	}
	loc = N_SYMOFF(filhdr);
	symtab = (struct nlist *) malloc(filhdr.a_syms);
	esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)];
	if (symtab == NULL)
		goto nospac;
	lseek(fsym, loc, L_SET);
	if (filhdr.a_syms == 0)
		goto nosymt;
	/* SHOULD SQUISH OUT STABS HERE!!! */
	if (read(fsym, symtab, filhdr.a_syms) != filhdr.a_syms)
		goto readerr;
	if (read(fsym, &ssiz, sizeof (ssiz)) != sizeof (ssiz))
		goto oldfmt;
	strtab = (char *) malloc(ssiz);
	if (strtab == 0)
		goto nospac;
	*(int *)strtab = ssiz;
	ssiz -= sizeof (ssiz);
	if (read(fsym, strtab + sizeof (ssiz), ssiz) != ssiz)
		goto readerr;
	for (sp = symtab; sp < esymtab; sp++)
		if (sp->n_strx)
			/* SHOULD PERFORM RANGE CHECK HERE */
			sp->n_un.n_name = strtab + sp->n_un.n_strx;
nosymt:
	if (INKERNEL(filhdr.a_entry)) {
		txtmap.b1 += KERNOFF;
		txtmap.e1 += KERNOFF;
		txtmap.b2 += KERNOFF;
		txtmap.e2 += KERNOFF;
	}
	return;
readerr:
	printf("Error reading symbol|string table\n");
	exit(1);
nospac:
	printf("Not enough space for symbol|string table\n");
	exit(1);
oldfmt:
	printf("Old format a.out - no string table\n");
	exit(1);
}
Esempio n. 22
0
static
#endif
void
dump_file(const char *fname)
{
    int fd;
    struct stat sb;
    caddr_t objbase;

    if (stat(fname, &sb) == -1) {
	warnx("cannot stat \"%s\"", fname);
	++error_count;
	return;
    }

    if ((sb.st_mode & S_IFMT) != S_IFREG) {
	warnx("\"%s\" is not a regular file", fname);
	++error_count;
	return;
    }

    if ((fd = open(fname, O_RDONLY, 0)) == -1) {
	warnx("cannot open \"%s\"", fname);
	++error_count;
	return;
    }

    objbase = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (objbase == (caddr_t) -1) {
	warnx("cannot mmap \"%s\"", fname);
	++error_count;
	close(fd);
	return;
    }

    close(fd);

    file_base = (const char *) objbase;	/* Makes address arithmetic easier */

    if (IS_ELF(*(const Elf32_Ehdr*) align_struct(file_base))) {
	warnx("%s: this is an ELF program; use objdump to examine", fname);
	++error_count;
	munmap(objbase, sb.st_size);
	return;
    }

    ex = (const struct exec *) align_struct(file_base);

    printf("%s: a_midmag = 0x%lx\n", fname, (long)ex->a_midmag);
    printf("  magic = 0x%lx = 0%lo, netmagic = 0x%lx = 0%lo\n",
	(long)N_GETMAGIC(*ex), (long)N_GETMAGIC(*ex),
	(long)N_GETMAGIC_NET(*ex), (long)N_GETMAGIC_NET(*ex));

    if (N_BADMAG(*ex)) {
	warnx("%s: bad magic number", fname);
	++error_count;
	munmap(objbase, sb.st_size);
	return;
    }

    printf("  a_text   = 0x%lx\n", (long)ex->a_text);
    printf("  a_data   = 0x%lx\n", (long)ex->a_data);
    printf("  a_bss    = 0x%lx\n", (long)ex->a_bss);
    printf("  a_syms   = 0x%lx\n", (long)ex->a_syms);
    printf("  a_entry  = 0x%lx\n", (long)ex->a_entry);
    printf("  a_trsize = 0x%lx\n", (long)ex->a_trsize);
    printf("  a_drsize = 0x%lx\n", (long)ex->a_drsize);

    text_base = file_base + N_TXTOFF(*ex);
    data_base = file_base + N_DATOFF(*ex);
    rel_base = (const struct relocation_info *)
	align_struct(file_base + N_RELOFF(*ex));
    sym_base = (const struct nlist *) align_struct(file_base + N_SYMOFF(*ex));
    str_base = file_base + N_STROFF(*ex);

    rel_count = (ex->a_trsize + ex->a_drsize) / sizeof rel_base[0];
    assert(rel_count * sizeof rel_base[0] == ex->a_trsize + ex->a_drsize);
    sym_count = ex->a_syms / sizeof sym_base[0];
    assert(sym_count * sizeof sym_base[0] == ex->a_syms);

    if (sym_count != 0) {
	sym_used = (unsigned char *) calloc(sym_count, sizeof(unsigned char));
	assert(sym_used != NULL);
    }

    printf("  Entry = 0x%lx\n", (long)ex->a_entry);
    printf("  Text offset = %x, address = %lx\n", N_TXTOFF(*ex),
	(long)N_TXTADDR(*ex));
    printf("  Data offset = %lx, address = %lx\n", (long)N_DATOFF(*ex),
	(long)N_DATADDR(*ex));

    /*
     * In an executable program file, everything is relocated relative to
     * the assumed run-time load address, i.e., N_TXTADDR(*ex), i.e., 0x1000.
     *
     * In a shared library file, everything is relocated relative to the
     * start of the file, i.e., N_TXTOFF(*ex), i.e., 0.
     *
     * The way to tell the difference is by looking at ex->a_entry.   If it
     * is >= 0x1000, then we have an executable program.  Otherwise, we
     * have a shared library.
     *
     * When a program is executed, the entire file is mapped into memory,
     * including the a.out header and so forth.  But it is not mapped at
     * address 0; rather it is mapped at address 0x1000.  The first page
     * of the user's address space is left unmapped in order to catch null
     * pointer dereferences.
     *
     * In this program, when we map in an executable program, we have to
     * simulate the empty page by decrementing our assumed base address by
     * a pagesize.
     */

    text_addr = text_base;
    data_addr = data_base;
    origin = 0;

    if (ex->a_entry >= PAGE_SIZE) {	/* Executable, not a shared library */
	/*
	 * The fields in the object have already been relocated on the
	 * assumption that the object will be loaded at N_TXTADDR(*ex).
	 * We have to compensate for that.
	 */
	text_addr -= PAGE_SIZE;
	data_addr -= PAGE_SIZE;
	origin = PAGE_SIZE;
	printf("  Program, origin = %lx\n", origin);
    } else if (N_GETFLAG(*ex) & EX_DYNAMIC)
	printf("  Shared library, origin = %lx\n", origin);
    else
	printf("  Object file, origin = %lx\n", origin);

    if (N_GETFLAG(*ex) & EX_DYNAMIC) {
	dyn = (const struct _dynamic *) align_struct(data_base);
	printf("  Dynamic version = %d\n", dyn->d_version);

	sdt = (const struct section_dispatch_table *)
	    align_struct(text_addr + (unsigned long) dyn->d_un.d_sdt);

	rtrel_base = (const struct relocation_info *)
	    align_struct(text_addr + sdt->sdt_rel);
	rtrel_count = (sdt->sdt_hash - sdt->sdt_rel) / sizeof rtrel_base[0];
	assert(rtrel_count * sizeof rtrel_base[0] ==
	    (size_t)(sdt->sdt_hash - sdt->sdt_rel));

	rtsym_base = (const struct nzlist *)
	    align_struct(text_addr + sdt->sdt_nzlist);
	rtsym_count = (sdt->sdt_strings - sdt->sdt_nzlist) /
	    sizeof rtsym_base[0];
	assert(rtsym_count * sizeof rtsym_base[0] ==
	    (size_t)(sdt->sdt_strings - sdt->sdt_nzlist));

	if (rtsym_count != 0) {
	    rtsym_used = (unsigned char *) calloc(rtsym_count,
		sizeof(unsigned char));
	    assert(rtsym_used != NULL);
	}

	rtstr_base = text_addr + sdt->sdt_strings;
    }

    dump_segs();
    dump_sods();
    dump_rels("Relocations", rel_base, rel_count, sym_name, sym_used);
    dump_syms();

    dump_rels("Run-time relocations", rtrel_base, rtrel_count, rtsym_name,
	rtsym_used);
    dump_rtsyms();

    if (rtsym_used != NULL) {
	free(rtsym_used);
	rtsym_used = NULL;
    }
    if (sym_used != NULL) {
	free(sym_used);
	sym_used = NULL;
    }
    munmap(objbase, sb.st_size);
}
Esempio n. 23
0
void
a_out_mod_symload(int strtablen)
{
	struct exec info_buf;
	struct lmc_loadbuf ldbuf;
	struct nlist *nlp;
	char buf[10 * BUFSIZ];
	char *symbuf;
	int bytesleft, sz;
	int numsyms;	/* XXX unused? */

	if (a_out_read_header(modfd, &info_buf) < 0)
		return;

	/*
	 * Seek to the symbol table to start loading it...
	 */
	if (lseek(modfd, N_SYMOFF(info_buf), SEEK_SET) == -1)
		err(12, "lseek");

	/*
	 * Transfer the symbol table entries.  First, read them all in,
	 * then adjust their string table pointers, then
	 * copy in bulk.  Then copy the string table itself.
	 */

	symbuf = malloc(info_buf.a_syms);
	if (symbuf == 0)
		err(13, "malloc");

	if (read(modfd, symbuf, info_buf.a_syms) != info_buf.a_syms)
		err(14, "read");
	numsyms = info_buf.a_syms / sizeof(struct nlist);

	for (nlp = (struct nlist *)symbuf;
	    (char *)nlp < symbuf + info_buf.a_syms; nlp++) {
		int strx;

		strx = nlp->n_un.n_strx;
		if (strx != 0) {
			/*
			 * If a valid name, set the name ptr to point at the
			 * loaded address for the string in the string table.
			 */
			if (strx > strtablen)
				nlp->n_un.n_name = 0;
			else
				nlp->n_un.n_name = (char *)(strx +
				    resrv.sym_addr + info_buf.a_syms);
		}
	}
	/*
	 * we've fixed the symbol table entries, now load them
	 */
	for (bytesleft = info_buf.a_syms; bytesleft > 0; bytesleft -= sz) {
		sz = MIN(bytesleft, MODIOBUF);
		ldbuf.cnt = sz;
		ldbuf.data = symbuf;
		if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
			err(11, "error transferring sym buffer");
		symbuf += sz;
	}

	free(symbuf - info_buf.a_syms);
	/* and now read the string table and load it. */
	for (bytesleft = strtablen; bytesleft > 0; bytesleft -= sz) {
		sz = MIN(bytesleft, MODIOBUF);
		read(modfd, buf, sz);
		ldbuf.cnt = sz;
		ldbuf.data = buf;
		if (ioctl(devfd, LMLOADSYMS, &ldbuf) == -1)
			err(11, "error transferring stringtable buffer");
	}
}
Esempio n. 24
0
int main(int ac, char **av)
{
	FILE *fin = NULL;
	struct exec *exhdr = NULL;
	char *fname = NULL;
	char *stringtable;
	int   strtbl_sz;
	struct relocation_info *data_reloc = NULL, *text_reloc = NULL;
	struct nlist *symbol_table = NULL;
	int show_header       = 0;
	int show_data_reloc   = 0;
	int show_text_reloc   = 0;
	int show_symbol_table = 0;
	int print_symnames    = 1;
	int correspondence    = 0;
	int hdr_info          = 0;
	int opt;

	while (-1 != (opt = getopt(ac, av, "hdtsacxn"))) {
		switch (opt) {
		case 'h': show_header = 1; break;
		case 'x': show_header = hdr_info = 1; break;  /* show_header implied */
		case 'd': show_data_reloc = 1; break;
		case 't': show_text_reloc = 1; break;
		case 's': show_symbol_table = 1; break;
		case 'c': correspondence = 1; break;
		case 'n': print_symnames = 0; break;
		case 'a':
			show_header = show_data_reloc = show_text_reloc = show_symbol_table = correspondence = hdr_info = 1;
			break;
		default: errout:
			fprintf(stderr, "%s: show exec header, relocation and symbol table data\n", av[0]);
			fprintf(stderr, "usage: %s [-h] [-d] [-t] [-s] [-c] [-x] [-a] <filename>\n", av[0]);
			fprintf(stderr, " -h: show exec header\n"
				" -x: show info derivable from exec header \n"
				" -d: show data segment relocations\n"
				" -t: show text segment relocations\n"
				" -c: show symbols that correspond to relocations\n"
				" -s: show symbol table\n"
				" -n: when showing symbol table, don't print symbol names\n"
				" -a: show it all\n");
			return 1;
			break;
		}
	}

	if (0 == show_header && 0 == show_data_reloc && 0 == show_text_reloc &&
		0 == show_symbol_table)
			show_header = show_data_reloc = show_text_reloc = show_symbol_table = correspondence = 1;

	if (optind < ac)
		fname = av[optind];

	if (NULL == fname) {
		fprintf(stderr, "Need a file to examine\n");
		goto errout;
	}

	if (NULL == (fin = fopen(fname, "r"))) {
		fprintf(stderr, "Couldn't open \"%s\" for reading: %s\n",
			fname, strerror(errno));
		return 1;
	}

	if (stat(fname, &attributes) < 0) {
		fprintf(stderr, "Problem on stat(2) of \"%s\": %s\n",
			fname, strerror(errno));
		fclose(fin);
		return 1;
	}

	exhdr = (struct exec *)read_extent(fin, sizeof(*exhdr), 0, __LINE__);

	if (NULL == exhdr) {
		cleanup(fin, 1, exhdr);
		return 2;
	}

	if (show_header) {
		puts("a.out header:");
		run_header(exhdr, hdr_info);
	}

	if (N_BADMAG(*exhdr)) {
		fprintf(stderr, "%s isn't a recognized NetBSD a.out file\n", fname);
		cleanup(fin, 1, exhdr);
		return 3;
	}

	stringtable  = read_stringtable(fin, exhdr, &strtbl_sz);
	data_reloc   = (struct relocation_info *)read_extent(fin, exhdr->a_drsize, N_DRELOFF(*exhdr), __LINE__);
	text_reloc   = (struct relocation_info *)read_extent(fin, exhdr->a_trsize, N_TRELOFF(*exhdr), __LINE__);
	symbol_table = (struct nlist *)          read_extent(fin, exhdr->a_syms,   N_SYMOFF(*exhdr), __LINE__);

	if (show_data_reloc) {
		puts("\nData relocations:");
		run_reloc(exhdr, exhdr->a_drsize, data_reloc, symbol_table, stringtable, strtbl_sz, correspondence);
	}

	if (show_text_reloc) {
		puts("\nText relocations:");
		run_reloc(exhdr, exhdr->a_trsize, text_reloc, symbol_table, stringtable, strtbl_sz, correspondence);
	}

	if (show_symbol_table) {
		puts("\nSymbol table:");
		run_symtable(exhdr, symbol_table, stringtable, strtbl_sz, print_symnames);
	}

	cleanup(fin, 5, exhdr, stringtable, data_reloc, text_reloc, symbol_table);

	return 0;
}
Esempio n. 25
0
int util_save_image(char *orig_file_name, char *save_file_name)
{
    int origFd = -1, saveFd = -1;
    char *start_data, *end_data, *start_text, *end_round;
    struct exec old_hdr, new_hdr;
    struct stat old_stat;
    int n, page_size, length_text, length_data;

    if ((origFd = open(orig_file_name, 0)) < 0) {
	perror(orig_file_name);
	(void) fprintf(stderr, "Cannot open original a.out file\n");
	goto bad;
    }

    if (fstat(origFd, &old_stat) < 0) {
	perror(orig_file_name);
	(void) fprintf(stderr, "Cannot stat original a.out file\n");
	goto bad;
    }

    /*
     * Read the a.out header from the original file.
     */
    if (read(origFd, (char *) &old_hdr, sizeof(old_hdr)) != sizeof(old_hdr)) {
	perror(orig_file_name);
	(void) fprintf(stderr, "Cannot read original a.out header\n");
	goto bad;
    }
    if (N_BADMAG(old_hdr)) {
	(void) fprintf(stderr, "File %s has a bad magic number (%o)\n",
			orig_file_name, old_hdr.a_magic);
	goto bad;
    }
    if (old_hdr.a_magic != ZMAGIC) {
	(void) fprintf(stderr, "File %s is not demand-paged\n", orig_file_name);
	goto bad;
    }

    /*
     * Open the output file.
     */
    if (access(save_file_name, /* F_OK */ 0) == 0) {
	(void) unlink(save_file_name);
    }
    if ((saveFd = creat(save_file_name, 0777)) < 0) {
	if (errno == ETXTBSY) {
	    (void) unlink(save_file_name);
	    saveFd = creat(save_file_name, 0777);
	}
	if (saveFd < 0) {
	    perror(save_file_name);
	    (void) fprintf(stderr, "Cannot create save file.\n");
	    goto bad;
	}
    }

    /*
     * Find out how far the data segment extends.
     */
    new_hdr = old_hdr;
    end_data = sbrk(0);
    page_size = getpagesize();
    n = ((((int) end_data) + page_size - 1) / page_size) * page_size;
    end_round = (char *) n;
    if (end_round > end_data) {
	end_data = sbrk(end_round - end_data);
    }

#ifdef vax
    start_text = 0;
    length_text = new_hdr.a_text;
    start_data = (char *) old_hdr.a_text;
    length_data = end_data - start_data;
#endif vax
#ifdef	sun
    start_text = (char *) N_TXTADDR(old_hdr) + sizeof(old_hdr);
    length_text = old_hdr.a_text - sizeof(old_hdr);
    start_data = (char *) N_DATADDR(old_hdr);
    length_data = end_data - start_data;
#endif	sun
    new_hdr.a_data = end_data - start_data;
    new_hdr.a_bss = 0;

    /*
     * First, the header plus enough pad to extend up to N_TXTOFF.
     */
    if (write(saveFd, (char *) &new_hdr, (int) sizeof(new_hdr)) !=
				sizeof(new_hdr)) {
	perror("write");
	(void) fprintf(stderr, "Error while copying header.\n");
	goto bad;
    }
    if (! pad_file(saveFd, N_TXTOFF(old_hdr) - sizeof(new_hdr))) {
	(void) fprintf(stderr, "Error while padding.\n");
	goto bad;
    }


    /*
     *  Copy our text segment
     */
    if (write(saveFd, start_text, length_text) != length_text) {
	perror("write");
	(void) fprintf(stderr, "Error while copying text segment.\n");
	goto bad;
    }


    /*
     *  Copy our data segment
     */
    if (write(saveFd, start_data, length_data) != length_data) {
	perror("write");
	(void) fprintf(stderr, "Error while copying data segment.\n");
	goto bad;
    }

    /*
     * Copy the symbol table and everything else.
     * This takes us to the end of the original file.
     */
    (void) lseek(origFd, (long) N_SYMOFF(old_hdr), 0);
    if (! copy_file(origFd, saveFd, old_stat.st_size - N_SYMOFF(old_hdr))) {
	(void) fprintf(stderr, "Error while copying symbol table.\n");
	goto bad;
    }
    (void) close(origFd);
    (void) close(saveFd);
    return 1;

bad:
    if (origFd >= 0) (void) close(origFd);
    if (saveFd >= 0) (void) close(saveFd);
    return 0;
}
Esempio n. 26
0
static bfd_boolean
aout_adobe_write_object_contents (bfd *abfd)
{
  struct external_exec swapped_hdr;
  static struct external_segdesc sentinel[1];	/* Initialized to zero.  */
  asection *sect;
  bfd_size_type amt;

  exec_hdr (abfd)->a_info = ZMAGIC;

  /* Calculate text size as total of text sections, etc.  */
  exec_hdr (abfd)->a_text = 0;
  exec_hdr (abfd)->a_data = 0;
  exec_hdr (abfd)->a_bss  = 0;
  exec_hdr (abfd)->a_trsize = 0;
  exec_hdr (abfd)->a_drsize = 0;

  for (sect = abfd->sections; sect; sect = sect->next)
    {
      if (sect->flags & SEC_CODE)
	{
	  exec_hdr (abfd)->a_text += sect->size;
	  exec_hdr (abfd)->a_trsize += sect->reloc_count *
	    sizeof (struct reloc_std_external);
	}
      else if (sect->flags & SEC_DATA)
	{
	  exec_hdr (abfd)->a_data += sect->size;
	  exec_hdr (abfd)->a_drsize += sect->reloc_count *
	    sizeof (struct reloc_std_external);
	}
      else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD))
	exec_hdr (abfd)->a_bss += sect->size;
    }

  exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
    * sizeof (struct external_nlist);
  exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);

  aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);

  amt = EXEC_BYTES_SIZE;
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
      || bfd_bwrite (& swapped_hdr, amt, abfd) != amt)
    return FALSE;

  /* Now write out the section information.  Text first, data next, rest
     afterward.  */
  for (sect = abfd->sections; sect; sect = sect->next)
    if (sect->flags & SEC_CODE)
      aout_adobe_write_section (abfd, sect);

  for (sect = abfd->sections; sect; sect = sect->next)
    if (sect->flags & SEC_DATA)
      aout_adobe_write_section (abfd, sect);

  for (sect = abfd->sections; sect; sect = sect->next)
    if (!(sect->flags & (SEC_CODE | SEC_DATA)))
      aout_adobe_write_section (abfd, sect);

  /* Write final `sentinel` section header (with type of 0).  */
  amt = sizeof (*sentinel);
  if (bfd_bwrite (sentinel, amt, abfd) != amt)
    return FALSE;

  /* Now write out reloc info, followed by syms and strings.  */
  if (bfd_get_symcount (abfd) != 0)
    {
      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      if (! aout_32_write_syms (abfd))
	return FALSE;

      if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      for (sect = abfd->sections; sect; sect = sect->next)
	if (sect->flags & SEC_CODE)
	  if (!aout_32_squirt_out_relocs (abfd, sect))
	    return FALSE;

      if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*exec_hdr (abfd))), SEEK_SET)
	  != 0)
	return FALSE;

      for (sect = abfd->sections; sect; sect = sect->next)
	if (sect->flags & SEC_DATA)
	  if (!aout_32_squirt_out_relocs (abfd, sect))
	    return FALSE;
    }

  return TRUE;
}
Esempio n. 27
0
void
run_header(struct exec *exhdr, int extended_info)
{
	char *id = NULL;

	assert(NULL != exhdr);

	/* print raw values */
	printf(
		"\ta_midmag 0x%08x (mid %d, magic 0%o, flag 0x%x)\n"
		"\ta_text   0x%08x\n"
		"\ta_data   0x%08x\n"
		"\ta_bss    0x%08x\n"
		"\ta_syms   0x%08x\n"
		"\ta_entry  0x%08x\n"
		"\ta_trsize 0x%08x\n"
		"\ta_drsize 0x%08x\n",
		exhdr->a_midmag,
		N_GETMID(*exhdr), N_GETMAGIC(*exhdr), N_GETFLAG(*exhdr),
		exhdr->a_text,
		exhdr->a_data,
		exhdr->a_bss,
		exhdr->a_syms,
		exhdr->a_entry,
		exhdr->a_trsize,
		exhdr->a_drsize
	);

	printf(
		"magic number %04o: %s\n", N_GETMAGIC(*exhdr),
		N_GETMAGIC(*exhdr) == OMAGIC ?  "old impure format" :
		N_GETMAGIC(*exhdr) == NMAGIC ?  "read-only text" :
		N_GETMAGIC(*exhdr) == ZMAGIC ?  "demand load format" :
		N_GETMAGIC(*exhdr) == QMAGIC ?  "deprecated format" :
		"totally funky"
	);

	switch (N_GETMID(*exhdr)) {
	case MID_ZERO:    id = "unknown - implementation dependent"; break;
	case MID_SUN010:  id = "sun 68010/68020 binary";             break;
	case MID_SUN020:  id = "sun 68020-only binary";              break;
	case MID_PC386:   id = "386 PC binary. (so quoth BFD)";      break;
	case MID_HP200:   id = "hp200 (68010) BSD binary";           break;
	case MID_I386:    id = "i386 BSD binary";                    break;
	case MID_M68K:    id = "m68k BSD binary with 8K page sizes"; break;
	case MID_M68K4K:  id = "m68k BSD binary with 4K page sizes"; break;
	case MID_NS32532: id = "ns32532";                            break;
	case MID_SPARC:   id = "sparc";                              break;
	case MID_PMAX:    id = "pmax";                               break;
	case MID_VAX:     id = "vax";                                break;
	case MID_ALPHA:   id = "Alpha BSD binary";                   break;
	case MID_MIPS:    id = "big-endian MIPS";                    break;
	case MID_ARM6:    id = "ARM6";                               break;
	case MID_HP300:   id = "hp300 (68020+68881) BSD binary";     break;
	case MID_HPUX:    id = "hp200/300 HP-UX binary";             break;
	case MID_HPUX800: id = "hp800 HP-UX binary";                 break;
	default:
		id = "don't know"; break;
	}

	printf("type %d, %s\n", N_GETMID(*exhdr), id);

	/* this left shift seems a bit bogus */

	switch((N_GETFLAG(*exhdr) & EX_DPMASK)>>4) {
	case 0:
		id = "traditional executable or object file"; break;
	case 1:
		id = "object file contains PIC code"; break;
	case 2:
		id = "dynamic executable"; break;
	case 3:
		id = "position independent executable image"; break;
	default:
		id = NULL;
	}

	if (NULL != id)
		printf("flags: 0x%x, %s\n", N_GETFLAG(*exhdr), id);
	else
		printf("flags: 0x%x\n", N_GETFLAG(*exhdr));

	if (extended_info) {
		unsigned long txt_addr;
		unsigned long dat_addr;
		unsigned long bss_addr;

		/* N_TXTADDR and N_DATADDR macros DON'T WORK */
		if (N_GETMAGIC(*exhdr) == ZMAGIC) {
			txt_addr = __LDPGSZ;
			dat_addr = ((txt_addr + exhdr->a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1));
		} else if (N_GETMAGIC(*exhdr) == OMAGIC) {
			txt_addr = 0;
			dat_addr = txt_addr + exhdr->a_text;
		} else {
			txt_addr = 0xdeadbeef;
			dat_addr = 0xcafebabe;
		}

		bss_addr = dat_addr + exhdr->a_data;

		printf("	text segment size  = 0x%lx, text segment file offset = %ld\n", exhdr->a_text, N_TXTOFF(*exhdr));
		printf("	data segment size  = 0x%lx, data segment file offset = %ld\n", exhdr->a_data, N_DATOFF(*exhdr));
		printf("	bss  segment size  = 0x%lx\n", exhdr->a_bss);
		printf("	text segment relocation size  = 0x%lx, file offset   = %ld, %d text relocations\n",
			exhdr->a_trsize, N_TRELOFF(*exhdr), exhdr->a_trsize/sizeof(struct relocation_info));
		printf("	data segment relocation size  = 0x%lx, file offset   = %ld, %d data relocations\n",
			exhdr->a_drsize, N_DRELOFF(*exhdr), exhdr->a_drsize/sizeof(struct relocation_info));
		printf("	symbol table size  = 0x%lx, symbol table file offset = %ld (%d symbols)\n",
			exhdr->a_syms, N_SYMOFF(*exhdr), exhdr->a_syms/sizeof(struct nlist));
		printf("	string table file offset = 0x%lx (%d)\n", N_STROFF(*exhdr), N_STROFF(*exhdr));
		printf("	entry point  = 0x%lx\n", exhdr->a_entry);
		printf("	text address = 0x%lx\n\tdata address = 0x%lx\n"
			"\tbss address = 0x%lx\n",
			txt_addr, dat_addr, bss_addr
			/* N_TXTADDR(*exhdr), N_DATADDR(*exhdr), N_BSSADDR(*exhdr) */
		);
	}
}
Esempio n. 28
0
int hide_aout(int inf, const char *filename)
{
    struct stat infstat;
    struct relocation_info *relp;
    struct nlist *symp;
    int rc;

    /*
     * do some error checking.
     */

    if(fstat(inf, &infstat) == -1) {
	perror(filename);
	return 1;
    }

    /*
     * Read the entire file into memory.  XXX - Really, we only need to
     * read the header and from TRELOFF to the end of the file.
     */

    if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) {
	fprintf(stderr, "%s: too big to read into memory\n", filename);
	return 1;
    }

    if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
	fprintf(stderr, "%s: read error: %s\n", filename,
		rc == -1? strerror(errno) : "short read");
	return 1;
    }

    /*
     * Calculate offsets and sizes from the header.
     */

    hdrp = (struct exec *) aoutdata;

#ifdef __FreeBSD__
    textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp));
    datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) +
					  hdrp->a_trsize);
#else
    textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp));
    datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp));
#endif
    symbase = (struct nlist *)		 (aoutdata + N_SYMOFF(*hdrp));
    strbase = (char *) 			 (aoutdata + N_STROFF(*hdrp));

    ntextrel = hdrp->a_trsize / sizeof(struct relocation_info);
    ndatarel = hdrp->a_drsize / sizeof(struct relocation_info);
    nsyms    = hdrp->a_syms   / sizeof(struct nlist);

    /*
     * Zap the type field of all globally-defined symbols.  The linker will
     * subsequently ignore these entries.  Don't zap any symbols in the
     * keep list.
     */

    for(symp = symbase; symp < symbase + nsyms; symp++) {
	if(!IS_GLOBAL_DEFINED(symp))		/* keep undefined syms */
	    continue;

	/* keep (C) symbols which are on the keep list */
	if(SYMSTR(symp)[0] == '_' && in_keep_list(SYMSTR(symp) + 1))
	    continue;

	symp->n_type = 0;
    }

    /*
     * Check whether the relocation entries reference any symbols that we
     * just zapped.  I don't know whether ld can handle this case, but I
     * haven't encountered it yet.  These checks are here so that the program
     * doesn't fail silently should such symbols be encountered.
     */

    for(relp = textrel; relp < textrel + ntextrel; relp++)
	check_reloc(filename, relp);
    for(relp = datarel; relp < datarel + ndatarel; relp++)
	check_reloc(filename, relp);

    /*
     * Write the .o file back out to disk.  XXX - Really, we only need to
     * write the symbol table entries back out.
     */
    lseek(inf, 0, SEEK_SET);
    if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
	fprintf(stderr, "%s: write error: %s\n", filename,
		rc == -1? strerror(errno) : "short write");
	return 1;
    }

    return 0;
}
Esempio n. 29
0
static ssize_t MSMachONameList_(const void *stuff, struct MSSymbolData *list, size_t nreq) {
    // XXX: ok, this is just pathetic; API fail much?
    size_t slide(0);
    for (uint32_t image(0), images(_dyld_image_count()); image != images; ++image)
        if (_dyld_get_image_header(image) == stuff) {
            slide = _dyld_get_image_vmaddr_slide(image);
            goto fat;
        }

    return -1;

fat:
    const uint8_t *base(reinterpret_cast<const uint8_t *>(stuff));
    const struct exec *buf(reinterpret_cast<const struct exec *>(base));

    if (OSSwapBigToHostInt32(buf->a_magic) == FAT_MAGIC) {
        struct host_basic_info hbi;
        {
            host_t host(mach_host_self());
            mach_msg_type_number_t count(HOST_BASIC_INFO_COUNT);
            if (host_info(host, HOST_BASIC_INFO, reinterpret_cast<host_info_t>(&hbi), &count) != KERN_SUCCESS)
                return -1;
            mach_port_deallocate(mach_task_self(), host);
        }

        const struct fat_header *fh(reinterpret_cast<const struct fat_header *>(base));
        uint32_t nfat_arch(OSSwapBigToHostInt32(fh->nfat_arch));
        const struct fat_arch *fat_archs(reinterpret_cast<const struct fat_arch *>(fh + 1));

        for (uint32_t i(0); i != nfat_arch; ++i)
            if (static_cast<cpu_type_t>(OSSwapBigToHostInt32(fat_archs[i].cputype)) == hbi.cpu_type) {
                buf = reinterpret_cast<const struct exec *>(base + OSSwapBigToHostInt32(fat_archs[i].offset));
                goto thin;
            }

        return -1;
    }

thin:
    const nlist_xx *symbols;
    const char *strings;
    size_t n;

    // XXX: this check looks really scary when it fails
    if (buf->a_magic == MH_MAGIC_XX) {
        const mach_header_xx *mh(reinterpret_cast<const mach_header_xx *>(base));
        const struct load_command *load_commands(reinterpret_cast<const struct load_command *>(mh + 1));

        const struct symtab_command *stp(NULL);
        const struct load_command *lcp;

        /* forlc (command, mh, LC_SYMTAB, struct symtab_command) {
            stp = command;
            goto found;
        } */

        lcp = load_commands;
        for (uint32_t i(0); i != mh->ncmds; ++i) {
            if (
                lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 ||
                reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mh->sizeofcmds
            )
                return -1;

            if (lcp->cmd == LC_SYMTAB) {
                if (lcp->cmdsize != sizeof(struct symtab_command))
                    return -1;
                stp = reinterpret_cast<const struct symtab_command *>(lcp);
                goto found;
            }

            lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize);
        }

        return -1;

found:
        n = stp->nsyms;

        symbols = NULL;
        strings = NULL;

        /* forlc (command, mh, LC_SEGMENT_XX, segment_command_xx) {
            stp = command;
            goto found;
        } */

        lcp = load_commands;
        for (uint32_t i(0); i != mh->ncmds; ++i) {
            if (
                lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 ||
                reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mh->sizeofcmds
            )
                return -1;

            if (lcp->cmd == LC_SEGMENT_XX) {
                if (lcp->cmdsize < sizeof(segment_command_xx))
                    return -1;
                const segment_command_xx *segment(reinterpret_cast<const segment_command_xx *>(lcp));
                if (stp->symoff >= segment->fileoff && stp->symoff < segment->fileoff + segment->filesize)
                    symbols = reinterpret_cast<const nlist_xx *>(stp->symoff - segment->fileoff + segment->vmaddr + slide);
                if (stp->stroff >= segment->fileoff && stp->stroff < segment->fileoff + segment->filesize)
                    strings = reinterpret_cast<const char *>(stp->stroff - segment->fileoff + segment->vmaddr + slide);
            }

            lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize);
        }

        if (symbols == NULL || strings == NULL)
            return -1;
        // XXX: detect a.out somehow?
    } else if (false) {
        /* XXX: is this right anymore?!? */
        symbols = reinterpret_cast<const nlist_xx *>(base + N_SYMOFF(*buf));
        strings = reinterpret_cast<const char *>(reinterpret_cast<const uint8_t *>(symbols) + buf->a_syms);
        n = buf->a_syms / sizeof(nlist_xx);
    } else return -1;

    size_t result(nreq);

    for (size_t m(0); m != n; ++m) {
        const nlist_xx *q(&symbols[m]);
        if (q->n_un.n_strx == 0 || (q->n_type & N_STAB) != 0)
            continue;

        const char *nambuf(strings + q->n_un.n_strx);
        //fprintf(stderr, " == %s\n", nambuf);

        for (size_t item(0); item != nreq; ++item) {
            struct MSSymbolData *p(list + item);
            if (p->name_ == NULL || strcmp(p->name_, nambuf) != 0)
                continue;

            p->name_ = NULL;

            p->value_ = q->n_value;
            if (p->value_ != 0)
                p->value_ += slide;

            p->type_ = q->n_type;
            p->desc_ = q->n_desc;
            p->sect_ = q->n_sect;

            if (--result == 0)
                return 0;
            break;
        }
    }

    return result;
}