summaryrefslogtreecommitdiff
path: root/src/cmd/6l
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6l')
-rw-r--r--src/cmd/6l/Makefile3
-rw-r--r--src/cmd/6l/asm.c45
-rw-r--r--src/cmd/6l/doc.go2
-rw-r--r--src/cmd/6l/l.h3
-rw-r--r--src/cmd/6l/obj.c21
-rw-r--r--src/cmd/6l/pass.c38
6 files changed, 95 insertions, 17 deletions
diff --git a/src/cmd/6l/Makefile b/src/cmd/6l/Makefile
index fba1b42ae..abe204d4f 100644
--- a/src/cmd/6l/Makefile
+++ b/src/cmd/6l/Makefile
@@ -16,12 +16,14 @@ OFILES=\
go.$O\
ldelf.$O\
ldmacho.$O\
+ ldpe.$O\
lib.$O\
list.$O\
macho.$O\
obj.$O\
optab.$O\
pass.$O\
+ pe.$O\
prof.$O\
span.$O\
symtab.$O\
@@ -33,6 +35,7 @@ HFILES=\
../ld/elf.h\
../ld/macho.h\
../ld/dwarf.h\
+ ../ld/pe.h\
include ../../Make.ccmd
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 9726d227c..d6ffa4ff9 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -35,6 +35,7 @@
#include "../ld/elf.h"
#include "../ld/dwarf.h"
#include "../ld/macho.h"
+#include "../ld/pe.h"
#define Dbufslop 100
@@ -205,15 +206,16 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_X86_64_GOTPCREL:
if(targ->dynimpname == nil || targ->dynexport) {
// have symbol
- // turn MOVQ of GOT entry into LEAQ of symbol itself
- if(r->off < 2 || s->p[r->off-2] != 0x8b) {
- diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ->name);
+ if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
+ // turn MOVQ of GOT entry into LEAQ of symbol itself
+ s->p[r->off-2] = 0x8d;
+ r->type = D_PCREL;
+ r->add += 4;
return;
}
- s->p[r->off-2] = 0x8d;
- r->type = D_PCREL;
- r->add += 4;
- return;
+ // fall back to using GOT and hope for the best (CMOV*)
+ // TODO: just needs relocation, no need to put in .dynsym
+ targ->dynimpname = targ->name;
}
addgotsym(targ);
r->type = D_PCREL;
@@ -782,6 +784,8 @@ asmb(void)
if(!debug['d'])
elftextsh += 10;
break;
+ case 10:
+ break;
}
symsize = 0;
@@ -807,6 +811,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 +837,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();
@@ -907,14 +915,17 @@ asmb(void)
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
- switch(HEADTYPE) {
- case 7:
- elfinterp(sh, startva, linuxdynld);
- break;
- case 9:
- elfinterp(sh, startva, freebsddynld);
- break;
+ if(interpreter == nil) {
+ switch(HEADTYPE) {
+ case 7:
+ interpreter = linuxdynld;
+ break;
+ case 9:
+ interpreter = freebsddynld;
+ break;
+ }
}
+ elfinterp(sh, startva, interpreter);
ph = newElfPhdr();
ph->type = PT_INTERP;
@@ -1090,6 +1101,9 @@ asmb(void)
if(a+elfwriteinterp() > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
+ case 10:
+ asmbpe();
+ break;
}
cflush();
}
@@ -1143,6 +1157,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);
diff --git a/src/cmd/6l/doc.go b/src/cmd/6l/doc.go
index 501317f36..97fa2cc5a 100644
--- a/src/cmd/6l/doc.go
+++ b/src/cmd/6l/doc.go
@@ -32,6 +32,8 @@ Options new in this version:
Write Apple Mach-O binaries (default when $GOOS is darwin)
-H7
Write Linux ELF binaries (default when $GOOS is linux)
+-I interpreter
+ Set the ELF dynamic linker to use.
-L dir1 -L dir2
Search for libraries (package files) in dir1, dir2, etc.
The default is the single location $GOROOT/pkg/$GOOS_amd64.
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 1c52ea89d..7f22493e0 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -183,6 +183,7 @@ enum
SRODATA,
SDATA,
SMACHOGOT,
+ SWINDOWS,
SBSS,
SXREF,
@@ -196,7 +197,6 @@ enum
SSUB = 1<<8,
NHASH = 10007,
- NHUNK = 100000,
MINSIZ = 8,
STRINGSZ = 200,
MINLC = 1,
@@ -352,6 +352,7 @@ EXTERN int nerrors;
EXTERN char* noname;
EXTERN char* outfile;
EXTERN vlong pc;
+EXTERN char* interpreter;
EXTERN char* rpath;
EXTERN int32 spsize;
EXTERN Sym* symlist;
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 96d78c3b9..f9e257842 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -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>";
@@ -57,7 +58,7 @@ char* paramspace = "FP";
void
usage(void)
{
- fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n");
+ fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n");
exits("usage");
}
@@ -95,6 +96,9 @@ main(int argc, char *argv[])
case 'H':
HEADTYPE = atolwhex(EARGF(usage()));
break;
+ case 'I':
+ interpreter = EARGF(usage());
+ break;
case 'L':
Lflag(EARGF(usage()));
break;
@@ -133,6 +137,9 @@ main(int argc, char *argv[])
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 +207,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 +262,8 @@ main(int argc, char *argv[])
else
doprof2();
span();
+ if(HEADTYPE == 10)
+ dope();
addexport();
textaddress();
pclntab();
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index 5c4ed00a6..5eb221a35 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -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