Commit fa249cae authored by Alex Brainman's avatar Alex Brainman

ld: remove cseekend and redo pe writing

Simplify code and add more checks.

Fixes #2105.

R=rsc
CC=golang-dev
https://golang.org/cl/4794060
parent 5a52c6ad
...@@ -1415,9 +1415,3 @@ cwrite(void *buf, int n) ...@@ -1415,9 +1415,3 @@ cwrite(void *buf, int n)
} }
coutpos += n; coutpos += n;
} }
void
cseekend(void)
{
seek(cout, 0, 2);
}
...@@ -302,7 +302,6 @@ EXTERN char* cbpmax; ...@@ -302,7 +302,6 @@ EXTERN char* cbpmax;
void cflush(void); void cflush(void);
vlong cpos(void); vlong cpos(void);
void cseek(vlong); void cseek(vlong);
void cseekend(void);
void cwrite(void*, int); void cwrite(void*, int);
void importcycles(void); void importcycles(void);
int Zconv(Fmt*); int Zconv(Fmt*);
...@@ -76,7 +76,7 @@ static Sym *dexport[1024]; ...@@ -76,7 +76,7 @@ static Sym *dexport[1024];
static int nexport; static int nexport;
static IMAGE_SECTION_HEADER* static IMAGE_SECTION_HEADER*
addpesection(char *name, int sectsize, int filesize, Segment *s) addpesection(char *name, int sectsize, int filesize)
{ {
IMAGE_SECTION_HEADER *h; IMAGE_SECTION_HEADER *h;
...@@ -94,19 +94,31 @@ addpesection(char *name, int sectsize, int filesize, Segment *s) ...@@ -94,19 +94,31 @@ addpesection(char *name, int sectsize, int filesize, Segment *s)
h->SizeOfRawData = rnd(filesize, PEFILEALIGN); h->SizeOfRawData = rnd(filesize, PEFILEALIGN);
nextfileoff += h->SizeOfRawData; nextfileoff += 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;
} }
static void
chksectoff(IMAGE_SECTION_HEADER *h, vlong off)
{
if(off != h->PointerToRawData) {
diag("%s.PointerToRawData = %#llux, want %#llux", h->Name, (vlong)h->PointerToRawData, off);
errorexit();
}
}
static void
chksectseg(IMAGE_SECTION_HEADER *h, Segment *s)
{
if(s->vaddr-PEBASE != h->VirtualAddress) {
diag("%s.VirtualAddress = %#llux, want %#llux", h->Name, (vlong)h->VirtualAddress, (vlong)(s->vaddr-PEBASE));
errorexit();
}
if(s->fileoff != h->PointerToRawData) {
diag("%s.PointerToRawData = %#llux, want %#llux", h->Name, (vlong)h->PointerToRawData, (vlong)(s->fileoff));
errorexit();
}
}
void void
peinit(void) peinit(void)
{ {
...@@ -138,7 +150,6 @@ pewrite(void) ...@@ -138,7 +150,6 @@ pewrite(void)
cseek(0); cseek(0);
cwrite(dosstub, sizeof dosstub); cwrite(dosstub, sizeof dosstub);
strnput("PE", 4); strnput("PE", 4);
cflush();
// TODO: This code should not assume that the // TODO: This code should not assume that the
// memory representation is little-endian or // memory representation is little-endian or
// that the structs are packed identically to // that the structs are packed identically to
...@@ -213,39 +224,41 @@ initdynimport(void) ...@@ -213,39 +224,41 @@ initdynimport(void)
} }
static void static void
addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) addimports(IMAGE_SECTION_HEADER *datsect)
{ {
IMAGE_SECTION_HEADER *isect; IMAGE_SECTION_HEADER *isect;
uvlong n, oftbase, ftbase; uvlong n, oftbase, ftbase;
vlong startoff, endoff;
Imp *m; Imp *m;
Dll *d; Dll *d;
Sym* dynamic; Sym* dynamic;
startoff = cpos();
dynamic = lookup(".windynamic", 0); dynamic = lookup(".windynamic", 0);
// skip import descriptor table (will write it later) // skip import descriptor table (will write it later)
n = 0; n = 0;
for(d = dr; d != nil; d = d->next) for(d = dr; d != nil; d = d->next)
n++; n++;
cseek(fileoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1)); cseek(startoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1));
// write dll names // write dll names
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
d->nameoff = cpos() - fileoff; d->nameoff = cpos() - startoff;
strput(d->name); strput(d->name);
} }
// write function names // write function names
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) {
m->off = nextsectoff + cpos() - fileoff; m->off = nextsectoff + cpos() - startoff;
wputl(0); // hint wputl(0); // hint
strput(m->s->dynimpname); strput(m->s->dynimpname);
} }
} }
// write OriginalFirstThunks // write OriginalFirstThunks
oftbase = cpos() - fileoff; oftbase = cpos() - startoff;
n = cpos(); n = cpos();
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
d->thunkoff = cpos() - n; d->thunkoff = cpos() - n;
...@@ -255,12 +268,13 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -255,12 +268,13 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
} }
// add pe section and pad it at the end // add pe section and pad it at the end
n = cpos() - fileoff; n = cpos() - startoff;
isect = addpesection(".idata", n, n, 0); isect = addpesection(".idata", n, n);
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;
chksectoff(isect, startoff);
strnput("", isect->SizeOfRawData - n); strnput("", isect->SizeOfRawData - n);
cflush(); endoff = cpos();
// write FirstThunks (allocated in .data section) // write FirstThunks (allocated in .data section)
ftbase = dynamic->value - datsect->VirtualAddress - PEBASE; ftbase = dynamic->value - datsect->VirtualAddress - PEBASE;
...@@ -270,10 +284,9 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -270,10 +284,9 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
put(m->off); put(m->off);
put(0); put(0);
} }
cflush();
// finally write import descriptor table // finally write import descriptor table
cseek(fileoff); cseek(startoff);
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
lputl(isect->VirtualAddress + oftbase + d->thunkoff); lputl(isect->VirtualAddress + oftbase + d->thunkoff);
lputl(0); lputl(0);
...@@ -286,7 +299,6 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -286,7 +299,6 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
lputl(0); lputl(0);
lputl(0); lputl(0);
lputl(0); lputl(0);
cflush();
// update data directory // update data directory
dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
...@@ -294,7 +306,7 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect) ...@@ -294,7 +306,7 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size; dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size;
cseekend(); cseek(endoff);
} }
static int static int
...@@ -329,7 +341,7 @@ initdynexport(void) ...@@ -329,7 +341,7 @@ initdynexport(void)
} }
void void
addexports(vlong fileoff) addexports(void)
{ {
IMAGE_SECTION_HEADER *sect; IMAGE_SECTION_HEADER *sect;
IMAGE_EXPORT_DIRECTORY e; IMAGE_EXPORT_DIRECTORY e;
...@@ -342,13 +354,13 @@ addexports(vlong fileoff) ...@@ -342,13 +354,13 @@ addexports(vlong fileoff)
if (nexport == 0) if (nexport == 0)
return; return;
sect = addpesection(".edata", size, size, 0); sect = addpesection(".edata", size, size);
sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ;
chksectoff(sect, cpos());
va = sect->VirtualAddress; va = sect->VirtualAddress;
dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va;
dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize;
cseek(fileoff);
va_name = va + sizeof e + nexport*4; va_name = va + sizeof e + nexport*4;
va_addr = va + sizeof e; va_addr = va + sizeof e;
va_na = va + sizeof e + nexport*8; va_na = va + sizeof e + nexport*8;
...@@ -383,9 +395,6 @@ addexports(vlong fileoff) ...@@ -383,9 +395,6 @@ addexports(vlong fileoff)
for(i=0; i<nexport; i++) for(i=0; i<nexport; i++)
strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1); strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1);
strnput("", sect->SizeOfRawData - size); strnput("", sect->SizeOfRawData - size);
cflush();
cseekend();
} }
void void
...@@ -428,7 +437,7 @@ newPEDWARFSection(char *name, vlong size) ...@@ -428,7 +437,7 @@ newPEDWARFSection(char *name, vlong size)
nextsymoff += strlen(name); nextsymoff += strlen(name);
symnames[nextsymoff] = 0; symnames[nextsymoff] = 0;
nextsymoff ++; nextsymoff ++;
h = addpesection(s, size, size, 0); h = addpesection(s, size, size);
h->Characteristics = IMAGE_SCN_MEM_READ| h->Characteristics = IMAGE_SCN_MEM_READ|
IMAGE_SCN_MEM_DISCARDABLE; IMAGE_SCN_MEM_DISCARDABLE;
...@@ -445,9 +454,10 @@ addsymtable(void) ...@@ -445,9 +454,10 @@ addsymtable(void)
return; return;
size = nextsymoff + 4; size = nextsymoff + 4;
h = addpesection(".symtab", size, size, 0); h = addpesection(".symtab", size, size);
h->Characteristics = IMAGE_SCN_MEM_READ| h->Characteristics = IMAGE_SCN_MEM_READ|
IMAGE_SCN_MEM_DISCARDABLE; IMAGE_SCN_MEM_DISCARDABLE;
chksectoff(h, cpos());
fh.PointerToSymbolTable = cpos(); fh.PointerToSymbolTable = cpos();
fh.NumberOfSymbols = 0; fh.NumberOfSymbols = 0;
// put symbol string table // put symbol string table
...@@ -455,7 +465,6 @@ addsymtable(void) ...@@ -455,7 +465,6 @@ addsymtable(void)
for (i=0; i<nextsymoff; i++) for (i=0; i<nextsymoff; i++)
cput(symnames[i]); cput(symnames[i]);
strnput("", h->SizeOfRawData - size); strnput("", h->SizeOfRawData - size);
cflush();
} }
void void
...@@ -478,9 +487,10 @@ addpersrc(void) ...@@ -478,9 +487,10 @@ addpersrc(void)
if(rsrcsym == nil) if(rsrcsym == nil)
return; return;
h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0); h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size);
h->Characteristics = IMAGE_SCN_MEM_READ| h->Characteristics = IMAGE_SCN_MEM_READ|
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
chksectoff(h, cpos());
// relocation // relocation
for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) {
p = rsrcsym->p + r->off; p = rsrcsym->p + r->off;
...@@ -493,7 +503,6 @@ addpersrc(void) ...@@ -493,7 +503,6 @@ addpersrc(void)
} }
cwrite(rsrcsym->p, rsrcsym->size); cwrite(rsrcsym->p, rsrcsym->size);
strnput("", h->SizeOfRawData - rsrcsym->size); strnput("", h->SizeOfRawData - rsrcsym->size);
cflush();
// update data directory // update data directory
dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress;
...@@ -517,24 +526,24 @@ asmbpe(void) ...@@ -517,24 +526,24 @@ asmbpe(void)
break; break;
} }
t = addpesection(".text", segtext.len, segtext.len, &segtext); t = addpesection(".text", segtext.len, segtext.len);
t->Characteristics = IMAGE_SCN_CNT_CODE| t->Characteristics = IMAGE_SCN_CNT_CODE|
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;
chksectseg(t, &segtext);
d = addpesection(".data", segdata.len, segdata.filelen, &segdata); d = addpesection(".data", segdata.len, segdata.filelen);
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;
chksectseg(d, &segdata);
if(!debug['s']) if(!debug['s'])
dwarfaddpeheaders(); dwarfaddpeheaders();
addimports(nextfileoff, d); cseek(nextfileoff);
addimports(d);
addexports(nextfileoff); addexports();
addsymtable(); addsymtable();
addpersrc(); addpersrc();
fh.NumberOfSections = nsect; fh.NumberOfSections = nsect;
......
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