mirror of
https://github.com/golang/go
synced 2024-11-12 08:10:21 -07:00
6l: windows/amd64 port
R=rsc CC=golang-dev https://golang.org/cl/3746044
This commit is contained in:
parent
6c240d7671
commit
3aec5516ed
@ -22,6 +22,7 @@ OFILES=\
|
||||
obj.$O\
|
||||
optab.$O\
|
||||
pass.$O\
|
||||
pe.$O\
|
||||
prof.$O\
|
||||
span.$O\
|
||||
symtab.$O\
|
||||
@ -33,6 +34,7 @@ HFILES=\
|
||||
../ld/elf.h\
|
||||
../ld/macho.h\
|
||||
../ld/dwarf.h\
|
||||
../ld/pe.h\
|
||||
|
||||
include ../../Make.ccmd
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "../ld/elf.h"
|
||||
#include "../ld/dwarf.h"
|
||||
#include "../ld/macho.h"
|
||||
#include "../ld/pe.h"
|
||||
|
||||
#define Dbufslop 100
|
||||
|
||||
@ -782,6 +783,8 @@ asmb(void)
|
||||
if(!debug['d'])
|
||||
elftextsh += 10;
|
||||
break;
|
||||
case 10:
|
||||
break;
|
||||
}
|
||||
|
||||
symsize = 0;
|
||||
@ -807,6 +810,10 @@ asmb(void)
|
||||
symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
|
||||
symo = rnd(symo, INITRND);
|
||||
break;
|
||||
case 10:
|
||||
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
|
||||
symo = rnd(symo, PEFILEALIGN);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* the symbol information is stored as
|
||||
@ -829,7 +836,7 @@ asmb(void)
|
||||
lputl(symsize);
|
||||
lputl(lcsize);
|
||||
cflush();
|
||||
if(!debug['s']) {
|
||||
if(HEADTYPE != 10 && !debug['s']) {
|
||||
elfsymo = symo+8+symsize+lcsize;
|
||||
seek(cout, elfsymo, 0);
|
||||
asmelfsym64();
|
||||
@ -1090,6 +1097,9 @@ asmb(void)
|
||||
if(a+elfwriteinterp() > ELFRESERVE)
|
||||
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
|
||||
break;
|
||||
case 10:
|
||||
asmbpe();
|
||||
break;
|
||||
}
|
||||
cflush();
|
||||
}
|
||||
@ -1143,6 +1153,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
||||
case SDATA:
|
||||
case SELFDATA:
|
||||
case SMACHOGOT:
|
||||
case SWINDOWS:
|
||||
if(!s->reachable)
|
||||
continue;
|
||||
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
||||
|
@ -183,6 +183,7 @@ enum
|
||||
SRODATA,
|
||||
SDATA,
|
||||
SMACHOGOT,
|
||||
SWINDOWS,
|
||||
SBSS,
|
||||
|
||||
SXREF,
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "../ld/elf.h"
|
||||
#include "../ld/macho.h"
|
||||
#include "../ld/dwarf.h"
|
||||
#include "../ld/pe.h"
|
||||
#include <ar.h>
|
||||
|
||||
char *noname = "<none>";
|
||||
@ -132,6 +133,9 @@ main(int argc, char *argv[])
|
||||
else
|
||||
if(strcmp(goos, "freebsd") == 0)
|
||||
HEADTYPE = 9;
|
||||
else
|
||||
if(strcmp(goos, "windows") == 0)
|
||||
HEADTYPE = 10;
|
||||
else
|
||||
print("goos is not known: %s\n", goos);
|
||||
}
|
||||
@ -200,6 +204,16 @@ main(int argc, char *argv[])
|
||||
if(INITRND == -1)
|
||||
INITRND = 4096;
|
||||
break;
|
||||
case 10: /* PE executable */
|
||||
peinit();
|
||||
HEADR = PEFILEHEADR;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = PEBASE+PESECTHEADR;
|
||||
if(INITDAT == -1)
|
||||
INITDAT = 0;
|
||||
if(INITRND == -1)
|
||||
INITRND = PESECTALIGN;
|
||||
break;
|
||||
}
|
||||
if(INITDAT != 0 && INITRND != 0)
|
||||
print("warning: -D0x%llux is ignored because of -R0x%ux\n",
|
||||
@ -245,6 +259,8 @@ main(int argc, char *argv[])
|
||||
else
|
||||
doprof2();
|
||||
span();
|
||||
if(HEADTYPE == 10)
|
||||
dope();
|
||||
addexport();
|
||||
textaddress();
|
||||
pclntab();
|
||||
|
@ -277,6 +277,29 @@ patch(void)
|
||||
vexit = s->value;
|
||||
for(cursym = textp; cursym != nil; cursym = cursym->next)
|
||||
for(p = cursym->text; p != P; p = p->link) {
|
||||
if(HEADTYPE == 10) {
|
||||
// Windows
|
||||
// Convert
|
||||
// op n(GS), reg
|
||||
// to
|
||||
// MOVL 0x58(GS), reg
|
||||
// op n(reg), reg
|
||||
// The purpose of this patch is to fix some accesses
|
||||
// to extern register variables (TLS) on Windows, as
|
||||
// a different method is used to access them.
|
||||
if(p->from.type == D_INDIR+D_GS
|
||||
&& p->to.type >= D_AX && p->to.type <= D_DI
|
||||
&& p->from.offset != 0x58) {
|
||||
q = appendp(p);
|
||||
q->from = p->from;
|
||||
q->from.type = D_INDIR + p->to.type;
|
||||
q->to = p->to;
|
||||
q->as = p->as;
|
||||
p->as = AMOVQ;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0x58;
|
||||
}
|
||||
}
|
||||
if(HEADTYPE == 7 || HEADTYPE == 9) {
|
||||
// ELF uses FS instead of GS.
|
||||
if(p->from.type == D_INDIR+D_GS)
|
||||
@ -411,6 +434,21 @@ dostkoff(void)
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = tlsoffset+0;
|
||||
p->to.type = D_CX;
|
||||
if(HEADTYPE == 10) { // Windows
|
||||
// movq %gs:0x58, %rcx
|
||||
// movq (%rcx), %rcx
|
||||
p->as = AMOVQ;
|
||||
p->from.type = D_INDIR+D_GS;
|
||||
p->from.offset = 0x58;
|
||||
p->to.type = D_CX;
|
||||
|
||||
|
||||
p = appendp(p);
|
||||
p->as = AMOVQ;
|
||||
p->from.type = D_INDIR+D_CX;
|
||||
p->from.offset = 0;
|
||||
p->to.type = D_CX;
|
||||
}
|
||||
|
||||
if(debug['K']) {
|
||||
// 6l -K means check not only for stack
|
||||
|
@ -871,7 +871,7 @@ address(void)
|
||||
segdata.rwx = 06;
|
||||
segdata.vaddr = va;
|
||||
segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
|
||||
if(thechar == '8' && HEADTYPE == 10) // Windows PE
|
||||
if((thechar == '6' || thechar == '8') && HEADTYPE == 10) // Windows PE
|
||||
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
|
||||
if(thechar == '8' && HEADTYPE == 2) { // Plan 9
|
||||
segdata.vaddr = va = rnd(va, 4096);
|
||||
|
133
src/cmd/ld/pe.c
133
src/cmd/ld/pe.c
@ -43,6 +43,7 @@ static int nextfileoff;
|
||||
|
||||
static IMAGE_FILE_HEADER fh;
|
||||
static IMAGE_OPTIONAL_HEADER oh;
|
||||
static PE64_IMAGE_OPTIONAL_HEADER oh64;
|
||||
static IMAGE_SECTION_HEADER sh[16];
|
||||
|
||||
typedef struct Imp Imp;
|
||||
@ -102,13 +103,14 @@ peinit(void)
|
||||
// 64-bit architectures
|
||||
case '6':
|
||||
pe64 = 1;
|
||||
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh64)+sizeof(sh), PEFILEALIGN);
|
||||
break;
|
||||
// 32-bit architectures
|
||||
default:
|
||||
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
|
||||
break;
|
||||
}
|
||||
|
||||
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
|
||||
|
||||
PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
|
||||
nextsectoff = PESECTHEADR;
|
||||
nextfileoff = PEFILEHEADR;
|
||||
@ -125,8 +127,13 @@ pewrite(void)
|
||||
|
||||
for (i=0; i<sizeof(fh); i++)
|
||||
cput(((char*)&fh)[i]);
|
||||
for (i=0; i<sizeof(oh); i++)
|
||||
cput(((char*)&oh)[i]);
|
||||
if(pe64) {
|
||||
for (i=0; i<sizeof(oh64); i++)
|
||||
cput(((char*)&oh64)[i]);
|
||||
} else {
|
||||
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]);
|
||||
@ -187,9 +194,9 @@ initdynimport(void)
|
||||
m->s->sub = dynamic->sub;
|
||||
dynamic->sub = m->s;
|
||||
m->s->value = dynamic->size;
|
||||
dynamic->size += 4;
|
||||
dynamic->size += PtrSize;
|
||||
}
|
||||
dynamic->size += 4;
|
||||
dynamic->size += PtrSize;
|
||||
}
|
||||
|
||||
return dr;
|
||||
@ -233,8 +240,8 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
|
||||
for(d = dr; d != nil; d = d->next) {
|
||||
d->thunkoff = cpos() - n;
|
||||
for(m = d->ms; m != nil; m = m->next)
|
||||
lputl(m->off);
|
||||
lputl(0);
|
||||
pe64 ? vputl(m->off) : lputl(m->off);
|
||||
pe64 ? vputl(0): lputl(0);
|
||||
}
|
||||
|
||||
// add pe section and pad it at the end
|
||||
@ -250,11 +257,11 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
|
||||
seek(cout, datsect->PointerToRawData + ftbase, 0);
|
||||
for(d = dr; d != nil; d = d->next) {
|
||||
for(m = d->ms; m != nil; m = m->next)
|
||||
lputl(m->off);
|
||||
lputl(0);
|
||||
pe64 ? vputl(m->off) : lputl(m->off);
|
||||
pe64 ? vputl(0): lputl(0);
|
||||
}
|
||||
cflush();
|
||||
|
||||
|
||||
// finally write import descriptor table
|
||||
seek(cout, fileoff, 0);
|
||||
for(d = dr; d != nil; d = d->next) {
|
||||
@ -272,10 +279,17 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
|
||||
cflush();
|
||||
|
||||
// update data directory
|
||||
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;
|
||||
if(pe64) {
|
||||
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
|
||||
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
|
||||
oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE;
|
||||
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);
|
||||
}
|
||||
@ -308,7 +322,7 @@ asmbpe(void)
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA|
|
||||
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
|
||||
|
||||
d = addpesection(".data", segdata.len, segdata.filelen, &segdata);
|
||||
d = addpesection(".data", segdata.len, pe64 ? segdata.len : segdata.filelen, &segdata);
|
||||
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
|
||||
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
|
||||
|
||||
@ -316,39 +330,68 @@ asmbpe(void)
|
||||
|
||||
fh.NumberOfSections = nsect;
|
||||
fh.TimeDateStamp = time(0);
|
||||
fh.SizeOfOptionalHeader = sizeof(oh);
|
||||
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
|
||||
IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
|
||||
if(thechar == '8')
|
||||
|
||||
if (pe64) {
|
||||
fh.SizeOfOptionalHeader = sizeof(oh64);
|
||||
oh64.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 {
|
||||
fh.SizeOfOptionalHeader = sizeof(oh);
|
||||
fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
|
||||
oh.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.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.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;
|
||||
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;
|
||||
}
|
||||
|
||||
pewrite();
|
||||
}
|
||||
|
@ -122,3 +122,36 @@ void peinit(void);
|
||||
void asmbpe(void);
|
||||
void dope(void);
|
||||
|
||||
// X64
|
||||
typedef struct {
|
||||
uint16 Magic;
|
||||
uint8 MajorLinkerVersion;
|
||||
uint8 MinorLinkerVersion;
|
||||
uint32 SizeOfCode;
|
||||
uint32 SizeOfInitializedData;
|
||||
uint32 SizeOfUninitializedData;
|
||||
uint32 AddressOfEntryPoint;
|
||||
uint32 BaseOfCode;
|
||||
uint64 ImageBase;
|
||||
uint32 SectionAlignment;
|
||||
uint32 FileAlignment;
|
||||
uint16 MajorOperatingSystemVersion;
|
||||
uint16 MinorOperatingSystemVersion;
|
||||
uint16 MajorImageVersion;
|
||||
uint16 MinorImageVersion;
|
||||
uint16 MajorSubsystemVersion;
|
||||
uint16 MinorSubsystemVersion;
|
||||
uint32 Win32VersionValue;
|
||||
uint32 SizeOfImage;
|
||||
uint32 SizeOfHeaders;
|
||||
uint32 CheckSum;
|
||||
uint16 Subsystem;
|
||||
uint16 DllCharacteristics;
|
||||
uint64 SizeOfStackReserve;
|
||||
uint64 SizeOfStackCommit;
|
||||
uint64 SizeOfHeapReserve;
|
||||
uint64 SizeOfHeapCommit;
|
||||
uint32 LoaderFlags;
|
||||
uint32 NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[16];
|
||||
} PE64_IMAGE_OPTIONAL_HEADER;
|
||||
|
Loading…
Reference in New Issue
Block a user