/* * mips4k bootable image. */ static int mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) { abort(); #ifdef unused USED(fd); fp->type = FMIPSB; switch(hp->e.h.amagic) { default: case 0407: /* some kind of mips */ settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, hp->e.h.tsize, sizeof(struct mips4kexec)); setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); break; case 0413: /* some kind of mips */ settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, hp->e.h.tsize, 0); setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, hp->e.h.tsize, hp->e.h.bsize); break; } setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); fp->hdrsz = 0; /* header stripped */ #endif return 1; }
static int commonllp64(int, Fhdr *fp, ExecHdr *hp) { long pgsize; uvlong entry; hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); if(!(hp->e.magic & HDR_MAGIC)) return 0; /* * There can be more magic here if the * header ever needs more expansion. * For now just catch use of any of the * unused bits. */ if((hp->e.magic & ~DYN_MAGIC)>>16) return 0; entry = beswav(hp->e.hdr[0]); pgsize = mach->pgsize; settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz); setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss); setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); if(hp->e.magic & DYN_MAGIC) { fp->txtaddr = 0; fp->dataddr = fp->txtsz; return 1; } commonboot(fp); return 1; }
/* * sparc bootable image */ static int sparcboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); fp->type = FSPARCB; settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, sizeof(struct sparcexec)); setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, fp->txtoff+hp->e.stext, hp->e.sbss); setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); fp->hdrsz = 0; /* header stripped */ return 1; }
/* * next bootable image */ static int nextboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); fp->type = FNEXTB; settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, hp->e.texts.size, hp->e.texts.offset); setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, hp->e.datas.offset, hp->e.bsss.size); setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, hp->e.symc.symoff); fp->hdrsz = 0; /* header stripped */ return 1; }
/* * Crack a normal a.out-type header */ static int adotout(int fd, Fhdr *fp, ExecHdr *hp) { long pgsize; USED(fd); pgsize = mach->pgsize; settext(fp, hp->e.entry, pgsize+sizeof(Exec), hp->e.text, sizeof(Exec)); setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); return 1; }
/* * (Free|Net)BSD ARM header. */ static int armdotout(int fd, Fhdr *fp, ExecHdr *hp) { uvlong kbase; USED(fd); settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); kbase = 0xF0000000; if ((fp->entry & kbase) == kbase) { /* Boot image */ fp->txtaddr = kbase+sizeof(Exec); fp->name = "ARM *BSD boot image"; fp->hdrsz = 0; /* header stripped */ fp->dataddr = kbase+fp->txtsz; } return 1; }
static void dodefine(State *s, char *p) { int brace; Symb *sym; char *name, *val; if(peek(s) & (Tdisable|Tinherit)) return; if(! Name1(*p)) cpperr(s, "%q - bad character in macro name\n", p); name = p; while(NameN(*p)) p++; val = nil; if(*p == '('){ *p++ = 0; brace = 1; while(*p){ switch(*p++){ case '(': brace++; break; case ')': brace--; break; default: break; } if(brace == 0) break; } val = p; } if(isspace(*p)){ *p++ = 0; while(isspace(*p)) p++; val = p; } if(val == nil || ! *val) val = "1"; setsym(name, val); }
static int commonllp64(int unused, Fhdr *fp, ExecHdr *hp) { int32 pgsize; uvlong entry; USED(unused); hswal(&hp->e, sizeof(Exec)/sizeof(int32), beswal); if(!(hp->e.exechdr.magic & HDR_MAGIC)) return 0; /* * There can be more magic here if the * header ever needs more expansion. * For now just catch use of any of the * unused bits. */ if((hp->e.exechdr.magic & ~DYN_MAGIC)>>16) return 0; union { char *p; uvlong *v; } u; u.p = (char*)&hp->e.exechdr; entry = beswav(*u.v); pgsize = mach->pgsize; settext(fp, entry, pgsize+fp->hdrsz, hp->e.exechdr.text, fp->hdrsz); setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), hp->e.exechdr.data, fp->txtsz+fp->hdrsz, hp->e.exechdr.bss); setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz); if(hp->e.exechdr.magic & DYN_MAGIC) { fp->txtaddr = 0; fp->dataddr = fp->txtsz; return 1; } commonboot(fp); return 1; }
/* * mips bootable image. */ static int mipsboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); fp->type = FMIPSB; switch(hp->e.amagic) { default: case 0407: /* some kind of mips */ settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, hp->e.tsize, sizeof(struct mipsexec)+4); setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, fp->txtoff+hp->e.tsize, hp->e.bsize); break; case 0413: /* some kind of mips */ settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, hp->e.tsize, 0); setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, hp->e.tsize, hp->e.bsize); break; } setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); fp->hdrsz = 0; /* header stripped */ return 1; }
/* * Elf32 binaries. */ static int elfdotout(int fd, Fhdr *fp, ExecHdr *hp) { ulong (*swal)(ulong); ushort (*swab)(ushort); Ehdr *ep; Phdr *ph; int i, it, id, is, phsz; /* bitswap the header according to the DATA format */ ep = &hp->e; if(ep->ident[CLASS] != ELFCLASS32) { werrstr("bad ELF class - not 32 bit"); return 0; } if(ep->ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; } else if(ep->ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; } else { werrstr("bad ELF encoding - not big or little endian"); return 0; } ep->type = swab(ep->type); ep->machine = swab(ep->machine); ep->version = swal(ep->version); ep->elfentry = swal(ep->elfentry); ep->phoff = swal(ep->phoff); ep->shoff = swal(ep->shoff); ep->flags = swal(ep->flags); ep->ehsize = swab(ep->ehsize); ep->phentsize = swab(ep->phentsize); ep->phnum = swab(ep->phnum); ep->shentsize = swab(ep->shentsize); ep->shnum = swab(ep->shnum); ep->shstrndx = swab(ep->shstrndx); if(ep->type != EXEC || ep->version != CURRENT) return 0; /* we could definitely support a lot more machines here */ fp->magic = ELF_MAG; fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; switch(ep->machine) { case I386: mach = &mi386; fp->type = FI386; break; case MIPS: mach = &mmips; fp->type = FMIPS; break; case SPARC64: mach = &msparc64; fp->type = FSPARC64; break; case POWER: mach = &mpower; fp->type = FPOWER; break; case AMD64: mach = &mamd64; fp->type = FAMD64; break; case ARM: mach = &marm; fp->type = FARM; break; default: return 0; } if(ep->phentsize != sizeof(Phdr)) { werrstr("bad ELF header size"); return 0; } phsz = sizeof(Phdr)*ep->phnum; ph = malloc(phsz); if(!ph) return 0; seek(fd, ep->phoff, 0); if(read(fd, ph, phsz) < 0) { free(ph); return 0; } hswal(ph, phsz/sizeof(ulong), swal); /* find text, data and symbols and install them */ it = id = is = -1; for(i = 0; i < ep->phnum; i++) { if(ph[i].type == LOAD && (ph[i].flags & (R|X)) == (R|X) && it == -1) it = i; else if(ph[i].type == LOAD && (ph[i].flags & (R|W)) == (R|W) && id == -1) id = i; else if(ph[i].type == NOPTYPE && is == -1) is = i; } if(it == -1 || id == -1) { /* * The SPARC64 boot image is something of an ELF hack. * Text+Data+BSS are represented by ph[0]. Symbols * are represented by ph[1]: * * filesz, memsz, vaddr, paddr, off * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff * ph[1] : symsz, lcsz, 0, 0, symoff */ if(ep->machine == SPARC64 && ep->phnum == 2) { ulong txtaddr, txtsz, dataddr, bsssz; txtaddr = ph[0].vaddr | 0x80000000; txtsz = ph[0].filesz - ph[0].paddr; dataddr = txtaddr + txtsz; bsssz = ph[0].memsz - ph[0].filesz; settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); free(ph); return 1; } werrstr("No TEXT or DATA sections"); free(ph); return 0; } settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); if(is != -1) setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); free(ph); return 1; }
/* * ELF64 binaries. */ static int elf64dotout(int fd, Fhdr *fp, ExecHdr *hp) { E64hdr *ep; P64hdr *ph; ushort (*swab)(ushort); ulong (*swal)(ulong); uvlong (*swav)(uvlong); int i, it, id, is, phsz; uvlong uvl; ep = &hp->e; if(ep->ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; swav = leswav; } else if(ep->ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; swav = beswav; } else { werrstr("bad ELF64 encoding - not big or little endian"); return 0; } ep->type = swab(ep->type); ep->machine = swab(ep->machine); ep->version = swal(ep->version); if(ep->type != EXEC || ep->version != CURRENT) return 0; ep->elfentry = swav(ep->elfentry); ep->phoff = swav(ep->phoff); ep->shoff = swav(ep->shoff); ep->flags = swal(ep->flags); ep->ehsize = swab(ep->ehsize); ep->phentsize = swab(ep->phentsize); ep->phnum = swab(ep->phnum); ep->shentsize = swab(ep->shentsize); ep->shnum = swab(ep->shnum); ep->shstrndx = swab(ep->shstrndx); fp->magic = ELF_MAG; fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; switch(ep->machine) { default: return 0; case AMD64: mach = &mamd64; fp->type = FAMD64; fp->name = "amd64 ELF64 executable"; break; case POWER64: mach = &mpower64; fp->type = FPOWER64; fp->name = "power64 ELF64 executable"; break; } if(ep->phentsize != sizeof(P64hdr)) { werrstr("bad ELF64 header size"); return 0; } phsz = sizeof(P64hdr)*ep->phnum; ph = malloc(phsz); if(!ph) return 0; seek(fd, ep->phoff, 0); if(read(fd, ph, phsz) < 0) { free(ph); return 0; } for(i = 0; i < ep->phnum; i++) { ph[i].type = swal(ph[i].type); ph[i].flags = swal(ph[i].flags); ph[i].offset = swav(ph[i].offset); ph[i].vaddr = swav(ph[i].vaddr); ph[i].paddr = swav(ph[i].paddr); ph[i].filesz = swav(ph[i].filesz); ph[i].memsz = swav(ph[i].memsz); ph[i].align = swav(ph[i].align); } /* find text, data and symbols and install them */ it = id = is = -1; for(i = 0; i < ep->phnum; i++) { if(ph[i].type == LOAD && (ph[i].flags & (R|X)) == (R|X) && it == -1) it = i; else if(ph[i].type == LOAD && (ph[i].flags & (R|W)) == (R|W) && id == -1) id = i; else if(ph[i].type == NOPTYPE && is == -1) is = i; } if(it == -1 || id == -1) { werrstr("No ELF64 TEXT or DATA sections"); free(ph); return 0; } settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); /* 8c: out of fixed registers */ uvl = ph[id].memsz - ph[id].filesz; setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl); if(is != -1) setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); free(ph); return 1; }
static int machdotout(int fd, Fhdr *fp, ExecHdr *hp) { uvlong (*swav)(uvlong); uint32 (*swal)(uint32); Machhdr *mp; MachCmd **cmd; MachSymSeg *symtab; MachSymSeg *pclntab; MachSeg64 *seg; MachSect64 *sect; MachSeg32 *seg32; MachSect32 *sect32; uvlong textsize, datasize, bsssize; uchar *cmdbuf; uchar *cmdp; int i, j, hdrsize; uint32 textva, textoff, datava, dataoff, symoff, symsize, pclnoff, pclnsize; mp = &hp->e.machhdr; if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) { werrstr("bad MACH executable type %#ux", leswal(mp->filetype)); return 0; } swal = leswal; swav = leswav; mp->magic = swal(mp->magic); mp->cputype = swal(mp->cputype); mp->cpusubtype = swal(mp->cpusubtype); mp->filetype = swal(mp->filetype); mp->ncmds = swal(mp->ncmds); mp->sizeofcmds = swal(mp->sizeofcmds); mp->flags = swal(mp->flags); mp->reserved = swal(mp->reserved); switch(mp->magic) { case 0xFEEDFACE: // 32-bit mach if (mp->cputype != MACH_CPU_TYPE_X86) { werrstr("bad MACH cpu type - not 386"); return 0; } if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) { werrstr("bad MACH cpu subtype - not 386"); return 0; } if (mp->filetype != MACH_EXECUTABLE_TYPE) { werrstr("bad MACH executable type"); return 0; } mach = &mi386; fp->type = FI386; hdrsize = 28; break; case 0xFEEDFACF: // 64-bit mach werrstr("64 bit mach NOT SUPPORTED"); return 0; //if (mp->cputype != MACH_CPU_TYPE_X86_64) { // werrstr("bad MACH cpu type - not amd64"); // return 0; //} // //if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86 && mp->cpusubtype != MACH_CPU_SUBTYPE_X86_64) { // werrstr("bad MACH cpu subtype - not amd64"); // return 0; //} //mach = &mamd64; //fp->type = FAMD64; //hdrsize = 32; //break; default: werrstr("not mach %#ux", mp->magic); return 0; } cmdbuf = malloc(mp->sizeofcmds); if(!cmdbuf) { werrstr("out of memory"); return 0; } seek(fd, hdrsize, 0); if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) { free(cmdbuf); return 0; } cmd = malloc(mp->ncmds * sizeof(MachCmd*)); if(!cmd) { free(cmdbuf); werrstr("out of memory"); return 0; } cmdp = cmdbuf; textva = 0; textoff = 0; dataoff = 0; datava = 0; symtab = 0; pclntab = 0; textsize = 0; datasize = 0; bsssize = 0; symoff = 0; symsize = 0; pclnoff = 0; pclnsize = 0; for (i = 0; i < mp->ncmds; i++) { MachCmd *c; cmd[i] = (MachCmd*)cmdp; c = cmd[i]; c->type = swal(c->type); c->size = swal(c->size); switch(c->type) { case MACH_SEGMENT_32: if(mp->magic != 0xFEEDFACE) { werrstr("segment 32 in mach 64"); goto bad; } seg32 = (MachSeg32*)c; seg32->vmaddr = swav(seg32->vmaddr); seg32->vmsize = swav(seg32->vmsize); seg32->fileoff = swav(seg32->fileoff); seg32->filesize = swav(seg32->filesize); seg32->maxprot = swal(seg32->maxprot); seg32->initprot = swal(seg32->initprot); seg32->nsects = swal(seg32->nsects); seg32->flags = swal(seg32->flags); if (strcmp(seg32->segname, "__TEXT") == 0) { textva = seg32->vmaddr; textoff = seg32->fileoff; textsize = seg32->vmsize; sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32)); for(j = 0; j < seg32->nsects; j++, sect32++) { if (strcmp(sect32->sectname, "__gosymtab") == 0) { symoff = swal(sect32->offset); symsize = swal(sect32->size); } if (strcmp(sect32->sectname, "__gopclntab") == 0) { pclnoff = swal(sect32->offset); pclnsize = swal(sect32->size); } } } if (strcmp(seg32->segname, "__DATA") == 0) { datava = seg32->vmaddr; dataoff = seg32->fileoff; datasize = seg32->filesize; bsssize = seg32->vmsize - seg32->filesize; } break; case MACH_SEGMENT_64: werrstr("MACH SEGMENT 64 NOT SUPPORTED"); goto bad; //if(mp->magic != 0xFEEDFACF) { // werrstr("segment 32 in mach 64"); // goto bad; //} //seg = (MachSeg64*)c; //seg->vmaddr = swav(seg->vmaddr); //seg->vmsize = swav(seg->vmsize); //seg->fileoff = swav(seg->fileoff); //seg->filesize = swav(seg->filesize); //seg->maxprot = swal(seg->maxprot); //seg->initprot = swal(seg->initprot); //seg->nsects = swal(seg->nsects); //seg->flags = swal(seg->flags); //if (strcmp(seg->segname, "__TEXT") == 0) { // textva = seg->vmaddr; // textoff = seg->fileoff; // textsize = seg->vmsize; // sect = (MachSect64*)(cmdp + sizeof(MachSeg64)); // for(j = 0; j < seg->nsects; j++, sect++) { // if (strcmp(sect->sectname, "__gosymtab") == 0) { // symoff = swal(sect->offset); // symsize = swal(sect->size); // } // if (strcmp(sect->sectname, "__gopclntab") == 0) { // pclnoff = swal(sect->offset); // pclnsize = swal(sect->size); // } // } //} //if (strcmp(seg->segname, "__DATA") == 0) { // datava = seg->vmaddr; // dataoff = seg->fileoff; // datasize = seg->filesize; // bsssize = seg->vmsize - seg->filesize; //} break; case MACH_UNIXTHREAD: break; case MACH_SYMSEG: if (symtab == 0) { symtab = (MachSymSeg*)c; symoff = swal(symtab->fileoff); symsize = swal(symtab->filesize); } else if (pclntab == 0) { pclntab = (MachSymSeg*)c; pclnoff = swal(pclntab->fileoff); pclnsize = swal(pclntab->filesize); } break; } cmdp += c->size; } if (textva == 0 || datava == 0) { free(cmd); free(cmdbuf); return 0; } /* compute entry by taking address after header - weird - BUG? */ settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff); setdata(fp, datava, datasize, dataoff, bsssize); if(symoff > 0) setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize); free(cmd); free(cmdbuf); return 1; bad: free(cmd); free(cmdbuf); return 0; }
static int machdotout(int fd, Fhdr *fp, ExecHdr *hp) { uvlong (*swav)(uvlong); uint32 (*swal)(uint32); ushort (*swab)(ushort); Machhdr *mp; MachCmd **cmd; MachSymSeg *symtab; MachSymSeg *pclntab; MachSeg64 *seg; MachSect64 *sect; MachSeg32 *seg32; MachSect32 *sect32; uvlong textsize, datasize, bsssize; uchar *cmdbuf; uchar *cmdp; int i, hdrsize; uint32 textva, textoff, datava, dataoff; mp = &hp->e.machhdr; if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) { werrstr("bad MACH executable type %#ux", leswal(mp->filetype)); return 0; } swab = leswab; swal = leswal; swav = leswav; mp->magic = swal(mp->magic); mp->cputype = swal(mp->cputype); mp->cpusubtype = swal(mp->cpusubtype); mp->filetype = swal(mp->filetype); mp->ncmds = swal(mp->ncmds); mp->sizeofcmds = swal(mp->sizeofcmds); mp->flags = swal(mp->flags); mp->reserved = swal(mp->reserved); hdrsize = 0; switch(mp->magic) { case 0xFEEDFACE: // 32-bit mach if (mp->cputype != MACH_CPU_TYPE_X86) { werrstr("bad MACH cpu type - not 386"); return 0; } if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) { werrstr("bad MACH cpu subtype - not 386"); return 0; } if (mp->filetype != MACH_EXECUTABLE_TYPE) { werrstr("bad MACH executable type"); return 0; } mach = &mi386; fp->type = FI386; hdrsize = 28; break; case 0xFEEDFACF: // 64-bit mach if (mp->cputype != MACH_CPU_TYPE_X86_64) { werrstr("bad MACH cpu type - not amd64"); return 0; } if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) { werrstr("bad MACH cpu subtype - not amd64"); return 0; } mach = &mamd64; fp->type = FAMD64; hdrsize = 32; break; default: werrstr("not mach %#ux", mp->magic); return 0; } cmdbuf = malloc(mp->sizeofcmds); seek(fd, hdrsize, 0); if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) { free(cmdbuf); return 0; } cmd = malloc(mp->ncmds * sizeof(MachCmd*)); cmdp = cmdbuf; textva = 0; textoff = 0; dataoff = 0; datava = 0; symtab = 0; pclntab = 0; textsize = datasize = bsssize = 0; for (i = 0; i < mp->ncmds; i++) { MachCmd *c; cmd[i] = (MachCmd*)cmdp; c = cmd[i]; c->type = swal(c->type); c->size = swal(c->size); switch(c->type) { case MACH_SEGMENT_32: if(mp->magic != 0xFEEDFACE) { werrstr("segment 32 in mach 64"); goto bad; } seg32 = (MachSeg32*)c; seg32->vmaddr = swav(seg32->vmaddr); seg32->vmsize = swav(seg32->vmsize); seg32->fileoff = swav(seg32->fileoff); seg32->filesize = swav(seg32->filesize); seg32->maxprot = swal(seg32->maxprot); seg32->initprot = swal(seg32->initprot); seg32->nsects = swal(seg32->nsects); seg32->flags = swal(seg32->flags); if (strcmp(seg32->segname, "__TEXT") == 0) { textva = seg32->vmaddr; textoff = seg32->fileoff; sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32)); if (strcmp(sect32->sectname, "__text") == 0) { textsize = swal(sect32->size); } else { werrstr("no text section"); goto bad; } } if (strcmp(seg32->segname, "__DATA") == 0) { datava = seg32->vmaddr; dataoff = seg32->fileoff; sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32)); if (strcmp(sect32->sectname, "__data") == 0) { datasize = swal(sect32->size); } else { werrstr("no data section"); goto bad; } sect32++; if (strcmp(sect32->sectname, "__nl_symbol_ptr") == 0) sect32++; if (strcmp(sect32->sectname, "__bss") == 0) { bsssize = swal(sect32->size); } else { werrstr("no bss section"); goto bad; } } break; case MACH_SEGMENT_64: if(mp->magic != 0xFEEDFACF) { werrstr("segment 32 in mach 64"); goto bad; } seg = (MachSeg64*)c; seg->vmaddr = swav(seg->vmaddr); seg->vmsize = swav(seg->vmsize); seg->fileoff = swav(seg->fileoff); seg->filesize = swav(seg->filesize); seg->maxprot = swal(seg->maxprot); seg->initprot = swal(seg->initprot); seg->nsects = swal(seg->nsects); seg->flags = swal(seg->flags); if (strcmp(seg->segname, "__TEXT") == 0) { textva = seg->vmaddr; textoff = seg->fileoff; sect = (MachSect64*)(cmdp + sizeof(MachSeg64)); if (strcmp(sect->sectname, "__text") == 0) { textsize = swav(sect->size); } else { werrstr("no text section"); goto bad; } } if (strcmp(seg->segname, "__DATA") == 0) { datava = seg->vmaddr; dataoff = seg->fileoff; sect = (MachSect64*)(cmdp + sizeof(MachSeg64)); if (strcmp(sect->sectname, "__data") == 0) { datasize = swav(sect->size); } else { werrstr("no data section"); goto bad; } sect++; if (strcmp(sect->sectname, "__bss") == 0) { bsssize = swav(sect->size); } else { werrstr("no bss section"); goto bad; } } break; case MACH_UNIXTHREAD: break; case MACH_SYMSEG: if (symtab == 0) symtab = (MachSymSeg*)c; else if (pclntab == 0) pclntab = (MachSymSeg*)c; break; } cmdp += c->size; } if (textva == 0 || datava == 0) { free(cmd); free(cmdbuf); return 0; } /* compute entry by taking address after header - weird - BUG? */ settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff); setdata(fp, datava, datasize, dataoff, bsssize); if(symtab != 0) setsym(fp, symtab->filesize, 0, pclntab? pclntab->filesize : 0, symtab->fileoff); free(cmd); free(cmdbuf); return 1; bad: free(cmd); free(cmdbuf); return 0; }
static int elfdotout(int fd, Fhdr *fp, ExecHdr *hp) { uint32 (*swal)(uint32); ushort (*swab)(ushort); Ehdr32 *ep; Phdr32 *ph; int i, it, id, is, phsz, shsz; Shdr32 *sh; /* bitswap the header according to the DATA format */ ep = &hp->e.elfhdr32; if(ep->ident[CLASS] != ELFCLASS32) { return elf64dotout(fd, fp, hp); } if(ep->ident[DATA] == ELFDATA2LSB) { swab = leswab; swal = leswal; } else if(ep->ident[DATA] == ELFDATA2MSB) { swab = beswab; swal = beswal; } else { werrstr("bad ELF encoding - not big or little endian"); return 0; } ep->type = swab(ep->type); ep->machine = swab(ep->machine); ep->version = swal(ep->version); ep->elfentry = swal(ep->elfentry); ep->phoff = swal(ep->phoff); ep->shoff = swal(ep->shoff); ep->flags = swal(ep->flags); ep->ehsize = swab(ep->ehsize); ep->phentsize = swab(ep->phentsize); ep->phnum = swab(ep->phnum); ep->shentsize = swab(ep->shentsize); ep->shnum = swab(ep->shnum); ep->shstrndx = swab(ep->shstrndx); if(ep->type != EXEC || ep->version != CURRENT) return 0; /* we could definitely support a lot more machines here */ fp->magic = ELF_MAG; fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; switch(ep->machine) { case I386: mach = &mi386; fp->type = FI386; break; case MIPS: mach = &mmips; fp->type = FMIPS; break; case SPARC64: mach = &msparc64; fp->type = FSPARC64; break; case POWER: mach = &mpower; fp->type = FPOWER; break; case ARM: mach = &marm; fp->type = FARM; break; default: return 0; } if(ep->phentsize != sizeof(Phdr32)) { werrstr("bad ELF header size"); return 0; } phsz = sizeof(Phdr32)*ep->phnum; ph = malloc(phsz); if(!ph) return 0; seek(fd, ep->phoff, 0); if(read(fd, ph, phsz) < 0) { free(ph); return 0; } hswal(ph, phsz/sizeof(uint32), swal); shsz = sizeof(Shdr32)*ep->shnum; sh = malloc(shsz); if(sh) { seek(fd, ep->shoff, 0); if(read(fd, sh, shsz) < 0) { free(sh); sh = 0; } else hswal(sh, shsz/sizeof(uint32), swal); } /* find text, data and symbols and install them */ it = id = is = -1; for(i = 0; i < ep->phnum; i++) { if(ph[i].type == LOAD && (ph[i].flags & (R|X)) == (R|X) && it == -1) it = i; else if(ph[i].type == LOAD && (ph[i].flags & (R|W)) == (R|W) && id == -1) id = i; else if(ph[i].type == NOPTYPE && is == -1) is = i; } if(it == -1 || id == -1) { /* * The SPARC64 boot image is something of an ELF hack. * Text+Data+BSS are represented by ph[0]. Symbols * are represented by ph[1]: * * filesz, memsz, vaddr, paddr, off * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff * ph[1] : symsz, lcsz, 0, 0, symoff */ if(ep->machine == SPARC64 && ep->phnum == 2) { uint32 txtaddr, txtsz, dataddr, bsssz; txtaddr = ph[0].vaddr | 0x80000000; txtsz = ph[0].filesz - ph[0].paddr; dataddr = txtaddr + txtsz; bsssz = ph[0].memsz - ph[0].filesz; settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); free(ph); return 1; } werrstr("No TEXT or DATA sections"); error: free(sh); free(ph); return 0; } settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); if(is != -1) setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); else if(sh != 0){ char *buf; uvlong symsize = 0; uvlong symoff = 0; uvlong pclnsz = 0; /* load shstrtab names */ buf = malloc(sh[ep->shstrndx].size); if (buf == 0) goto done; memset(buf, 0, sizeof buf); seek(fd, sh[ep->shstrndx].offset, 0); read(fd, buf, sh[ep->shstrndx].size); for(i = 0; i < ep->shnum; i++) { if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) { symsize = sh[i].size; symoff = sh[i].offset; } if (strcmp(&buf[sh[i].name], ".gopclntab") == 0) { if (sh[i].offset != symoff+symsize) { werrstr("pc line table not contiguous with symbol table"); free(buf); goto error; } pclnsz = sh[i].size; } } setsym(fp, symsize, 0, pclnsz, symoff); free(buf); } done: free(sh); free(ph); return 1; }
void main(int argc, char **argv) { int omode; volatile int quiet; char *s; char *name; quiet = 0; name = 0; outputinit(); maxoff = MAXOFF; omode = OREAD; ARGBEGIN{ default: usage(); case 'A': abort(); case 'k': kflag = 1; break; case 'w': omode = ORDWR; break; case 'I': s = ARGF(); if(s == 0) dprint("missing -I argument\n"); else Ipath = s; break; case 'm': name = ARGF(); if(name == 0) dprint("missing -m argument\n"); break; case 'q': quiet = 1; break; }ARGEND attachargs(argc, argv, omode, !quiet); dotmap = dumbmap(-1); /* * show initial state and drop into the execution loop. */ notify(fault); setsym(); if(setjmp(env) == 0){ if (pid || corhdr) setcor(); /* could get error */ if (correg && !quiet) { dprint("%s\n", mach->exc(cormap, correg)); printpc(); } } setjmp(env); if (executing) delbp(); executing = FALSE; for (;;) { flushbuf(); if (errmsg) { dprint(errmsg); printc('\n'); errmsg = 0; exitflg = 0; } if (mkfault) { mkfault=0; printc('\n'); prints(DBNAME); } clrinp(); rdc(); reread(); if (eof) { if (infile == STDIN) done(); iclose(-1, 0); eof = 0; longjmp(env, 1); } exitflg = 0; command(0, 0); reread(); if (rdc() != '\n') error("newline expected"); } }
/* * Read from Windows PE/COFF .exe file image. */ static int pedotout(int fd, Fhdr *fp, ExecHdr *hp) { uint32 start, magic; uint32 symtab, esymtab, pclntab, epclntab; IMAGE_FILE_HEADER fh; IMAGE_SECTION_HEADER sh; IMAGE_OPTIONAL_HEADER oh; PE64_IMAGE_OPTIONAL_HEADER oh64; uint8 sym[18]; uint32 *valp, ib, entry; int i, ohoffset; USED(hp); seek(fd, 0x3c, 0); if (readn(fd, &start, sizeof(start)) != sizeof(start)) { werrstr("crippled PE MSDOS header"); return 0; } start = leswal(start); seek(fd, start, 0); if (readn(fd, &magic, sizeof(magic)) != sizeof(magic)) { werrstr("no PE magic number found"); return 0; } if (beswal(magic) != 0x50450000) { /* "PE\0\0" */ werrstr("incorrect PE magic number"); return 0; } if (readn(fd, &fh, sizeof(fh)) != sizeof(fh)) { werrstr("crippled PE File Header"); return 0; } if (fh.PointerToSymbolTable == 0) { werrstr("zero pointer to COFF symbol table"); return 0; } ohoffset = seek(fd, 0, 1); if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) { werrstr("crippled PE Optional Header"); return 0; } switch(oh.Magic) { case 0x10b: // PE32 fp->type = FI386; ib = leswal(oh.ImageBase); entry = leswal(oh.AddressOfEntryPoint); break; case 0x20b: // PE32+ fp->type = FAMD64; seek(fd, ohoffset, 0); if (readn(fd, &oh64, sizeof(oh64)) != sizeof(oh64)) { werrstr("crippled PE32+ Optional Header"); return 0; } ib = leswal(oh64.ImageBase); entry = leswal(oh64.AddressOfEntryPoint); break; default: werrstr("invalid PE Optional Header magic number"); return 0; } fp->txtaddr = 0; fp->dataddr = 0; for (i=0; i<leswab(fh.NumberOfSections); i++) { if (readn(fd, &sh, sizeof(sh)) != sizeof(sh)) { werrstr("could not read Section Header %d", i+1); return 0; } if (match8(sh.Name, ".text")) settext(fp, ib+entry, ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData)); if (match8(sh.Name, ".data")) setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData)); } if (fp->txtaddr==0 || fp->dataddr==0) { werrstr("no .text or .data"); return 0; } seek(fd, leswal(fh.PointerToSymbolTable), 0); symtab = esymtab = pclntab = epclntab = 0; for (i=0; i<leswal(fh.NumberOfSymbols); i++) { if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) { werrstr("crippled COFF symbol %d", i); return 0; } valp = (uint32 *)&sym[8]; if (match8(sym, "symtab")) symtab = leswal(*valp); if (match8(sym, "esymtab")) esymtab = leswal(*valp); if (match8(sym, "pclntab")) pclntab = leswal(*valp); if (match8(sym, "epclntab")) epclntab = leswal(*valp); } if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) { werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table"); return 0; } setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab); return 1; }