1
0
mirror of https://github.com/golang/go synced 2024-11-12 08:20:22 -07:00

6l: windows/amd64 port

R=rsc
CC=golang-dev
https://golang.org/cl/3746044
This commit is contained in:
Wei Guangjing 2011-01-20 09:21:10 -05:00 committed by Russ Cox
parent 6c240d7671
commit 3aec5516ed
8 changed files with 191 additions and 47 deletions

View File

@ -22,6 +22,7 @@ OFILES=\
obj.$O\ obj.$O\
optab.$O\ optab.$O\
pass.$O\ pass.$O\
pe.$O\
prof.$O\ prof.$O\
span.$O\ span.$O\
symtab.$O\ symtab.$O\
@ -33,6 +34,7 @@ HFILES=\
../ld/elf.h\ ../ld/elf.h\
../ld/macho.h\ ../ld/macho.h\
../ld/dwarf.h\ ../ld/dwarf.h\
../ld/pe.h\
include ../../Make.ccmd include ../../Make.ccmd

View File

@ -35,6 +35,7 @@
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/dwarf.h" #include "../ld/dwarf.h"
#include "../ld/macho.h" #include "../ld/macho.h"
#include "../ld/pe.h"
#define Dbufslop 100 #define Dbufslop 100
@ -782,6 +783,8 @@ asmb(void)
if(!debug['d']) if(!debug['d'])
elftextsh += 10; elftextsh += 10;
break; break;
case 10:
break;
} }
symsize = 0; symsize = 0;
@ -807,6 +810,10 @@ asmb(void)
symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen; symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
case 10:
symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
symo = rnd(symo, PEFILEALIGN);
break;
} }
/* /*
* the symbol information is stored as * the symbol information is stored as
@ -829,7 +836,7 @@ asmb(void)
lputl(symsize); lputl(symsize);
lputl(lcsize); lputl(lcsize);
cflush(); cflush();
if(!debug['s']) { if(HEADTYPE != 10 && !debug['s']) {
elfsymo = symo+8+symsize+lcsize; elfsymo = symo+8+symsize+lcsize;
seek(cout, elfsymo, 0); seek(cout, elfsymo, 0);
asmelfsym64(); asmelfsym64();
@ -1090,6 +1097,9 @@ asmb(void)
if(a+elfwriteinterp() > ELFRESERVE) if(a+elfwriteinterp() > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break; break;
case 10:
asmbpe();
break;
} }
cflush(); cflush();
} }
@ -1143,6 +1153,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SDATA: case SDATA:
case SELFDATA: case SELFDATA:
case SMACHOGOT: case SMACHOGOT:
case SWINDOWS:
if(!s->reachable) if(!s->reachable)
continue; continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype); put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);

View File

@ -183,6 +183,7 @@ enum
SRODATA, SRODATA,
SDATA, SDATA,
SMACHOGOT, SMACHOGOT,
SWINDOWS,
SBSS, SBSS,
SXREF, SXREF,

View File

@ -36,6 +36,7 @@
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h" #include "../ld/macho.h"
#include "../ld/dwarf.h" #include "../ld/dwarf.h"
#include "../ld/pe.h"
#include <ar.h> #include <ar.h>
char *noname = "<none>"; char *noname = "<none>";
@ -132,6 +133,9 @@ main(int argc, char *argv[])
else else
if(strcmp(goos, "freebsd") == 0) if(strcmp(goos, "freebsd") == 0)
HEADTYPE = 9; HEADTYPE = 9;
else
if(strcmp(goos, "windows") == 0)
HEADTYPE = 10;
else else
print("goos is not known: %s\n", goos); print("goos is not known: %s\n", goos);
} }
@ -200,6 +204,16 @@ main(int argc, char *argv[])
if(INITRND == -1) if(INITRND == -1)
INITRND = 4096; INITRND = 4096;
break; 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) if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%llux is ignored because of -R0x%ux\n", print("warning: -D0x%llux is ignored because of -R0x%ux\n",
@ -245,6 +259,8 @@ main(int argc, char *argv[])
else else
doprof2(); doprof2();
span(); span();
if(HEADTYPE == 10)
dope();
addexport(); addexport();
textaddress(); textaddress();
pclntab(); pclntab();

View File

@ -277,6 +277,29 @@ patch(void)
vexit = s->value; vexit = s->value;
for(cursym = textp; cursym != nil; cursym = cursym->next) for(cursym = textp; cursym != nil; cursym = cursym->next)
for(p = cursym->text; p != P; p = p->link) { 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) { if(HEADTYPE == 7 || HEADTYPE == 9) {
// ELF uses FS instead of GS. // ELF uses FS instead of GS.
if(p->from.type == D_INDIR+D_GS) if(p->from.type == D_INDIR+D_GS)
@ -411,6 +434,21 @@ dostkoff(void)
p->from.type = D_INDIR+D_GS; p->from.type = D_INDIR+D_GS;
p->from.offset = tlsoffset+0; p->from.offset = tlsoffset+0;
p->to.type = D_CX; 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']) { if(debug['K']) {
// 6l -K means check not only for stack // 6l -K means check not only for stack

View File

@ -871,7 +871,7 @@ 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 if((thechar == '6' || thechar == '8') && HEADTYPE == 10) // Windows PE
segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
if(thechar == '8' && HEADTYPE == 2) { // Plan 9 if(thechar == '8' && HEADTYPE == 2) { // Plan 9
segdata.vaddr = va = rnd(va, 4096); segdata.vaddr = va = rnd(va, 4096);

View File

@ -43,6 +43,7 @@ static int nextfileoff;
static IMAGE_FILE_HEADER fh; static IMAGE_FILE_HEADER fh;
static IMAGE_OPTIONAL_HEADER oh; static IMAGE_OPTIONAL_HEADER oh;
static PE64_IMAGE_OPTIONAL_HEADER oh64;
static IMAGE_SECTION_HEADER sh[16]; static IMAGE_SECTION_HEADER sh[16];
typedef struct Imp Imp; typedef struct Imp Imp;
@ -102,13 +103,14 @@ peinit(void)
// 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);
break; break;
// 32-bit architectures // 32-bit architectures
default: default:
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
break; break;
} }
PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+sizeof(oh)+sizeof(sh), PEFILEALIGN);
PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN); PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
nextsectoff = PESECTHEADR; nextsectoff = PESECTHEADR;
nextfileoff = PEFILEHEADR; nextfileoff = PEFILEHEADR;
@ -125,8 +127,13 @@ pewrite(void)
for (i=0; i<sizeof(fh); i++) for (i=0; i<sizeof(fh); i++)
cput(((char*)&fh)[i]); cput(((char*)&fh)[i]);
for (i=0; i<sizeof(oh); i++) if(pe64) {
cput(((char*)&oh)[i]); 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 (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]);
@ -187,9 +194,9 @@ initdynimport(void)
m->s->sub = dynamic->sub; m->s->sub = dynamic->sub;
dynamic->sub = m->s; dynamic->sub = m->s;
m->s->value = dynamic->size; m->s->value = dynamic->size;
dynamic->size += 4; dynamic->size += PtrSize;
} }
dynamic->size += 4; dynamic->size += PtrSize;
} }
return dr; return dr;
@ -233,8 +240,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)
lputl(m->off); pe64 ? vputl(m->off) : lputl(m->off);
lputl(0); pe64 ? vputl(0): lputl(0);
} }
// add pe section and pad it at the end // 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); 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)
lputl(m->off); pe64 ? vputl(m->off) : lputl(m->off);
lputl(0); pe64 ? vputl(0): lputl(0);
} }
cflush(); cflush();
// finally write import descriptor table // finally write import descriptor table
seek(cout, fileoff, 0); seek(cout, fileoff, 0);
for(d = dr; d != nil; d = d->next) { for(d = dr; d != nil; d = d->next) {
@ -272,10 +279,17 @@ addimports(vlong fileoff, IMAGE_SECTION_HEADER *datsect)
cflush(); cflush();
// update data directory // update data directory
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; if(pe64) {
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; oh64.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize;
oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size; 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); seek(cout, 0, 2);
} }
@ -308,7 +322,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, segdata.filelen, &segdata); d = addpesection(".data", segdata.len, pe64 ? 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;
@ -316,39 +330,68 @@ asmbpe(void)
fh.NumberOfSections = nsect; fh.NumberOfSections = nsect;
fh.TimeDateStamp = time(0); fh.TimeDateStamp = time(0);
fh.SizeOfOptionalHeader = sizeof(oh);
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(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; 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.ImageBase = PEBASE;
oh.MajorLinkerVersion = 1; oh.SectionAlignment = PESECTALIGN;
oh.MinorLinkerVersion = 0; oh.FileAlignment = PEFILEALIGN;
oh.SizeOfCode = t->SizeOfRawData; oh.MajorOperatingSystemVersion = 4;
oh.SizeOfInitializedData = d->SizeOfRawData; oh.MinorOperatingSystemVersion = 0;
oh.SizeOfUninitializedData = 0; oh.MajorImageVersion = 1;
oh.AddressOfEntryPoint = entryvalue()-PEBASE; oh.MinorImageVersion = 0;
oh.BaseOfCode = t->VirtualAddress; oh.MajorSubsystemVersion = 4;
oh.BaseOfData = d->VirtualAddress; oh.MinorSubsystemVersion = 0;
oh.SizeOfImage = nextsectoff;
oh.ImageBase = PEBASE; oh.SizeOfHeaders = PEFILEHEADR;
oh.SectionAlignment = PESECTALIGN; oh.Subsystem = 3; // WINDOWS_CUI
oh.FileAlignment = PEFILEALIGN; oh.SizeOfStackReserve = 0x00200000;
oh.MajorOperatingSystemVersion = 4; oh.SizeOfStackCommit = 0x00001000;
oh.MinorOperatingSystemVersion = 0; oh.SizeOfHeapReserve = 0x00100000;
oh.MajorImageVersion = 1; oh.SizeOfHeapCommit = 0x00001000;
oh.MinorImageVersion = 0; oh.NumberOfRvaAndSizes = 16;
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(); pewrite();
} }

View File

@ -122,3 +122,36 @@ void peinit(void);
void asmbpe(void); void asmbpe(void);
void dope(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;