static void addsymtable(void) { IMAGE_SECTION_HEADER *h; int i, size; LSym *s; fh.NumberOfSymbols = sizeof(symlabels)/sizeof(symlabels[0]); size = nextsymoff + 4 + 18*fh.NumberOfSymbols; h = addpesection(".symtab", size, size); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_DISCARDABLE; chksectoff(h, cpos()); fh.PointerToSymbolTable = cpos(); // put COFF symbol table for (i=0; i<fh.NumberOfSymbols; i++) { s = linkrlookup(ctxt, symlabels[i], 0); strnput(s->name, 8); lputl(datoff(s->value)); wputl(textsect); wputl(0x0308); // "array of structs" cput(2); // storage class: external cput(0); // no aux entries } // put COFF string table lputl(nextsymoff + 4); for (i=0; i<nextsymoff; i++) cput(symnames[i]); strnput("", h->SizeOfRawData - size); }
void addexports(vlong fileoff) { IMAGE_SECTION_HEADER *sect; IMAGE_EXPORT_DIRECTORY e; int size, i, va, va_name, va_addr, va_na, v; size = sizeof e + 10*nexport + strlen(outfile) + 1; for(i=0; i<nexport; i++) size += strlen(dexport[i]->dynimpname) + 1; if (nexport == 0) return; sect = addpesection(".edata", size, size, 0); sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; va = sect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; seek(cout, fileoff, 0); va_name = va + sizeof e + nexport*4; va_addr = va + sizeof e; va_na = va + sizeof e + nexport*8; e.Characteristics = 0; e.MajorVersion = 0; e.MinorVersion = 0; e.NumberOfFunctions = nexport; e.NumberOfNames = nexport; e.Name = va + sizeof e + nexport*10; // Program names. e.Base = 1; e.AddressOfFunctions = va_addr; e.AddressOfNames = va_name; e.AddressOfNameOrdinals = va_na; // put IMAGE_EXPORT_DIRECTORY for (i=0; i<sizeof(e); i++) cput(((char*)&e)[i]); // put EXPORT Address Table for(i=0; i<nexport; i++) lputl(dexport[i]->value - PEBASE); // put EXPORT Name Pointer Table v = e.Name + strlen(outfile)+1; for(i=0; i<nexport; i++) { lputl(v); v += strlen(dexport[i]->dynimpname)+1; } // put EXPORT Ordinal Table for(i=0; i<nexport; i++) wputl(i); // put Names strnput(outfile, strlen(outfile)+1); for(i=0; i<nexport; i++) strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1); strnput("", sect->SizeOfRawData - size); cflush(); seek(cout, 0, 2); }
void addpersrc(void) { IMAGE_SECTION_HEADER *h; uchar *p; uint32 val; Reloc *r; if(rsrcsym == nil) return; h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; chksectoff(h, cpos()); // relocation for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { p = rsrcsym->p + r->off; val = h->VirtualAddress + r->add; // 32-bit little-endian p[0] = val; p[1] = val>>8; p[2] = val>>16; p[3] = val>>24; } cwrite(rsrcsym->p, rsrcsym->size); strnput("", h->SizeOfRawData - rsrcsym->size); // update data directory dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize; }
static void pewrite(void) { int i, j; strnput("MZ", 0x3c); LPUT(0x40); // file offset to PE header strnput("PE", 4); for (i=0; i<sizeof(fh); i++) cput(((char*)&fh)[i]); for (i=0; i<sizeof(oh); i++) cput(((char*)&oh)[i]); for (i=0; i<nsect; i++) for (j=0; j<sizeof(sh[i]); j++) cput(((char*)&sh[i])[j]); }
static void addexcept(IMAGE_SECTION_HEADER *text) { IMAGE_SECTION_HEADER *pdata, *xdata; vlong startoff; uvlong n; LSym *sym; USED(text); if(thechar != '6') return; // write unwind info sym = linklookup(ctxt, "runtime.sigtramp", 0); startoff = cpos(); lputl(9); // version=1, flags=UNW_FLAG_EHANDLER, rest 0 lputl(sym->value - PEBASE); lputl(0); n = cpos() - startoff; xdata = addpesection(".xdata", n, n); xdata->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_CNT_INITIALIZED_DATA; chksectoff(xdata, startoff); strnput("", xdata->SizeOfRawData - n); // write a function table entry for the whole text segment startoff = cpos(); lputl(text->VirtualAddress); lputl(text->VirtualAddress + text->VirtualSize); lputl(xdata->VirtualAddress); n = cpos() - startoff; pdata = addpesection(".pdata", n, n); pdata->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_CNT_INITIALIZED_DATA; chksectoff(pdata, startoff); strnput("", pdata->SizeOfRawData - n); dd[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = pdata->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = pdata->VirtualSize; }
static void pewrite(void) { cseek(0); cwrite(dosstub, sizeof dosstub); strnput("PE", 4); // TODO: This code should not assume that the // memory representation is little-endian or // that the structs are packed identically to // their file representation. cwrite(&fh, sizeof fh); if(pe64) cwrite(&oh64, sizeof oh64); else cwrite(&oh, sizeof oh); cwrite(sh, nsect * sizeof sh[0]); }
static void addsymtable(void) { IMAGE_SECTION_HEADER *h; int i, size; if(nextsymoff == 0) return; size = nextsymoff + 4; h = addpesection(".symtab", size, size, 0); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_DISCARDABLE; fh.PointerToSymbolTable = cpos(); fh.NumberOfSymbols = 0; // put symbol string table lputl(size); for (i=0; i<nextsymoff; i++) cput(symnames[i]); strnput("", h->SizeOfRawData - size); cflush(); }
void asmb(void) { Prog *p; long t; Optab *o; long prevpc; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); /* emit text segment */ seek(cout, HEADR, 0); prevpc = pc = INITTEXT; for(p = firstp; p != P; p = p->link) { if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; if(p->from3.type == D_CONST) { for(; pc < p->pc; pc++) CPUT(0); } } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(asmout(p, o, 0)) { p = p->link; pc += 4; } pc += o->size; if (prevpc & (1<<31) && (pc & (1<<31)) == 0) { char *tn; tn = "??none??"; if(curtext != P && curtext->from.sym != S) tn = curtext->from.sym->name; Bprint(&bso, "%s: warning: text segment wrapped past 0\n", tn); } prevpc = pc; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); /* emit data segment */ curtext = P; switch(HEADTYPE) { case 6: /* * but first, for virtex 4, inject a jmp instruction after * other text: branch to absolute entry address (0xfffe2100). */ lput((18 << 26) | (0x03FFFFFC & entryvalue()) | 2); textsize += JMPSZ; cflush(); /* fall through */ case 0: case 1: case 2: case 5: seek(cout, HEADR+textsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4), 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096), 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100); else datblk(t, datsize-t); } symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 2: case 5: case 6: seek(cout, HEADR+textsize+datsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4)+datsize, 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f sp\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(dlm) asmdyn(); if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */ if((symsize+lcsize) & 1) CPUT(0); cflush(); } else if(dlm){ asmdyn(); cflush(); } /* back up and write the header */ seek(cout, 0L, 0); switch(HEADTYPE) { case 0: lput(0x1030107); /* magic and sections */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 1: lput(0x4a6f7921); /* Joy! */ lput(0x70656666); /* peff */ lput(0x70777063); /* pwpc */ lput(1); lput(0); lput(0); lput(0); lput(0); lput(0x30002); /*YY*/ lput(0); lput(~0); lput(0); lput(textsize+datsize); lput(textsize+datsize); lput(textsize+datsize); lput(0xd0); /* header size */ lput(0x10400); lput(~0); lput(0); lput(0xc); lput(0xc); lput(0xc); lput(0xc0); lput(0x01010400); lput(~0); lput(0); lput(0x38); lput(0x38); lput(0x38); lput(0x80); lput(0x04040400); lput(0); lput(1); lput(0); lput(~0); lput(0); lput(~0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0x3100); /* load address */ lput(0); lput(0); lput(0); /* whew! */ break; case 2: if(dlm) lput(0x80000000 | (4*21*21+7)); /* magic */ else lput(4*21*21+7); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: break; case 4: lput((0x1DFL<<16)|3L); /* magic and sections */ lput(time(0)); /* time and date */ lput(rnd(HEADR+textsize, 4096)+datsize); lput(symsize); /* nsyms */ lput((0x48L<<16)|15L); /* size of optional hdr and flags */ lput((0413<<16)|01L); /* magic and version */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(entryvalue()); /* va of entry */ lput(INITTEXT); /* va of base of text */ lput(INITDAT); /* va of base of data */ lput(INITDAT); /* address of TOC */ lput((1L<<16)|1); /* sn(entry) | sn(text) */ lput((2L<<16)|1); /* sn(data) | sn(toc) */ lput((0L<<16)|3); /* sn(loader) | sn(bss) */ lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */ lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */ lput(0); /* max stack allowed */ lput(0); /* max data allowed */ lput(0); lput(0); lput(0); /* reserved */ strnput(".text", 8); /* text segment */ lput(INITTEXT); /* address */ lput(INITTEXT); lput(textsize); lput(HEADR); lput(0L); lput(HEADR+textsize+datsize+symsize); lput(lcsize); /* line number size */ lput(0x20L); /* flags */ strnput(".data", 8); /* data segment */ lput(INITDAT); /* address */ lput(INITDAT); lput(datsize); lput(rnd(HEADR+textsize, 4096));/* sizes */ lput(0L); lput(0L); lput(0L); lput(0x40L); /* flags */ strnput(".bss", 8); /* bss segment */ lput(INITDAT+datsize); /* address */ lput(INITDAT+datsize); lput(bsssize); lput(0L); lput(0L); lput(0L); lput(0L); lput(0x80L); /* flags */ break; case 5: /* * intended for blue/gene */ elf32(POWER, ELFDATA2MSB, 0, nil); break; case 6: /* * intended for virtex 4 boot */ debug['S'] = 1; /* symbol table */ elf32(POWER, ELFDATA2MSB, 1, elf32jmp); break; } cflush(); }
void asmb(void) { Prog *p; long t; Optab *o; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); seek(cout, HEADR, 0); pc = INITTEXT; for(p = firstp; p != P; p = p->link) { if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; if(p->from3.type == D_CONST) { for(; pc < p->pc; pc++) CPUT(0); } } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(asmout(p, o, 0)) { p = p->link; pc += 4; } pc += o->size; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); curtext = P; switch(HEADTYPE) { case 0: case 1: case 2: case 5: seek(cout, HEADR+textsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4), 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096), 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100); else datblk(t, datsize-t); } symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 2: case 5: seek(cout, HEADR+textsize+datsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4)+datsize, 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f sp\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(dlm) asmdyn(); if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */ if((symsize+lcsize) & 1) CPUT(0); cflush(); } else if(dlm){ asmdyn(); cflush(); } seek(cout, 0L, 0); switch(HEADTYPE) { case 0: lput(0x1030107); /* magic and sections */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 1: lput(0x4a6f7921); /* Joy! */ lput(0x70656666); /* peff */ lput(0x70777063); /* pwpc */ lput(1); lput(0); lput(0); lput(0); lput(0); lput(0x30002); /*YY*/ lput(0); lput(~0); lput(0); lput(textsize+datsize); lput(textsize+datsize); lput(textsize+datsize); lput(0xd0); /* header size */ lput(0x10400); lput(~0); lput(0); lput(0xc); lput(0xc); lput(0xc); lput(0xc0); lput(0x01010400); lput(~0); lput(0); lput(0x38); lput(0x38); lput(0x38); lput(0x80); lput(0x04040400); lput(0); lput(1); lput(0); lput(~0); lput(0); lput(~0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0x3100); /* load address */ lput(0); lput(0); lput(0); /* whew! */ break; case 2: if(dlm) lput(0x80000000 | (4*21*21+7)); /* magic */ else lput(4*21*21+7); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: break; case 4: lput((0x1DFL<<16)|3L); /* magic and sections */ lput(time(0)); /* time and date */ lput(rnd(HEADR+textsize, 4096)+datsize); lput(symsize); /* nsyms */ lput((0x48L<<16)|15L); /* size of optional hdr and flags */ lput((0413<<16)|01L); /* magic and version */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(entryvalue()); /* va of entry */ lput(INITTEXT); /* va of base of text */ lput(INITDAT); /* va of base of data */ lput(INITDAT); /* address of TOC */ lput((1L<<16)|1); /* sn(entry) | sn(text) */ lput((2L<<16)|1); /* sn(data) | sn(toc) */ lput((0L<<16)|3); /* sn(loader) | sn(bss) */ lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */ lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */ lput(0); /* max stack allowed */ lput(0); /* max data allowed */ lput(0); lput(0); lput(0); /* reserved */ strnput(".text", 8); /* text segment */ lput(INITTEXT); /* address */ lput(INITTEXT); lput(textsize); lput(HEADR); lput(0L); lput(HEADR+textsize+datsize+symsize); lput(lcsize); /* line number size */ lput(0x20L); /* flags */ strnput(".data", 8); /* data segment */ lput(INITDAT); /* address */ lput(INITDAT); lput(datsize); lput(rnd(HEADR+textsize, 4096));/* sizes */ lput(0L); lput(0L); lput(0L); lput(0x40L); /* flags */ strnput(".bss", 8); /* bss segment */ lput(INITDAT+datsize); /* address */ lput(INITDAT+datsize); lput(bsssize); lput(0L); lput(0L); lput(0L); lput(0L); lput(0x80L); /* flags */ break; case 5: strnput("\177ELF", 4); /* e_ident */ CPUT(1); /* class = 32 bit */ CPUT(2); /* data = MSB */ CPUT(1); /* version = CURRENT */ strnput("", 9); lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */ lput(1L); /* version = CURRENT */ lput(entryvalue() & ~KMASK); /* entry vaddr */ lput(52L); /* offset to first phdr */ lput(0L); /* offset to first shdr */ lput(0L); /* flags = PPC */ lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ lput((3L<<16)|0L); /* # Phdrs & Shdr size */ lput((0L<<16)|0L); /* # Shdrs & shdr string size */ lput(1L); /* text - type = PT_LOAD */ lput(HEADR); /* file offset */ lput(INITTEXT & ~KMASK); /* vaddr */ lput(INITTEXT); /* paddr */ lput(textsize); /* file size */ lput(textsize); /* memory size */ lput(0x05L); /* protections = RX */ lput(0x10000L); /* alignment */ lput(1L); /* data - type = PT_LOAD */ lput(HEADR+textsize); /* file offset */ lput(INITDAT & ~KMASK); /* vaddr */ lput(INITDAT); /* paddr */ lput(datsize); /* file size */ lput(datsize); /* memory size */ lput(0x07L); /* protections = RWX */ lput(0x10000L); /* alignment */ lput(0L); /* data - type = PT_NULL */ lput(HEADR+textsize+datsize); /* file offset */ lput(0L); lput(0L); lput(symsize); /* symbol table size */ lput(lcsize); /* line number size */ lput(0x04L); /* protections = R */ lput(0x04L); /* alignment code?? */ break; } cflush(); }
static void add_import_table(void) { IMAGE_IMPORT_DESCRIPTOR ds[2], *d; char *dllname = "kernel32.dll"; struct { char *name; uint32 thunk; } *f, fs[] = { { "GetProcAddress", 0 }, { "LoadLibraryExA", 0 }, { 0, 0 } }; uint32 size = 0; memset(ds, 0, sizeof(ds)); size += sizeof(ds); ds[0].Name = size; size += strlen(dllname) + 1; for(f=fs; f->name; f++) { f->thunk = size; size += sizeof(uint16) + strlen(f->name) + 1; } ds[0].FirstThunk = size; for(f=fs; f->name; f++) size += sizeof(fs[0].thunk); IMAGE_SECTION_HEADER *isect; isect = new_section(".idata", size, 0); isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; uint32 va = isect->VirtualAddress; oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = va; oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; ds[0].Name += va; ds[0].FirstThunk += va; for(f=fs; f->name; f++) f->thunk += va; vlong off = seek(cout, 0, 1); seek(cout, 0, 2); for(d=ds; ; d++) { lputl(d->OriginalFirstThunk); lputl(d->TimeDateStamp); lputl(d->ForwarderChain); lputl(d->Name); lputl(d->FirstThunk); if(!d->Name) break; } strput(dllname); for(f=fs; f->name; f++) { wputl(0); strput(f->name); } for(f=fs; f->name; f++) lputl(f->thunk); strnput("", isect->SizeOfRawData - size); cflush(); seek(cout, off, 0); }
static void addimports(IMAGE_SECTION_HEADER *datsect) { IMAGE_SECTION_HEADER *isect; uvlong n, oftbase, ftbase; vlong startoff, endoff; Imp *m; Dll *d; LSym* dynamic; startoff = cpos(); dynamic = linklookup(ctxt, ".windynamic", 0); // skip import descriptor table (will write it later) n = 0; for(d = dr; d != nil; d = d->next) n++; cseek(startoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1)); // write dll names for(d = dr; d != nil; d = d->next) { d->nameoff = cpos() - startoff; strput(d->name); } // write function names for(d = dr; d != nil; d = d->next) { for(m = d->ms; m != nil; m = m->next) { m->off = nextsectoff + cpos() - startoff; wputl(0); // hint strput(m->s->extname); } } // write OriginalFirstThunks oftbase = cpos() - startoff; n = cpos(); for(d = dr; d != nil; d = d->next) { d->thunkoff = cpos() - n; for(m = d->ms; m != nil; m = m->next) put(m->off); put(0); } // add pe section and pad it at the end n = cpos() - startoff; isect = addpesection(".idata", n, n); isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; chksectoff(isect, startoff); strnput("", isect->SizeOfRawData - n); endoff = cpos(); // write FirstThunks (allocated in .data section) ftbase = dynamic->value - datsect->VirtualAddress - PEBASE; cseek(datsect->PointerToRawData + ftbase); for(d = dr; d != nil; d = d->next) { for(m = d->ms; m != nil; m = m->next) put(m->off); put(0); } // finally write import descriptor table cseek(startoff); for(d = dr; d != nil; d = d->next) { lputl(isect->VirtualAddress + oftbase + d->thunkoff); lputl(0); lputl(0); lputl(isect->VirtualAddress + d->nameoff); lputl(datsect->VirtualAddress + ftbase + d->thunkoff); } lputl(0); //end lputl(0); lputl(0); lputl(0); lputl(0); // update data directory dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size; cseek(endoff); }
void asmb(void) { Prog *p; long t; Optab *o; long prevpc; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); /* emit text segment */ seek(cout, HEADR, 0); prevpc = pc = INITTEXT; for(p = firstp; p != P; p = p->link) { if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; if(p->from3.type == D_CONST) { for(; pc < p->pc; pc++) CPUT(0); } } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(asmout(p, o, 0)) { p = p->link; pc += 4; } pc += o->size; if (prevpc & (1<<31) && (pc & (1<<31)) == 0) { char *tn; tn = "?none?"; if(curtext != P && curtext->from.sym != S) tn = curtext->from.sym->name; Bprint(&bso, "%s: warning: text segment wrapped past 0\n", tn); } prevpc = pc; } /* for virtex 4, inject a jmp instruction after other text */ if(HEADTYPE == 6) /* branch to absolute entry address (0xfffe2100) */ lput((18 << 26) | (0x03FFFFFC & entryvalue()) | 2); if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); /* emit data segment */ curtext = P; switch(HEADTYPE) { case 6: textsize += JMPSZ; /* fall through */ case 0: case 1: case 2: case 5: seek(cout, HEADR+textsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4), 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096), 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100); else datblk(t, datsize-t); } symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 2: case 5: case 6: seek(cout, HEADR+textsize+datsize, 0); break; case 3: seek(cout, rnd(HEADR+textsize, 4)+datsize, 0); break; case 4: seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f sp\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(dlm) asmdyn(); if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */ if((symsize+lcsize) & 1) CPUT(0); cflush(); } else if(dlm){ asmdyn(); cflush(); } /* back up and write the header */ seek(cout, 0L, 0); switch(HEADTYPE) { case 0: lput(0x1030107); /* magic and sections */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 1: lput(0x4a6f7921); /* Joy! */ lput(0x70656666); /* peff */ lput(0x70777063); /* pwpc */ lput(1); lput(0); lput(0); lput(0); lput(0); lput(0x30002); /*YY*/ lput(0); lput(~0); lput(0); lput(textsize+datsize); lput(textsize+datsize); lput(textsize+datsize); lput(0xd0); /* header size */ lput(0x10400); lput(~0); lput(0); lput(0xc); lput(0xc); lput(0xc); lput(0xc0); lput(0x01010400); lput(~0); lput(0); lput(0x38); lput(0x38); lput(0x38); lput(0x80); lput(0x04040400); lput(0); lput(1); lput(0); lput(~0); lput(0); lput(~0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0); lput(0x3100); /* load address */ lput(0); lput(0); lput(0); /* whew! */ break; case 2: if(dlm) lput(0x80000000 | (4*21*21+7)); /* magic */ else lput(4*21*21+7); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: break; case 4: lput((0x1DFL<<16)|3L); /* magic and sections */ lput(time(0)); /* time and date */ lput(rnd(HEADR+textsize, 4096)+datsize); lput(symsize); /* nsyms */ lput((0x48L<<16)|15L); /* size of optional hdr and flags */ lput((0413<<16)|01L); /* magic and version */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(entryvalue()); /* va of entry */ lput(INITTEXT); /* va of base of text */ lput(INITDAT); /* va of base of data */ lput(INITDAT); /* address of TOC */ lput((1L<<16)|1); /* sn(entry) | sn(text) */ lput((2L<<16)|1); /* sn(data) | sn(toc) */ lput((0L<<16)|3); /* sn(loader) | sn(bss) */ lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */ lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */ lput(0); /* max stack allowed */ lput(0); /* max data allowed */ lput(0); lput(0); lput(0); /* reserved */ strnput(".text", 8); /* text segment */ lput(INITTEXT); /* address */ lput(INITTEXT); lput(textsize); lput(HEADR); lput(0L); lput(HEADR+textsize+datsize+symsize); lput(lcsize); /* line number size */ lput(0x20L); /* flags */ strnput(".data", 8); /* data segment */ lput(INITDAT); /* address */ lput(INITDAT); lput(datsize); lput(rnd(HEADR+textsize, 4096));/* sizes */ lput(0L); lput(0L); lput(0L); lput(0x40L); /* flags */ strnput(".bss", 8); /* bss segment */ lput(INITDAT+datsize); /* address */ lput(INITDAT+datsize); lput(bsssize); lput(0L); lput(0L); lput(0L); lput(0L); lput(0x80L); /* flags */ break; case 5: /* * customised for blue/gene, * notably the alignment and KMASK masking. */ strnput("\177ELF", 4); /* e_ident */ CPUT(1); /* class = 32 bit */ CPUT(2); /* data = MSB */ CPUT(1); /* version = CURRENT */ strnput("", 9); lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */ lput(1L); /* version = CURRENT */ lput(entryvalue() & ~KMASK); /* entry vaddr */ lput(52L); /* offset to first phdr */ if(debug['S']){ lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */ lput(0L); /* flags = PPC */ lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ lput((3L<<16)|40L); /* # Phdrs & Shdr size */ lput((3L<<16)|2L); /* # Shdrs & shdr string size */ } else{ lput(0L); lput(0L); /* flags = PPC */ lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ lput((3L<<16)|0L); /* # Phdrs & Shdr size */ lput((3L<<16)|0L); /* # Shdrs & shdr string size */ } lput(1L); /* text - type = PT_LOAD */ lput(HEADR); /* file offset */ lput(INITTEXT & ~KMASK); /* vaddr */ lput(INITTEXT); /* paddr */ lput(textsize); /* file size */ lput(textsize); /* memory size */ lput(0x05L); /* protections = RX */ lput(0x10000L); /* alignment */ lput(1L); /* data - type = PT_LOAD */ lput(HEADR+textsize); /* file offset */ lput(INITDAT & ~KMASK); /* vaddr */ lput(INITDAT); /* paddr */ lput(datsize); /* file size */ lput(datsize); /* memory size */ lput(0x07L); /* protections = RWX */ lput(0x10000L); /* alignment */ lput(0L); /* data - type = PT_NULL */ lput(HEADR+textsize+datsize); /* file offset */ lput(0L); /* vaddr */ lput(0L); /* paddr */ lput(symsize); /* symbol table size */ lput(lcsize); /* line number size */ lput(0x04L); /* protections = R */ lput(0x04L); /* alignment code?? */ cflush(); if(!debug['S']) break; seek(cout, HEADR+textsize+datsize+symsize, 0); lput(1); /* Section name (string tbl index) */ lput(1); /* Section type */ lput(2|4); /* Section flags */ lput(INITTEXT & ~KMASK); /* Section virtual addr at execution */ lput(HEADR); /* Section file offset */ lput(textsize); /* Section size in bytes */ lput(0); /* Link to another section */ lput(0); /* Additional section information */ lput(0x10000L); /* Section alignment */ lput(0); /* Entry size if section holds table */ lput(7); /* Section name (string tbl index) */ lput(1); /* Section type */ lput(2|1); /* Section flags */ lput(INITDAT & ~KMASK); /* Section virtual addr at execution */ lput(HEADR+textsize); /* Section file offset */ lput(datsize); /* Section size in bytes */ lput(0); /* Link to another section */ lput(0); /* Additional section information */ lput(0x10000L); /* Section alignment */ lput(0); /* Entry size if section holds table */ /* string section header */ lput(12); /* Section name (string tbl index) */ lput(3); /* Section type */ lput(1 << 5); /* Section flags */ lput(0); /* Section virtual addr at execution */ lput(HEADR+textsize+datsize+symsize+3*40); /* Section file offset */ lput(14); /* Section size in bytes */ lput(0); /* Link to another section */ lput(0); /* Additional section information */ lput(1); /* Section alignment */ lput(0); /* Entry size if section holds table */ /* string table */ cput(0); strnput(".text", 5); cput(0); strnput(".data", 5); cput(0); strnput(".strtab", 7); cput(0); cput(0); break; case 6: /* * customised for virtex 4 boot, * notably the alignment and KMASK masking. */ strnput("\177ELF", 4); /* e_ident */ CPUT(1); /* class = 32 bit */ CPUT(2); /* data = MSB */ CPUT(1); /* version = CURRENT */ strnput("", 9); lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */ lput(1L); /* version = CURRENT */ lput(entryvalue()); /* entry vaddr */ lput(52L); /* offset to first phdr */ debug['S'] = 1; /* no symbol table */ if(debug['S']){ lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */ lput(0L); /* flags = PPC */ lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ lput((4L<<16)|40L); /* # Phdrs & Shdr size */ lput((4L<<16)|2L); /* # Shdrs & shdr string size */ } else{ lput(0L); lput(0L); /* flags = PPC */ lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ lput((4L<<16)|0L); /* # Phdrs & Shdr size */ lput((4L<<16)|0L); /* # Shdrs & shdr string size */ } lput(1L); /* text - type = PT_LOAD */ lput(HEADR); /* file offset */ lput(INITTEXT); /* vaddr */ lput(INITTEXT); /* paddr */ lput(textsize-JMPSZ); /* file size */ lput(textsize-JMPSZ); /* memory size */ lput(0x05L); /* protections = RX */ lput(0); /* alignment */ lput(1L); /* data - type = PT_LOAD */ lput(HEADR+textsize); /* file offset */ lput(INITDAT); /* vaddr */ lput(INITDAT); /* paddr */ lput(datsize); /* file size */ lput(datsize+bsssize); /* memory size */ lput(0x07L); /* protections = RWX */ lput(0); /* alignment */ lput(0L); /* data - type = PT_NULL */ lput(HEADR+textsize+datsize); /* file offset */ lput(0L); /* vaddr */ lput(0L); /* paddr */ lput(symsize); /* symbol table size */ lput(lcsize); /* line number size */ lput(0x04L); /* protections = R */ lput(0x04L); /* alignment code?? */ /* add tiny text section at end with jmp to start */ lput(1L); /* text - type = PT_LOAD */ lput(HEADR+textsize-JMPSZ); /* file offset */ lput(0xFFFFFFFC); /* vaddr */ lput(0xFFFFFFFC); /* paddr */ lput(JMPSZ); /* file size */ lput(JMPSZ); /* memory size */ lput(0x05L); /* protections = RX */ lput(0); /* disable alignment */ cflush(); break; } cflush(); }
void asmb(void) { Prog *p; int32 t, etext; int np; vlong va, fo, w, symo; int strtabsize; vlong symdatva = 0x99LL<<24; Optab *o; strtabsize = 0; symo = 0; if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); OFFSET = HEADR; seek(cout, OFFSET, 0); pc = INITTEXT; for(p = firstp; p != P; p = p->link) { setarch(p); if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; } if(p->pc != pc) { diag("phase error %lux sb %lux", p->pc, pc); if(!debug['a']) prasm(curp); pc = p->pc; } curp = p; o = oplook(p); /* could probably avoid this call */ if(thumb) thumbasmout(p, o); else asmout(p, o); pc += o->size; } while(pc-INITTEXT < textsize) { cput(0); pc++; } if(debug['a']) Bprint(&bso, "\n"); Bflush(&bso); cflush(); /* output strings in text segment */ etext = INITTEXT + textsize; for(t = pc; t < etext; t += sizeof(buf)-100) { if(etext-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 1); else datblk(t, etext-t, 1); } /* output section header strings */ curtext = P; switch(HEADTYPE) { case 0: case 1: case 2: case 5: OFFSET = HEADR+textsize; seek(cout, OFFSET, 0); break; case 3: OFFSET = rnd(HEADR+textsize, 4096); seek(cout, OFFSET, 0); break; case 6: seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); strtabsize = linuxstrtable(); cflush(); t = rnd(HEADR+textsize, INITRND); seek(cout, t, 0); break; } if(dlm){ char buf[8]; write(cout, buf, INITDAT-textsize); textsize = INITDAT; } for(t = 0; t < datsize; t += sizeof(buf)-100) { if(datsize-t > sizeof(buf)-100) datblk(t, sizeof(buf)-100, 0); else datblk(t, datsize-t, 0); } cflush(); /* output symbol table */ symsize = 0; lcsize = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { case 0: case 1: case 4: case 5: debug['s'] = 1; break; case 2: OFFSET = HEADR+textsize+datsize; seek(cout, OFFSET, 0); break; case 3: OFFSET += rnd(datsize, 4096); seek(cout, OFFSET, 0); break; case 6: symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; symo = rnd(symo, INITRND); seek(cout, symo + 8, 0); break; } if(!debug['s']) asmsym(); if(debug['v']) Bprint(&bso, "%5.2f pc\n", cputime()); Bflush(&bso); if(!debug['s']) asmlc(); if(!debug['s']) asmthumbmap(); if(dlm) asmdyn(); cflush(); } else if(dlm){ seek(cout, HEADR+textsize+datsize, 0); asmdyn(); cflush(); } curtext = P; if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); OFFSET = 0; seek(cout, OFFSET, 0); switch(HEADTYPE) { case 0: /* no header */ break; case 1: /* aif for risc os */ lputl(0xe1a00000); /* NOP - decompress code */ lputl(0xe1a00000); /* NOP - relocation code */ lputl(0xeb000000 + 12); /* BL - zero init code */ lputl(0xeb000000 + (entryvalue() - INITTEXT + HEADR - 12 - 8) / 4); /* BL - entry code */ lputl(0xef000011); /* SWI - exit code */ lputl(textsize+HEADR); /* text size */ lputl(datsize); /* data size */ lputl(0); /* sym size */ lputl(bsssize); /* bss size */ lputl(0); /* sym type */ lputl(INITTEXT-HEADR); /* text addr */ lputl(0); /* workspace - ignored */ lputl(32); /* addr mode / data addr flag */ lputl(0); /* data addr */ for(t=0; t<2; t++) lputl(0); /* reserved */ for(t=0; t<15; t++) lputl(0xe1a00000); /* NOP - zero init code */ lputl(0xe1a0f00e); /* B (R14) - zero init return */ break; case 2: /* plan 9 */ if(dlm) lput(0x80000000|0x647); /* magic */ else lput(0x647); /* magic */ lput(textsize); /* sizes */ lput(datsize); lput(bsssize); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case 3: /* boot for NetBSD */ lput((143<<16)|0413); /* magic */ lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(datsize, 4096)); lputl(bsssize); lputl(symsize); /* nsyms */ lputl(entryvalue()); /* va of entry */ lputl(0L); lputl(0L); break; case 4: /* boot for IXP1200 */ break; case 5: /* boot for ipaq */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; case 6: /* elf arm */ strnput("\177ELF", 4); /* e_ident */ cput(1); /* class = 32 bit */ cput(1); /* data = LSB */ cput(1); /* version = CURRENT */ strnput("", 9); wputl(2); /* type = EXEC */ wputl(40); /* machine = ARM */ lputl(1L); /* version = CURRENT */ lputl(entryvalue()); /* entry vaddr */ lputl(52L); /* offset to first phdr */ np = 3; if(!debug['s']) np++; lputl(52L+32*np); /* offset to first shdr */ lputl(0L); /* processor specific flags */ wputl(52); /* Ehdr size */ wputl(32); /* Phdr size */ wputl(np); /* # of Phdrs */ wputl(40); /* Shdr size */ if (!debug['s']) wputl(7); /* # of Shdrs */ else wputl(5); /* # of Shdrs */ wputl(4); /* Shdr with strings */ fo = 0; va = INITTEXT & ~((vlong)INITRND - 1); w = HEADR+textsize; linuxphdr(1, /* text - type = PT_LOAD */ 1L+4L, /* text - flags = PF_X+PF_R */ 0, /* file offset */ va, /* vaddr */ va, /* paddr */ w, /* file size */ w, /* memory size */ INITRND); /* alignment */ fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); w = datsize; linuxphdr(1, /* data - type = PT_LOAD */ 2L+4L, /* data - flags = PF_W+PF_R */ fo, /* file offset */ va, /* vaddr */ va, /* paddr */ w, /* file size */ w+bsssize, /* memory size */ INITRND); /* alignment */ if(!debug['s']) { linuxphdr(1, /* data - type = PT_LOAD */ 2L+4L, /* data - flags = PF_W+PF_R */ symo, /* file offset */ symdatva, /* vaddr */ symdatva, /* paddr */ 8+symsize+lcsize, /* file size */ 8+symsize+lcsize, /* memory size */ INITRND); /* alignment */ } linuxphdr(0x6474e551, /* gok - type = gok */ 1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ 0, /* file offset */ 0, /* vaddr */ 0, /* paddr */ 0, /* file size */ 0, /* memory size */ 8); /* alignment */ linuxshdr(nil, /* name */ 0, /* type */ 0, /* flags */ 0, /* addr */ 0, /* off */ 0, /* size */ 0, /* link */ 0, /* info */ 0, /* align */ 0); /* entsize */ stroffset = 1; /* 0 means no name, so start at 1 */ fo = HEADR; va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; w = textsize; linuxshdr(".text", /* name */ 1, /* type */ 6, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); w = datsize; linuxshdr(".data", /* name */ 1, /* type */ 3, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ fo += w; va += w; w = bsssize; linuxshdr(".bss", /* name */ 8, /* type */ 3, /* flags */ va, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 8, /* align */ 0); /* entsize */ w = strtabsize; linuxshdr(".shstrtab", /* name */ 3, /* type */ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 0); /* entsize */ if (debug['s']) break; fo = symo+8; w = symsize; linuxshdr(".gosymtab", /* name */ 1, /* type 1 = SHT_PROGBITS */ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 24); /* entsize */ fo += w; w = lcsize; linuxshdr(".gopclntab", /* name */ 1, /* type 1 = SHT_PROGBITS*/ 0, /* flags */ 0, /* addr */ fo, /* off */ w, /* size */ 0, /* link */ 0, /* info */ 1, /* align */ 24); /* entsize */ break; } cflush(); if(debug['c']){ print("textsize=%ld\n", textsize); print("datsize=%ld\n", datsize); print("bsssize=%ld\n", bsssize); print("symsize=%ld\n", symsize); print("lcsize=%ld\n", lcsize); print("total=%ld\n", textsize+datsize+bsssize+symsize+lcsize); } }