int _read5(Biobuf *bp, Prog *p) { int as, n; Addr a; as = BGETC(bp); /* as */ if(as < 0) return 0; p->kind = aNone; p->sig = 0; if(as == ANAME || as == ASIGNAME){ if(as == ASIGNAME){ Bread(bp, &p->sig, 4); p->sig = leswal(p->sig); } p->kind = aName; p->type = type2char(BGETC(bp)); /* type */ p->sym = BGETC(bp); /* sym */ n = 0; for(;;) { as = BGETC(bp); if(as < 0) return 0; n++; if(as == 0) break; } p->id = malloc(n); if(p->id == 0) return 0; Bseek(bp, -n, 1); if(Bread(bp, p->id, n) != n) return 0; return 1; } if(as == ATEXT) p->kind = aText; else if(as == AGLOBL) p->kind = aData; skip(bp, 6); /* scond(1), reg(1), lineno(4) */ a = addr(bp); addr(bp); if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) p->kind = aNone; p->sym = a.sym; return 1; }
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 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; }
/* * 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; }