1
0
mirror of https://github.com/golang/go synced 2024-11-22 06:24:38 -07:00

8l: pe generation fixes

Restore ability to have different file and
section alignment in generated pe file.

Stop generating .bss pe section, it is
part of .data now.

Some code refactoring.

R=rsc, vcc
CC=golang-dev
https://golang.org/cl/2731041
This commit is contained in:
Alex Brainman 2010-11-02 10:56:56 +11:00
parent ce98044523
commit 8f8f625cb1
5 changed files with 70 additions and 59 deletions

View File

@ -397,10 +397,14 @@ asmb(void)
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
break; break;
Elfsym: Elfsym:
case 10:
symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
case 10:
// TODO(brainman): not sure what symo meant to be, but it is not used for Windows PE for now anyway
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
break;
} }
if(HEADTYPE != 10 && !debug['s']) { if(HEADTYPE != 10 && !debug['s']) {
seek(cout, symo, 0); seek(cout, symo, 0);

View File

@ -265,13 +265,13 @@ main(int argc, char *argv[])
break; break;
case 10: /* PE executable */ case 10: /* PE executable */
peinit(); peinit();
HEADR = PERESERVE; HEADR = PEFILEHEADR;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = PEBASE+0x1000; INITTEXT = PEBASE+PESECTHEADR;
if(INITDAT == -1) if(INITDAT == -1)
INITDAT = 0; INITDAT = 0;
if(INITRND == -1) if(INITRND == -1)
INITRND = 4096; INITRND = PESECTALIGN;
break; break;
case 11: case 11:
tlsoffset = 0; tlsoffset = 0;
@ -332,8 +332,6 @@ main(int argc, char *argv[])
dodata(); dodata();
address(); address();
reloc(); reloc();
if(HEADTYPE == 10)
dope();
asmb(); asmb();
undef(); undef();
if(debug['v']) { if(debug['v']) {

View File

@ -33,6 +33,7 @@
#include "l.h" #include "l.h"
#include "../ld/lib.h" #include "../ld/lib.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/pe.h"
/* /*
* divide-and-conquer list-link * divide-and-conquer list-link
@ -736,6 +737,8 @@ address(void)
segdata.rwx = 06; segdata.rwx = 06;
segdata.vaddr = va; segdata.vaddr = va;
segdata.fileoff = va - segtext.vaddr + segtext.fileoff; segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
if(thechar == '8' && HEADTYPE == 10) // Windows PE
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
for(s=segdata.sect; s != nil; s=s->next) { for(s=segdata.sect; s != nil; s=s->next) {
s->vaddr = va; s->vaddr = va;
va += s->len; va += s->len;

View File

@ -33,18 +33,20 @@ static char dosstub[] =
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
int32 PESECTHEADR;
int32 PEFILEHEADR;
static int pe64; static int pe64;
static int nsect; static int nsect;
static int sect_virt_begin; static int nextsectoff;
static int sect_raw_begin = PERESERVE; static int nextfileoff;
static IMAGE_FILE_HEADER fh; static IMAGE_FILE_HEADER fh;
static IMAGE_OPTIONAL_HEADER oh; static IMAGE_OPTIONAL_HEADER oh;
static IMAGE_SECTION_HEADER sh[16]; static IMAGE_SECTION_HEADER sh[16];
static IMAGE_SECTION_HEADER *textsect, *datsect, *bsssect;
static IMAGE_SECTION_HEADER* static IMAGE_SECTION_HEADER*
new_section(char *name, int size, int noraw) addpesection(char *name, int sectsize, int filesize, Segment *s)
{ {
IMAGE_SECTION_HEADER *h; IMAGE_SECTION_HEADER *h;
@ -54,15 +56,23 @@ new_section(char *name, int size, int noraw)
} }
h = &sh[nsect++]; h = &sh[nsect++];
strncpy((char*)h->Name, name, sizeof(h->Name)); strncpy((char*)h->Name, name, sizeof(h->Name));
h->VirtualSize = size; h->VirtualSize = sectsize;
if(!sect_virt_begin) h->VirtualAddress = nextsectoff;
sect_virt_begin = 0x1000; nextsectoff = rnd(nextsectoff+sectsize, PESECTALIGN);
h->VirtualAddress = sect_virt_begin; h->PointerToRawData = nextfileoff;
sect_virt_begin = rnd(sect_virt_begin+size, 0x1000); if(filesize > 0) {
if(!noraw) { h->SizeOfRawData = rnd(filesize, PEFILEALIGN);
h->SizeOfRawData = rnd(size, PEALIGN); nextfileoff += h->SizeOfRawData;
h->PointerToRawData = sect_raw_begin; }
sect_raw_begin += h->SizeOfRawData; if(s) {
if(s->vaddr-PEBASE != h->VirtualAddress) {
diag("%s.VirtualAddress = %#llux, want %#llux", name, (vlong)h->VirtualAddress, (vlong)(s->vaddr-PEBASE));
errorexit();
}
if(s->fileoff != h->PointerToRawData) {
diag("%s.PointerToRawData = %#llux, want %#llux", name, (vlong)h->PointerToRawData, (vlong)(s->fileoff));
errorexit();
}
} }
return h; return h;
} }
@ -79,6 +89,11 @@ peinit(void)
default: default:
break; break;
} }
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
nextsectoff = PESECTHEADR;
nextfileoff = PEFILEHEADR;
} }
static void static void
@ -97,26 +112,6 @@ pewrite(void)
for (i=0; i<nsect; i++) for (i=0; i<nsect; i++)
for (j=0; j<sizeof(sh[i]); j++) for (j=0; j<sizeof(sh[i]); j++)
cput(((char*)&sh[i])[j]); cput(((char*)&sh[i])[j]);
strnput("", PERESERVE-0x400);
}
void
dope(void)
{
textsect = new_section(".text", segtext.len, 0);
textsect->Characteristics = IMAGE_SCN_CNT_CODE|
IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
datsect = new_section(".data", segdata.filelen, 0);
datsect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
if(segdata.vaddr != PEBASE+datsect->VirtualAddress)
diag("segdata.vaddr = %#llux, want %#llux", (vlong)segdata.vaddr, (vlong)(PEBASE+datsect->VirtualAddress));
bsssect = new_section(".bss", segdata.len - segdata.filelen, 1);
bsssect->Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
} }
static void static void
@ -128,7 +123,7 @@ strput(char *s)
} }
static void static void
add_import_table(void) addimports(vlong fileoff)
{ {
IMAGE_IMPORT_DESCRIPTOR ds[2], *d; IMAGE_IMPORT_DESCRIPTOR ds[2], *d;
char *dllname = "kernel32.dll"; char *dllname = "kernel32.dll";
@ -155,7 +150,7 @@ add_import_table(void)
size += sizeof(fs[0].thunk); size += sizeof(fs[0].thunk);
IMAGE_SECTION_HEADER *isect; IMAGE_SECTION_HEADER *isect;
isect = new_section(".idata", size, 0); isect = addpesection(".idata", size, size, 0);
isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
@ -168,7 +163,7 @@ add_import_table(void)
for(f=fs; f->name; f++) for(f=fs; f->name; f++)
f->thunk += va; f->thunk += va;
seek(cout, 0, 2); seek(cout, fileoff, 0);
for(d=ds; ; d++) { for(d=ds; ; d++) {
lputl(d->OriginalFirstThunk); lputl(d->OriginalFirstThunk);
lputl(d->TimeDateStamp); lputl(d->TimeDateStamp);
@ -192,7 +187,7 @@ add_import_table(void)
void void
asmbpe(void) asmbpe(void)
{ {
vlong eof; IMAGE_SECTION_HEADER *t, *d;
switch(thechar) { switch(thechar) {
default: default:
@ -206,11 +201,16 @@ asmbpe(void)
break; break;
} }
// make sure the end of file is INITRND-aligned. t = addpesection(".text", segtext.len, segtext.len, &segtext);
eof = seek(cout, 0, 2); t->Characteristics = IMAGE_SCN_CNT_CODE|
strnput("", rnd(eof, INITRND) - eof); IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
add_import_table(); d = addpesection(".data", segdata.len, segdata.filelen, &segdata);
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
addimports(nextfileoff);
fh.NumberOfSections = nsect; fh.NumberOfSections = nsect;
fh.TimeDateStamp = time(0); fh.TimeDateStamp = time(0);
@ -223,24 +223,24 @@ asmbpe(void)
oh.Magic = 0x10b; // PE32 oh.Magic = 0x10b; // PE32
oh.MajorLinkerVersion = 1; oh.MajorLinkerVersion = 1;
oh.MinorLinkerVersion = 0; oh.MinorLinkerVersion = 0;
oh.SizeOfCode = textsect->SizeOfRawData; oh.SizeOfCode = t->SizeOfRawData;
oh.SizeOfInitializedData = datsect->SizeOfRawData; oh.SizeOfInitializedData = d->SizeOfRawData;
oh.SizeOfUninitializedData = bsssect->SizeOfRawData; oh.SizeOfUninitializedData = 0;
oh.AddressOfEntryPoint = entryvalue()-PEBASE; oh.AddressOfEntryPoint = entryvalue()-PEBASE;
oh.BaseOfCode = textsect->VirtualAddress; oh.BaseOfCode = t->VirtualAddress;
oh.BaseOfData = datsect->VirtualAddress; oh.BaseOfData = d->VirtualAddress;
oh.ImageBase = PEBASE; oh.ImageBase = PEBASE;
oh.SectionAlignment = 0x00001000; oh.SectionAlignment = PESECTALIGN;
oh.FileAlignment = PEALIGN; oh.FileAlignment = PEFILEALIGN;
oh.MajorOperatingSystemVersion = 4; oh.MajorOperatingSystemVersion = 4;
oh.MinorOperatingSystemVersion = 0; oh.MinorOperatingSystemVersion = 0;
oh.MajorImageVersion = 1; oh.MajorImageVersion = 1;
oh.MinorImageVersion = 0; oh.MinorImageVersion = 0;
oh.MajorSubsystemVersion = 4; oh.MajorSubsystemVersion = 4;
oh.MinorSubsystemVersion = 0; oh.MinorSubsystemVersion = 0;
oh.SizeOfImage = sect_virt_begin; oh.SizeOfImage = nextsectoff;
oh.SizeOfHeaders = PERESERVE; oh.SizeOfHeaders = PEFILEHEADR;
oh.Subsystem = 3; // WINDOWS_CUI oh.Subsystem = 3; // WINDOWS_CUI
oh.SizeOfStackReserve = 0x00200000; oh.SizeOfStackReserve = 0x00200000;
oh.SizeOfStackCommit = 0x00001000; oh.SizeOfStackCommit = 0x00001000;

View File

@ -72,9 +72,16 @@ typedef struct {
uint32 FirstThunk; uint32 FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR; } IMAGE_IMPORT_DESCRIPTOR;
#define PERESERVE 0x1000
#define PEALIGN 0x1000
#define PEBASE 0x00400000 #define PEBASE 0x00400000
// SectionAlignment must be greater than or equal to FileAlignment.
// The default is the page size for the architecture.
#define PESECTALIGN 0x1000
// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
// The default is 512. If the SectionAlignment is less than
// the architecture's page size, then FileAlignment must match SectionAlignment.
#define PEFILEALIGN (2<<8)
extern int32 PESECTHEADR;
extern int32 PEFILEHEADR;
enum { enum {
IMAGE_FILE_MACHINE_I386 = 0x14c, IMAGE_FILE_MACHINE_I386 = 0x14c,
@ -112,5 +119,4 @@ enum {
}; };
void peinit(void); void peinit(void);
void dope(void);
void asmbpe(void); void asmbpe(void);