diff options
Diffstat (limited to 'src/cmd/6l')
-rw-r--r-- | src/cmd/6l/6.out.h | 3 | ||||
-rw-r--r-- | src/cmd/6l/asm.c | 165 | ||||
-rw-r--r-- | src/cmd/6l/l.h | 16 | ||||
-rw-r--r-- | src/cmd/6l/obj.c | 28 | ||||
-rw-r--r-- | src/cmd/6l/optab.c | 20 | ||||
-rw-r--r-- | src/cmd/6l/span.c | 10 |
6 files changed, 149 insertions, 93 deletions
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h index 805b3fc6f..28de74944 100644 --- a/src/cmd/6l/6.out.h +++ b/src/cmd/6l/6.out.h @@ -654,6 +654,8 @@ enum as APFSUB, APFSUBR, APINSRW, + APINSRD, + APINSRQ, APMADDWL, APMAXSW, APMAXUB, @@ -671,6 +673,7 @@ enum as APSHUFL, APSHUFLW, APSHUFW, + APSHUFB, APSLLO, APSLLL, APSLLQ, diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index 5fb75ba4d..07ba59ad9 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -131,7 +131,7 @@ adddynrel(Sym *s, Reloc *r) // Handle relocations found in ELF object files. case 256 + R_X86_64_PC32: - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name); if(targ->type == 0 || targ->type == SXREF) diag("unknown symbol %s in pcrel", targ->name); @@ -142,7 +142,7 @@ adddynrel(Sym *s, Reloc *r) case 256 + R_X86_64_PLT32: r->type = D_PCREL; r->add += 4; - if(targ->dynimpname != nil && !targ->dynexport) { + if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add += targ->plt; @@ -150,7 +150,7 @@ adddynrel(Sym *s, Reloc *r) return; case 256 + R_X86_64_GOTPCREL: - if(targ->dynimpname == nil || targ->dynexport) { + if(targ->type != SDYNIMPORT) { // have symbol if(r->off >= 2 && s->p[r->off-2] == 0x8b) { // turn MOVQ of GOT entry into LEAQ of symbol itself @@ -161,7 +161,6 @@ adddynrel(Sym *s, Reloc *r) } // 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; @@ -171,7 +170,7 @@ adddynrel(Sym *s, Reloc *r) return; case 256 + R_X86_64_64: - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name); r->type = D_ADDR; return; @@ -182,12 +181,12 @@ adddynrel(Sym *s, Reloc *r) case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0: // TODO: What is the difference between all these? r->type = D_ADDR; - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected reloc for dynamic symbol %s", targ->name); return; case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1: - if(targ->dynimpname != nil && !targ->dynexport) { + if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add = targ->plt; @@ -201,12 +200,12 @@ adddynrel(Sym *s, Reloc *r) case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1: case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1: r->type = D_PCREL; - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name); return; case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1: - if(targ->dynimpname == nil || targ->dynexport) { + if(targ->type != SDYNIMPORT) { // have symbol // turn MOVQ of GOT entry into LEAQ of symbol itself if(r->off < 2 || s->p[r->off-2] != 0x8b) { @@ -219,7 +218,7 @@ adddynrel(Sym *s, Reloc *r) } // fall through case 512 + MACHO_X86_64_RELOC_GOT*2 + 1: - if(targ->dynimpname == nil || targ->dynexport) + if(targ->type != SDYNIMPORT) diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); addgotsym(targ); r->type = D_PCREL; @@ -229,7 +228,7 @@ adddynrel(Sym *s, Reloc *r) } // Handle references to ELF symbols from our own object files. - if(targ->dynimpname == nil || targ->dynexport) + if(targ->type != SDYNIMPORT) return; switch(r->type) { @@ -285,10 +284,13 @@ adddynrel(Sym *s, Reloc *r) } int -elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) +elfreloc1(Reloc *r, vlong sectoff) { - VPUT(off); + int32 elfsym; + VPUT(sectoff); + + elfsym = r->xsym->elfsym; switch(r->type) { default: return -1; @@ -307,11 +309,67 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); else return -1; - add -= r->siz; break; } - VPUT(add); + VPUT(r->xadd); + return 0; +} + +int +machoreloc1(Reloc *r, vlong sectoff) +{ + uint32 v; + Sym *rs; + + rs = r->xsym; + + if(rs->type == SHOSTOBJ) { + if(rs->dynid < 0) { + diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); + return -1; + } + v = rs->dynid; + v |= 1<<27; // external relocation + } else { + v = rs->sect->extnum; + if(v == 0) { + diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type); + return -1; + } + } + + switch(r->type) { + default: + return -1; + case D_ADDR: + v |= MACHO_X86_64_RELOC_UNSIGNED<<28; + break; + case D_PCREL: + v |= 1<<24; // pc-relative bit + v |= MACHO_X86_64_RELOC_BRANCH<<28; + break; + } + + switch(r->siz) { + default: + return -1; + case 1: + v |= 0<<25; + break; + case 2: + v |= 1<<25; + break; + case 4: + v |= 2<<25; + break; + case 8: + v |= 3<<25; + break; + } + + LPUT(sectoff); + LPUT(v); return 0; } @@ -448,29 +506,23 @@ addgotsym(Sym *s) void adddynsym(Sym *s) { - Sym *d, *str; + Sym *d; int t; char *name; - vlong off; if(s->dynid >= 0) return; - if(s->dynimpname == nil) - diag("adddynsym: no dynamic name for %s", s->name); - if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); - name = s->dynimpname; - if(name == nil) - name = s->name; + name = s->extname; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; - if(s->dynexport && (s->type&SMASK) == STEXT) + if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; @@ -480,7 +532,7 @@ adddynsym(Sym *s) adduint8(d, 0); /* section where symbol is defined */ - if(!s->dynexport && s->dynimpname != nil) + if(s->type == SDYNIMPORT) adduint16(d, SHN_UNDEF); else { switch(s->type) { @@ -510,62 +562,15 @@ adddynsym(Sym *s) /* size of object */ adduint64(d, s->size); - if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) { + if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(lookup(".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { - // Mach-o symbol nlist64 - d = lookup(".dynsym", 0); - name = s->dynimpname; - if(name == nil) - name = s->name; - if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps - symgrow(d, ndynexp*16); - } - if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp() - s->dynid = -s->dynid-100; - off = s->dynid*16; - } else { - off = d->size; - s->dynid = off/16; - } - // darwin still puts _ prefixes on all C symbols - str = lookup(".dynstr", 0); - setuint32(d, off, str->size); - off += 4; - adduint8(str, '_'); - addstring(str, name); - if(s->type == SDYNIMPORT) { - setuint8(d, off, 0x01); // type - N_EXT - external symbol - off++; - setuint8(d, off, 0); // section - off++; - } else { - setuint8(d, off, 0x0f); - off++; - switch(s->type) { - default: - case STEXT: - setuint8(d, off, 1); - break; - case SDATA: - setuint8(d, off, 2); - break; - case SBSS: - setuint8(d, off, 4); - break; - } - off++; - } - setuint16(d, off, 0); // desc - off += 2; - if(s->type == SDYNIMPORT) - setuint64(d, off, 0); // value - else - setaddr(d, off, s); - off += 8; - } else if(HEADTYPE != Hwindows) { + diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); + } else if(HEADTYPE == Hwindows) { + // already taken care of + } else { diag("adddynsym: unsupported binary format"); } } @@ -706,7 +711,7 @@ asmb(void) dwarfemitdebugsections(); - if(isobj) + if(linkmode == LinkExternal) elfemitreloc(); } break; @@ -729,6 +734,10 @@ asmb(void) dwarfemitdebugsections(); break; + case Hdarwin: + if(linkmode == LinkExternal) + machoemitreloc(); + break; } } diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index ffb8a4552..1d6e55c97 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -42,6 +42,7 @@ enum thechar = '6', PtrSize = 8, IntSize = 8, + MaxAlign = 32, // max data alignment // Loop alignment constants: // want to align loop entry to LoopAlign-byte boundary, @@ -100,9 +101,12 @@ struct Reloc { int32 off; uchar siz; + uchar done; int32 type; int64 add; + int64 xadd; Sym* sym; + Sym* xsym; }; struct Prog @@ -140,11 +144,12 @@ struct Auto struct Sym { char* name; + char* extname; // name used in external object files short type; short version; uchar dupok; uchar reachable; - uchar dynexport; + uchar cgoexport; uchar special; uchar stkcheck; uchar hide; @@ -167,7 +172,6 @@ struct Sym vlong size; Sym* gotype; char* file; - char* dynimpname; char* dynimplib; char* dynimpvers; struct Section* sect; @@ -263,6 +267,7 @@ enum Zo_iw, Zm_o, Zm_r, + Zm2_r, Zm_r_xm, Zm_r_i_xm, Zm_r_3d, @@ -292,10 +297,11 @@ enum P32 = 0x32, /* 32-bit only */ Pe = 0x66, /* operand escape */ Pm = 0x0f, /* 2byte opcode escape */ - Pq = 0xff, /* both escape */ + Pq = 0xff, /* both escapes: 66 0f */ Pb = 0xfe, /* byte operands */ - Pf2 = 0xf2, /* xmm escape 1 */ - Pf3 = 0xf3, /* xmm escape 2 */ + Pf2 = 0xf2, /* xmm escape 1: f2 0f */ + Pf3 = 0xf3, /* xmm escape 2: f3 0f */ + Pq3 = 0x67, /* xmm escape 3: 66 48 0f */ Pw = 0x48, /* Rex.w */ Py = 0x80, /* defaults to 64-bit mode */ diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index 10e4a9860..3775df9de 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -83,6 +83,7 @@ main(int argc, char *argv[]) INITRND = -1; INITENTRY = 0; LIBINITENTRY = 0; + linkmode = LinkInternal; // TODO: LinkAuto once everything works. nuxiinit(); flagcount("1", "use alternate profiling code", &debug['1']); @@ -108,7 +109,7 @@ main(int argc, char *argv[]) flagcount("d", "disable dynamic executable", &debug['d']); flagcount("f", "ignore version mismatch", &debug['f']); flagcount("g", "disable go package data checks", &debug['g']); - flagcount("hostobj", "generate host object file", &isobj); + flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); flagstr("k", "sym: set field tracking symbol", &tracksym); flagcount("n", "dump symbol table", &debug['n']); flagstr("o", "outfile: set output file", &outfile); @@ -116,10 +117,11 @@ main(int argc, char *argv[]) flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); flagcount("race", "enable race detector", &flag_race); flagcount("s", "disable symbol table", &debug['s']); + flagcount("shared", "generate shared object", &flag_shared); + flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); flagcount("u", "reject unsafe packages", &debug['u']); flagcount("v", "print link trace", &debug['v']); flagcount("w", "disable DWARF generation", &debug['w']); - flagcount("shared", "generate shared object", &flag_shared); flagparse(&argc, &argv, usage); @@ -131,13 +133,19 @@ main(int argc, char *argv[]) if(HEADTYPE == -1) HEADTYPE = headtype(goos); - if(isobj) { - switch(HEADTYPE) { - default: - sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE)); - case Hlinux: - break; - } + switch(HEADTYPE) { + default: + if(linkmode == LinkAuto) + linkmode = LinkInternal; + if(linkmode == LinkExternal) + sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); + break; + case Hdarwin: + case Hfreebsd: + case Hlinux: + case Hnetbsd: + case Hopenbsd: + break; } if(outfile == nil) { @@ -282,6 +290,7 @@ main(int argc, char *argv[]) reloc(); asmb(); undef(); + hostlink(); if(debug['v']) { Bprint(&bso, "%5.2f cpu time\n", cputime()); Bprint(&bso, "%d symbols\n", nsymbol); @@ -412,6 +421,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) ntext = 0; eof = Boffset(f) + len; src[0] = 0; + pn = estrdup(pn); // we keep it in Sym* references newloop: memset(h, 0, sizeof(h)); diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c index a163e6faa..b0d5ca788 100644 --- a/src/cmd/6l/optab.c +++ b/src/cmd/6l/optab.c @@ -522,6 +522,11 @@ uchar ymshuf[] = Ymm, Ymr, Zibm_r, 2, 0 }; +uchar ymshufb[] = +{ + Yxm, Yxr, Zm2_r, 2, + 0 +}; uchar yxshuf[] = { Yxm, Yxr, Zibm_r, 2, @@ -532,6 +537,16 @@ uchar yextrw[] = Yxr, Yrl, Zibm_r, 2, 0 }; +uchar yinsrw[] = +{ + Yml, Yxr, Zibm_r, 2, + 0 +}; +uchar yinsr[] = +{ + Ymm, Yxr, Zibm_r, 3, + 0 +}; uchar ypsdq[] = { Yi8, Yxr, Zibo_m, 2, @@ -982,7 +997,9 @@ Optab optab[] = { APFRSQRT, ymfp, Px, 0x97 }, { APFSUB, ymfp, Px, 0x9a }, { APFSUBR, ymfp, Px, 0xaa }, - { APINSRW, yextrw, Pq, 0xc4,(00) }, + { APINSRW, yinsrw, Pq, 0xc4,(00) }, + { APINSRD, yinsr, Pq, 0x3a, 0x22, (00) }, + { APINSRQ, yinsr, Pq3, 0x3a, 0x22, (00) }, { APMADDWL, ymm, Py, 0xf5,Pe,0xf5 }, { APMAXSW, yxm, Pe, 0xee }, { APMAXUB, yxm, Pe, 0xde }, @@ -1008,6 +1025,7 @@ Optab optab[] = { APSHUFL, yxshuf, Pq, 0x70,(00) }, { APSHUFLW, yxshuf, Pf2, 0x70,(00) }, { APSHUFW, ymshuf, Pm, 0x70,(00) }, + { APSHUFB, ymshufb,Pq, 0x38, 0x00 }, { APSLLO, ypsdq, Pq, 0x73,(07) }, { APSLLL, yps, Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) }, { APSLLQ, yps, Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) }, diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c index 283a0e349..fa94d8cf9 100644 --- a/src/cmd/6l/span.c +++ b/src/cmd/6l/span.c @@ -1161,6 +1161,11 @@ found: *andptr++ = Pe; *andptr++ = Pm; break; + case Pq3: /* 16 bit escape, Rex.w, and opcode escape */ + *andptr++ = Pe; + *andptr++ = Pw; + *andptr++ = Pm; + break; case Pf2: /* xmm opcode escape */ case Pf3: @@ -1229,6 +1234,11 @@ found: *andptr++ = op; asmand(&p->from, &p->to); break; + case Zm2_r: + *andptr++ = op; + *andptr++ = o->op[z+1]; + asmand(&p->from, &p->to); + break; case Zm_r_xm: mediaop(o, op, t[3], z); |