Exemple #1
0
int
a_out_mod_sizes(int fd, size_t *modsize, int *strtablen,
    struct lmc_resrv *resrvp, struct stat *sp)
{
	struct exec info_buf;

	if (a_out_read_header(fd, &info_buf) < 0)
		return -1;

	/*
	 * Calculate the size of the module
	 */
	*modsize = info_buf.a_text + info_buf.a_data + info_buf.a_bss;

	*strtablen = sp->st_size - N_STROFF(info_buf);

	if (symtab) {
		/*
		 * XXX TODO:  grovel through symbol table looking for
		 * just the symbol table stuff from the new module,
		 * and skip the stuff from the kernel.
		 */
		resrvp->sym_size = info_buf.a_syms + *strtablen;
		resrvp->sym_symsize = info_buf.a_syms;
	} else
		resrvp->sym_size = resrvp->sym_symsize = 0;

	return (0);
}
Exemple #2
0
int
ksyms_aout_parse()
{
	struct exec eh;
	uint32_t size;

	if (lseek(ksyms, 0, SEEK_SET) == -1)
		return -1;

	if (read(ksyms, &eh, sizeof eh) != sizeof eh)
		return -1;

	if (N_BADMAG(eh))
		return -1;

	ksymoffs = (off_t)N_STROFF(eh);
	if (lseek(ksyms, ksymoffs, SEEK_SET) == -1)
		return -1;

	if (read(ksyms, &size, sizeof size) != sizeof size)
		return -1;
	ksymoffs += sizeof size;
	if (size <= sizeof size)
		return -1;
	ksymsize = (off_t)size - sizeof size;

	return 0;
}
Exemple #3
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;
}
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);
}
Exemple #5
0
char *
read_stringtable(FILE *fin, struct exec *exhdr, int *strtbl_sz)
{
	unsigned long length;
	char *p = NULL;

	assert(NULL != fin);

	if (NULL == exhdr) {
		fprintf(stderr, "Trying to read string table, but got no a.out header\n");
		return NULL;
	}

	if (fseek(fin, N_STROFF(*exhdr), SEEK_SET) < 0) {
		fprintf(stderr, "Problem seeking to string table: %s\n",
			strerror(errno));
		return NULL;
	}

	if (fread(&length, sizeof(length), 1, fin) != 1) {
		fprintf(stderr, "Problem reading length of string table: %s\n",
			strerror(errno));
		return NULL;
	}

	if (length >= 4) {
		p = read_extent(fin, length, N_STROFF(*exhdr), __LINE__);
		*strtbl_sz = length;
		printf("\nstring table size %d\n", *strtbl_sz);
	} else  {
		fprintf(stderr, "Problem, length of string table read as %d,"
			" can't be right\n, ", length);
		*strtbl_sz = 0;
	}

	return p;
}
Exemple #6
0
static void demangleAout(const HDR *x, long nsyms)
{
	newSym=xfopen(newSym_n, "w+");
	xsetbuf(newSym, newSymb);
	newSng=xfopen(newSng_n, "w+");
	xsetbuf(newSng, newSngb);
	newSngLoc = 4;

//cerr << "created temps!" << endl;
//sleep(5);

	readStringTable(N_STROFF(*x));

	buildNewTables(x, nsyms);
	if (overwriteAout)
		overwriteOldTables(x);

	delete stringTable;

	fclose(newSym);
	fclose(newSng);
	unlink(newSym_n);
	unlink(newSng_n);
}
Exemple #7
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;
}
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;
}
Exemple #9
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);
}
Exemple #10
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);
}
Exemple #11
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 */
}
Exemple #12
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;
}
Exemple #13
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);
}
Exemple #14
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) */
		);
	}
}
Exemple #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);
}