Bool aout_is_exec(Environ *e, uByte *load, uInt loadlen) { struct exec *ex = (struct exec*)load; int m; DPRINTF(("aout_is_exec: midmag=%#x badmagic=%d mid=%#x\n", ex->a_midmag, N_BADMAG(*ex), N_GETMID(*ex))); if (N_BADMAG(*ex)) return FALSE; m = N_GETMID(*ex); if (m == AOUT_MAGIC_0) return TRUE; #ifdef AOUT_MAGIC_1 if (m == AOUT_MAGIC_1) return TRUE; #endif #ifdef AOUT_MAGIC_2 if (m == AOUT_MAGIC_2) return TRUE; #endif #ifdef AOUT_MAGIC_3 if (m == AOUT_MAGIC_3) return TRUE; #endif return FALSE; }
int CheckAOutFile(int fd) { #ifdef NOAOUT return(-1); #else struct exec ex, ex_swap; int mid = -1; if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex)) return(-1); (void)lseek(fd, (off_t) 0, SEEK_SET); if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap)) return(-1); (void)lseek(fd, (off_t) 0, SEEK_SET); mid = getMID(mid, N_GETMID (ex)); if (mid == -1) { mid = getMID(mid, N_GETMID (ex_swap)); } if (mid != -1) { return(0); } else { return(-1); } #endif /* NOAOUT */ }
static int is_exos_aout(int fd) { struct exec hdr; u_int dynamic; if (lseek(fd, 0, SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr) || lseek(fd, sizeof(hdr) + hdr.a_text, SEEK_SET) == -1 || read(fd, &dynamic, sizeof(dynamic)) != sizeof(dynamic)) return 0; if (N_GETMAGIC(hdr) != OMAGIC || N_GETMID(hdr) != MID_I386 || N_GETFLAG(hdr) != 0) return 0; return 1; }
/* * Open 'filename', read in program and and return 0 if ok 1 on error. * Fill in marks */ int loadfile(const char *fname, u_long *marks, int flags) { union { #ifdef BOOT_ECOFF struct ecoff_exechdr coff; #endif #ifdef BOOT_ELF Elf_Ehdr elf; #endif #ifdef BOOT_AOUT struct exec aout; #endif } hdr; ssize_t nr; int fd, rval; /* Open the file. */ if ((fd = open(fname, 0)) < 0) { WARN(("open %s", fname ? fname : "<default>")); return -1; } /* Read the exec header. */ if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) { WARN(("read header")); goto err; } #ifdef BOOT_ECOFF if (!ECOFF_BADMAG(&hdr.coff)) { rval = coff_exec(fd, &hdr.coff, marks, flags); } else #endif #ifdef BOOT_ELF if (memcmp(hdr.elf.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf.e_ident[EI_CLASS] == ELFCLASS) { #ifdef BOOT_ZBOOT rval = zboot_exec(fd, marks, flags); #else rval = elf_exec(fd, &hdr.elf, marks, flags); #endif } else #endif #ifdef BOOT_AOUT if (OKMAGIC(N_GETMAGIC(hdr.aout)) #ifndef NO_MID_CHECK && N_GETMID(hdr.aout) == MID_MACHINE #endif ) { rval = aout_exec(fd, &hdr.aout, marks, flags); } else #endif { rval = 1; errno = EFTYPE; WARN(("%s", fname ? fname : "<default>")); } if (rval == 0) { PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START])); return fd; } err: (void)close(fd); return -1; }
/* * 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); }
int GetAOutFileInfo(struct dllist *dl) { #ifdef NOAOUT return(-1); #else struct exec ex, ex_swap; u_int32_t mid = -1; u_int32_t magic, clbytes, clofset; if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex)) return(-1); (void)lseek(dl->ldfd, (off_t) 0, SEEK_SET); if (read(dl->ldfd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap)) return(-1); mopFileSwapX((u_char *)&ex_swap, 0, 4); mid = getMID(mid, N_GETMID (ex)); if (mid == (uint32_t)-1) { mid = getMID(mid, N_GETMID (ex_swap)); if (mid != (uint32_t)-1) { mopFileSwapX((u_char *)&ex, 0, 4); } } if (mid == (uint32_t)-1) { return(-1); } if (N_BADMAG (ex)) { return(-1); } switch (mid) { case MID_I386: #ifdef MID_NS32532 case MID_NS32532: #endif #ifdef MID_PMAX case MID_PMAX: #endif #ifdef MID_VAX case MID_VAX: #endif #ifdef MID_ALPHA case MID_ALPHA: #endif #ifdef MID_ARM6 case MID_ARM6: #endif ex.a_text = mopFileGetLX((u_char *)&ex_swap, 4, 4); ex.a_data = mopFileGetLX((u_char *)&ex_swap, 8, 4); ex.a_bss = mopFileGetLX((u_char *)&ex_swap, 12, 4); ex.a_syms = mopFileGetLX((u_char *)&ex_swap, 16, 4); ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4); ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4); ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4); break; #ifdef MID_M68K case MID_M68K: #endif #ifdef MID_M68K4K case MID_M68K4K: #endif case MID_SPARC: #ifdef MID_MIPS case MID_MIPS: #endif ex.a_text = mopFileGetBX((u_char *)&ex_swap, 4, 4); ex.a_data = mopFileGetBX((u_char *)&ex_swap, 8, 4); ex.a_bss = mopFileGetBX((u_char *)&ex_swap, 12, 4); ex.a_syms = mopFileGetBX((u_char *)&ex_swap, 16, 4); ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4); ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4); ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4); break; default: break; } printf("a.out image ("); switch (N_GETMID (ex)) { case MID_I386: printf("i386"); break; #ifdef MID_M68K case MID_M68K: printf("m68k"); break; #endif #ifdef MID_M68K4K case MID_M68K4K: printf("m68k 4k"); break; #endif #ifdef MID_NS32532 case MID_NS32532: printf("pc532"); break; #endif case MID_SPARC: printf("sparc"); break; #ifdef MID_PMAX case MID_PMAX: printf("pmax"); break; #endif #ifdef MID_VAX case MID_VAX: printf("vax"); break; #endif #ifdef MID_ALPHA case MID_ALPHA: printf("alpha"); break; #endif #ifdef MID_MIPS case MID_MIPS: printf("mips"); break; #endif #ifdef MID_ARM6 case MID_ARM6: printf("arm32"); break; #endif default: break; } printf(") Magic: "); switch (N_GETMAGIC (ex)) { case OMAGIC: printf("OMAGIC"); break; case NMAGIC: printf("NMAGIC"); break; case ZMAGIC: printf("ZMAGIC"); break; case QMAGIC: printf("QMAGIC"); break; default: printf("Unknown %ld", (long) N_GETMAGIC (ex)); } printf("\n"); printf("Size of text: %08lx\n", (long)ex.a_text); printf("Size of data: %08lx\n", (long)ex.a_data); printf("Size of bss: %08lx\n", (long)ex.a_bss); printf("Size of symbol tab: %08lx\n", (long)ex.a_syms); printf("Transfer Address: %08lx\n", (long)ex.a_entry); printf("Size of reloc text: %08lx\n", (long)ex.a_trsize); printf("Size of reloc data: %08lx\n", (long)ex.a_drsize); magic = N_GETMAGIC (ex); clbytes = getCLBYTES(mid); clofset = clbytes - 1; dl->image_type = IMAGE_TYPE_AOUT; dl->loadaddr = 0; dl->xferaddr = ex.a_entry; dl->a_text = ex.a_text; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_text_fill = clbytes - (ex.a_text & clofset); if (dl->a_text_fill == clbytes) dl->a_text_fill = 0; } else dl->a_text_fill = 0; dl->a_data = ex.a_data; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_data_fill = clbytes - (ex.a_data & clofset); if (dl->a_data_fill == clbytes) dl->a_data_fill = 0; } else dl->a_data_fill = 0; dl->a_bss = ex.a_bss; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_bss_fill = clbytes - (ex.a_bss & clofset); if (dl->a_bss_fill == clbytes) dl->a_bss_fill = 0; } else { dl->a_bss_fill = clbytes - ((ex.a_text+ex.a_data+ex.a_bss) & clofset); if (dl->a_bss_fill == clbytes) dl->a_bss_fill = 0; } dl->a_mid = mid; return(0); #endif /* NOAOUT */ }
/* * 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; }
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) */ ); } }
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; }
static int exec_exos_aout(int fd, const char *path, char *const argv[], char *const envp[], struct Env *e, u_int flags) { u_int envid = e->env_id; struct exec hdr; u_int dynamic; int r; struct _exos_exec_args eea; if (lseek(fd, 0, SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr) || lseek(fd, sizeof(hdr) + hdr.a_text, SEEK_SET) == -1 || read(fd, &dynamic, sizeof(dynamic)) != sizeof(dynamic)) return 0; if (N_GETMAGIC(hdr) != OMAGIC || N_GETMID(hdr) != MID_I386 || N_GETFLAG(hdr) != 0) return 0; if (!(flags & _EXEC_USE_FD)) { close(fd); fd = -1; } else if (lseek(fd, 0, SEEK_SET) == -1) return 0; if (dynamic < SHARED_LIBRARY_START) dynamic = 0; if (dynamic == 0 && (flags & _EXEC_SHLIB_ONLY)) { r = -EINVAL; goto err; } /* if static, then read in entire program... */ if (!dynamic) { u_int start_text_addr; if (flags & _EXEC_USE_FD) start_text_addr = __load_prog_fd(fd, 1, envid); else start_text_addr = __load_prog(path, argv[0], 1, envid); if (!start_text_addr) { r = -ENOEXEC; goto err; } /* set start address */ e->env_tf.tf_eip = start_text_addr; } /* if dynamic, then make sure shared library is available */ else if (dynamic) { struct stat sb; /* If flag so indicates, then require RO copy and use in mem version */ if (!(flags & _EXEC_SHLIB_ONLY)) { /* if the shared library is not already in memory, or if it's old */ /* then we need to (re)read it in */ if (stat(PATH_LIBEXOS, &sb)) { r = -errno; kprintf("error stat'ing sl: %d\n", errno); goto err; } /* if we don't have a RO copy or it's out of date... */ if (!isvamapped(SHARED_LIBRARY_START_RODATA) || memcmp(&sl_data->mod_time, &sb.st_mtimespec, sizeof(sb.st_mtimespec))) { int slfd; /* if it's out of date, then unmap it */ if (isvamapped(SHARED_LIBRARY_START_RODATA)) munmap((void*)SHARED_LIBRARY_START_RODATA, (sl_data->text_pages + sl_data->data_pages) * NBPG); slfd = open (PATH_LIBEXOS, O_RDONLY); if (slfd < 0) { r = -errno; kprintf("could not open shared library " PATH_LIBEXOS "\n"); goto err; } if ((r = __load_sl_image (slfd)) < 0) { kprintf("could not load library\n"); close(slfd); goto err; } *((struct timespec*)&sl_data->mod_time) = sb.st_mtimespec; assert(sys_self_mod_pte_range(0, PG_RO, PG_W, SHARED_LIBRARY_START_RODATA, 1) == 0); close (slfd); } } else { if (!isvamapped(SHARED_LIBRARY_START_RODATA)) { r = -EINVAL; goto err; } } /* share the text region read only/exec into child */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA, sl_data->text_pages * NBPG, 0, 0, envid, SHARED_LIBRARY_START)) { kprintf ("__vm_share_region failed for text region\n"); r = -ENOEXEC; goto err; } /* share the read only data region into child cow */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA + sl_data->text_pages * NBPG, sl_data->data_pages * NBPG, 0, 0, envid, SHARED_LIBRARY_START + sl_data->text_pages * NBPG)) { kprintf ("__vm_share_region failed for cow data region\n"); r = -ENOEXEC; goto err; } if (sys_mod_pte_range(0, PG_COW, PG_RO | PG_SHARED, SHARED_LIBRARY_START + sl_data->text_pages * NBPG, sl_data->data_pages, 0, envid) < 0) { kprintf ("sys_mod_pte_range failed for cow data region\n"); r = -ENOEXEC; goto err; } /* share the RO copy of the shared library */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA, (sl_data->text_pages + sl_data->data_pages) * NBPG, 0, 0, envid, SHARED_LIBRARY_START_RODATA)) { kprintf ("__vm_share_region failed for read only text/data region\n"); r = -ENOEXEC; goto err; } /* demand alloc bss for sl or no? */ if (getenv("NO_BSS_DEMAND_ALLOC")) { /* zero the bss */ if (__zero_segment (envid, SHARED_LIBRARY_START + (sl_data->text_pages + sl_data->data_pages) * NBPG, sl_data->bss_pages * NBPG) < 0) { kprintf("could not create bss segment\n"); r = -ENOEXEC; goto err; } } /* otherwise the fault handler will deal with it */ /* set start address */ e->env_tf.tf_eip = SHARED_LIBRARY_START + sizeof(struct exec); } /* take care of args, etc */ if (flags & _EXEC_USE_FD) eea.eea_prog_fd = fd; else eea.eea_prog_fd = -1; if ((r = setup_new_stack(argv, envp, envid, &e->env_tf.tf_esp, &eea)) < 0) goto err; return 1; err: return r; }
/* * 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); }
/* * Read in program from the given file descriptor. * Return error code (0 on success). * Fill in marks. */ int fdloadfile(int fd, u_long *marks, int flags) { union { #ifdef BOOT_ECOFF struct ecoff_exechdr coff; #endif #ifdef BOOT_ELF32 Elf32_Ehdr elf32; #endif #ifdef BOOT_ELF64 Elf64_Ehdr elf64; #endif #ifdef BOOT_AOUT struct exec aout; #endif } hdr; ssize_t nr; int rval; /* Read the exec header. */ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) goto err; nr = read(fd, &hdr, sizeof(hdr)); if (nr == -1) { WARN(("read header failed")); goto err; } if (nr != sizeof(hdr)) { WARN(("read header short")); errno = EFTYPE; goto err; } #ifdef BOOT_ECOFF if (!ECOFF_BADMAG(&hdr.coff)) { rval = loadfile_coff(fd, &hdr.coff, marks, flags); } else #endif #ifdef BOOT_ELF32 if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { netbsd_elf_class = ELFCLASS32; rval = loadfile_elf32(fd, &hdr.elf32, marks, flags); } else #endif #ifdef BOOT_ELF64 if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) { netbsd_elf_class = ELFCLASS64; rval = loadfile_elf64(fd, &hdr.elf64, marks, flags); } else #endif #ifdef BOOT_AOUT if (OKMAGIC(N_GETMAGIC(hdr.aout)) #ifndef NO_MID_CHECK && N_GETMID(hdr.aout) == MID_MACHINE #endif ) { rval = loadfile_aout(fd, &hdr.aout, marks, flags); } else #endif { rval = 1; errno = EFTYPE; } if (rval == 0) { if ((flags & LOAD_ALL) != 0) PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START])); return 0; } err: return errno; }