Commit d08df513 authored by Alex Brainman's avatar Alex Brainman

8l/6l: pe fixes

- fixed length of amd64 .data pe section
  (don't need to include non-initialised data)

- use correct oh/oh64 variable when updating
  data directory in addexports

- simplify and cleanup

R=vcc, rsc
CC=golang-dev
https://golang.org/cl/4106044
parent 89cc4d78
...@@ -130,6 +130,7 @@ void ldobj1(Biobuf *f, char*, int64 len, char *pn); ...@@ -130,6 +130,7 @@ void ldobj1(Biobuf *f, char*, int64 len, char *pn);
void ldobj(Biobuf*, char*, int64, char*, int); void ldobj(Biobuf*, char*, int64, char*, int);
void ldelf(Biobuf*, char*, int64, char*); void ldelf(Biobuf*, char*, int64, char*);
void ldmacho(Biobuf*, char*, int64, char*); void ldmacho(Biobuf*, char*, int64, char*);
void ldpe(Biobuf*, char*, int64, char*);
void ldpkg(Biobuf*, char*, int64, char*, int); void ldpkg(Biobuf*, char*, int64, char*, int);
void mark(Sym *s); void mark(Sym *s);
void mkfwd(void); void mkfwd(void);
......
...@@ -49,6 +49,10 @@ static IMAGE_FILE_HEADER fh; ...@@ -49,6 +49,10 @@ static IMAGE_FILE_HEADER fh;
static IMAGE_OPTIONAL_HEADER oh; static IMAGE_OPTIONAL_HEADER oh;
static PE64_IMAGE_OPTIONAL_HEADER oh64; static PE64_IMAGE_OPTIONAL_HEADER oh64;
static IMAGE_SECTION_HEADER sh[16]; static IMAGE_SECTION_HEADER sh[16];
static IMAGE_DATA_DIRECTORY* dd;
#define set(n, v) (pe64 ? (oh64.n = v) : (oh.n = v))
#define put(v) (pe64 ? vputl(v) : lputl(v))
typedef struct Imp Imp; typedef struct Imp Imp;
struct Imp { struct Imp {
...@@ -106,18 +110,23 @@ addpesection(char *name, int sectsize, int filesize, Segment *s) ...@@ -106,18 +110,23 @@ addpesection(char *name, int sectsize, int filesize, Segment *s)
void void
peinit(void) peinit(void)
{ {
int32 l;
switch(thechar) { switch(thechar) {
// 64-bit architectures // 64-bit architectures
case '6': case '6':
pe64 = 1; pe64 = 1;
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh64)+sizeof(sh), PEFILEALIGN); l = sizeof(oh64);
dd = oh64.DataDirectory;
break; break;
// 32-bit architectures // 32-bit architectures
default: default:
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN); l = sizeof(oh);
dd = oh.DataDirectory;
break; break;
} }
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+l+sizeof(sh), PEFILEALIGN);
PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN); PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
nextsectoff = PESECTHEADR; nextsectoff = PESECTHEADR;
nextfileoff = PEFILEHEADR; nextfileoff = PEFILEHEADR;
...@@ -126,24 +135,20 @@ peinit(void) ...@@ -126,24 +135,20 @@ peinit(void)
static void static void
pewrite(void) pewrite(void)
{ {
int i, j;
seek(cout, 0, 0); seek(cout, 0, 0);
ewrite(cout, dosstub, sizeof dosstub); ewrite(cout, dosstub, sizeof dosstub);
strnput("PE", 4); strnput("PE", 4);
cflush();
for (i=0; i<sizeof(fh); i++) // TODO: This code should not assume that the
cput(((char*)&fh)[i]); // memory representation is little-endian or
if(pe64) { // that the structs are packed identically to
for (i=0; i<sizeof(oh64); i++) // their file representation.
cput(((char*)&oh64)[i]); ewrite(cout, &fh, sizeof fh);
} else { if(pe64)
for (i=0; i<sizeof(oh); i++) ewrite(cout, &oh64, sizeof oh64);
cput(((char*)&oh)[i]); else
} ewrite(cout, &oh, sizeof oh);
for (i=0; i<nsect; i++) ewrite(cout, &sh, nsect * sizeof sh[0]);
for (j=0; j<sizeof(sh[i]); j++)
cput(((char*)&sh[i])[j]);
} }
static void static void
...@@ -247,8 +252,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -247,8 +252,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
d->thunkoff = cpos() - n; d->thunkoff = cpos() - n;
for(m = d->ms; m != nil; m = m->next) for(m = d->ms; m != nil; m = m->next)
pe64 ? vputl(m->off) : lputl(m->off); put(m->off);
pe64 ? vputl(0): lputl(0); put(0);
} }
// add pe section and pad it at the end // add pe section and pad it at the end
...@@ -264,8 +269,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -264,8 +269,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
seek(cout, datsect->PointerToRawData + ftbase, 0); seek(cout, datsect->PointerToRawData + ftbase, 0);
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
for(m = d->ms; m != nil; m = m->next) for(m = d->ms; m != nil; m = m->next)
pe64 ? vputl(m->off) : lputl(m->off); put(m->off);
pe64 ? vputl(0): lputl(0); put(0);
} }
cflush(); cflush();
...@@ -286,17 +291,10 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -286,17 +291,10 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
cflush(); cflush();
// update data directory // update data directory
if(pe64) { dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
} else {
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
}
seek(cout, 0, 2); seek(cout, 0, 2);
} }
...@@ -340,7 +338,6 @@ addexports(vlong fileoff) ...@@ -340,7 +338,6 @@ addexports(vlong fileoff)
IMAGE_SECTION_HEADER *sect; IMAGE_SECTION_HEADER *sect;
IMAGE_EXPORT_DIRECTORY e; IMAGE_EXPORT_DIRECTORY e;
int size, i, va, va_name, va_addr, va_na, v; int size, i, va, va_name, va_addr, va_na, v;
Sym *s;
size = sizeof e + 10*nexport + strlen(outfile) + 1; size = sizeof e + 10*nexport + strlen(outfile) + 1;
for(i=0; i<nexport; i++) for(i=0; i<nexport; i++)
...@@ -352,8 +349,8 @@ addexports(vlong fileoff) ...@@ -352,8 +349,8 @@ addexports(vlong fileoff)
sect = addpesection(".edata", size, size, 0); sect = addpesection(".edata", size, size, 0);
sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ;
va = sect->VirtualAddress; va = sect->VirtualAddress;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize;
seek(cout, fileoff, 0); seek(cout, fileoff, 0);
va_name = va + sizeof e + nexport*4; va_name = va + sizeof e + nexport*4;
...@@ -395,7 +392,6 @@ addexports(vlong fileoff) ...@@ -395,7 +392,6 @@ addexports(vlong fileoff)
seek(cout, 0, 2); seek(cout, 0, 2);
} }
void void
dope(void) dope(void)
{ {
...@@ -463,7 +459,6 @@ addsymtable(void) ...@@ -463,7 +459,6 @@ addsymtable(void)
cflush(); cflush();
} }
void void
asmbpe(void) asmbpe(void)
{ {
...@@ -486,7 +481,7 @@ asmbpe(void) ...@@ -486,7 +481,7 @@ asmbpe(void)
IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ; IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
d = addpesection(".data", segdata.len, pe64 ? segdata.len : segdata.filelen, &segdata); d = addpesection(".data", segdata.len, segdata.filelen, &segdata);
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
...@@ -503,67 +498,39 @@ asmbpe(void) ...@@ -503,67 +498,39 @@ asmbpe(void)
fh.TimeDateStamp = time(0); fh.TimeDateStamp = time(0);
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED| fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED; IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
if (pe64) { if (pe64) {
fh.SizeOfOptionalHeader = sizeof(oh64); fh.SizeOfOptionalHeader = sizeof(oh64);
oh64.Magic = 0x20b; // PE32+ set(Magic, 0x20b); // PE32+
oh64.MajorLinkerVersion = 1;
oh64.MinorLinkerVersion = 0;
oh64.SizeOfCode = t->SizeOfRawData;
oh64.SizeOfInitializedData = d->SizeOfRawData;
oh64.SizeOfUninitializedData = 0;
oh64.AddressOfEntryPoint = entryvalue()-PEBASE;
oh64.BaseOfCode = t->VirtualAddress;
oh64.ImageBase = PEBASE;
oh64.SectionAlignment = PESECTALIGN;
oh64.FileAlignment = PEFILEALIGN;
oh64.MajorOperatingSystemVersion = 4;
oh64.MinorOperatingSystemVersion = 0;
oh64.MajorImageVersion = 1;
oh64.MinorImageVersion = 0;
oh64.MajorSubsystemVersion = 4;
oh64.MinorSubsystemVersion = 0;
oh64.SizeOfImage = nextsectoff;
oh64.SizeOfHeaders = PEFILEHEADR;
oh64.Subsystem = 3; // WINDOWS_CUI
oh64.SizeOfStackReserve = 0x00200000;
oh64.SizeOfStackCommit = 0x00001000;
oh64.SizeOfHeapReserve = 0x00100000;
oh64.SizeOfHeapCommit = 0x00001000;
oh64.NumberOfRvaAndSizes = 16;
} else { } else {
fh.SizeOfOptionalHeader = sizeof(oh); fh.SizeOfOptionalHeader = sizeof(oh);
fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE; fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
oh.Magic = 0x10b; // PE32 set(Magic, 0x10b); // PE32
oh.MajorLinkerVersion = 1;
oh.MinorLinkerVersion = 0;
oh.SizeOfCode = t->SizeOfRawData;
oh.SizeOfInitializedData = d->SizeOfRawData;
oh.SizeOfUninitializedData = 0;
oh.AddressOfEntryPoint = entryvalue()-PEBASE;
oh.BaseOfCode = t->VirtualAddress;
oh.BaseOfData = d->VirtualAddress; oh.BaseOfData = d->VirtualAddress;
oh.ImageBase = PEBASE;
oh.SectionAlignment = PESECTALIGN;
oh.FileAlignment = PEFILEALIGN;
oh.MajorOperatingSystemVersion = 4;
oh.MinorOperatingSystemVersion = 0;
oh.MajorImageVersion = 1;
oh.MinorImageVersion = 0;
oh.MajorSubsystemVersion = 4;
oh.MinorSubsystemVersion = 0;
oh.SizeOfImage = nextsectoff;
oh.SizeOfHeaders = PEFILEHEADR;
oh.Subsystem = 3; // WINDOWS_CUI
oh.SizeOfStackReserve = 0x00200000;
oh.SizeOfStackCommit = 0x00001000;
oh.SizeOfHeapReserve = 0x00100000;
oh.SizeOfHeapCommit = 0x00001000;
oh.NumberOfRvaAndSizes = 16;
} }
set(MajorLinkerVersion, 1);
set(MinorLinkerVersion, 0);
set(SizeOfCode, t->SizeOfRawData);
set(SizeOfInitializedData, d->SizeOfRawData);
set(SizeOfUninitializedData, 0);
set(AddressOfEntryPoint, entryvalue()-PEBASE);
set(BaseOfCode, t->VirtualAddress);
set(ImageBase, PEBASE);
set(SectionAlignment, PESECTALIGN);
set(FileAlignment, PEFILEALIGN);
set(MajorOperatingSystemVersion, 4);
set(MinorOperatingSystemVersion, 0);
set(MajorImageVersion, 1);
set(MinorImageVersion, 0);
set(MajorSubsystemVersion, 4);
set(MinorSubsystemVersion, 0);
set(SizeOfImage, nextsectoff);
set(SizeOfHeaders, PEFILEHEADR);
set(Subsystem, 3); // WINDOWS_CUI
set(SizeOfStackReserve, 0x00200000);
set(SizeOfStackCommit, 0x00001000);
set(SizeOfHeapReserve, 0x00100000);
set(SizeOfHeapCommit, 0x00001000);
set(NumberOfRvaAndSizes, 16);
pewrite(); pewrite();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment