diff options
Diffstat (limited to 'src/cmd/6l')
-rw-r--r-- | src/cmd/6l/Makefile | 3 | ||||
-rw-r--r-- | src/cmd/6l/asm.c | 45 | ||||
-rw-r--r-- | src/cmd/6l/doc.go | 2 | ||||
-rw-r--r-- | src/cmd/6l/l.h | 3 | ||||
-rw-r--r-- | src/cmd/6l/obj.c | 21 | ||||
-rw-r--r-- | src/cmd/6l/pass.c | 38 |
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 |