1
0
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:
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\
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

View File

@ -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);

View File

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

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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;