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 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(void) { 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]->extname) + 1; if (nexport == 0) return; sect = addpesection(".edata", size, size); sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; chksectoff(sect, cpos()); va = sect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; 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]->extname)+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]->extname, strlen(dexport[i]->extname)+1); strnput("", sect->SizeOfRawData - size); }
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 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); }