cmd/internal/objabi: extract shared functionality from obj

Now only cmd/asm and cmd/compile depend on cmd/internal/obj. Changing
the assembler backends no longer requires reinstalling cmd/link or
cmd/addr2line.

There's also now one canonical definition of the object file format in
cmd/internal/objabi/doc.go, with a warning to update all three
implementations.

objabi is still something of a grab bag of unrelated code (e.g., flag
and environment variable handling probably belong in a separate "tool"
package), but this is still progress.

Fixes #15165.
Fixes #20026.

Change-Id: Ic4b92fac7d0d35438e0d20c9579aad4085c5534c
Reviewed-on: https://go-review.googlesource.com/40972
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Matthew Dempsky 2017-04-18 12:53:25 -07:00
parent f71f32e5e1
commit 1e3570ac86
118 changed files with 2419 additions and 2407 deletions

View file

@ -31,7 +31,7 @@
package x86
import (
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/link/internal/ld"
"log"
)
@ -45,7 +45,7 @@ func addcall(ctxt *ld.Link, s *ld.Symbol, t *ld.Symbol) {
r := ld.Addrel(s)
r.Sym = t
r.Off = int32(i)
r.Type = obj.R_CALL
r.Type = objabi.R_CALL
r.Siz = 4
}
@ -81,7 +81,7 @@ func gentext(ctxt *ld.Link) {
{"di", 7},
} {
thunkfunc := ctxt.Syms.Lookup("__x86.get_pc_thunk."+r.name, 0)
thunkfunc.Type = obj.STEXT
thunkfunc.Type = objabi.STEXT
thunkfunc.Attr |= ld.AttrLocal
thunkfunc.Attr |= ld.AttrReachable //TODO: remove?
o := func(op ...uint8) {
@ -100,7 +100,7 @@ func gentext(ctxt *ld.Link) {
ctxt.Textp = append(thunks, ctxt.Textp...) // keep Textp in dependency order
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == obj.STEXT && ld.Buildmode != ld.BuildmodePlugin {
if addmoduledata.Type == objabi.STEXT && ld.Buildmode != ld.BuildmodePlugin {
// we're linking a module containing the runtime -> no need for
// an init function
return
@ -109,7 +109,7 @@ func gentext(ctxt *ld.Link) {
addmoduledata.Attr |= ld.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = obj.STEXT
initfunc.Type = objabi.STEXT
initfunc.Attr |= ld.AttrLocal
initfunc.Attr |= ld.AttrReachable
o := func(op ...uint8) {
@ -142,7 +142,7 @@ func gentext(ctxt *ld.Link) {
r := ld.Addrel(initfunc)
r.Sym = ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
r.Off = int32(i)
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
r.Add = 12
r.Siz = 4
@ -160,7 +160,7 @@ func gentext(ctxt *ld.Link) {
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
initarray_entry.Type = obj.SINITARR
initarray_entry.Type = objabi.SINITARR
ld.Addaddr(ctxt, initarray_entry, initfunc)
}
@ -176,20 +176,20 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// Handle relocations found in ELF object files.
case 256 + ld.R_386_PC32:
if targ.Type == obj.SDYNIMPORT {
if targ.Type == objabi.SDYNIMPORT {
ld.Errorf(s, "unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name)
}
if targ.Type == 0 || targ.Type == obj.SXREF {
if targ.Type == 0 || targ.Type == objabi.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
}
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
r.Add += 4
return true
case 256 + ld.R_386_PLT32:
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
r.Add += 4
if targ.Type == obj.SDYNIMPORT {
if targ.Type == objabi.SDYNIMPORT {
addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt)
@ -198,13 +198,13 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true
case 256 + ld.R_386_GOT32, 256 + ld.R_386_GOT32X:
if targ.Type != obj.SDYNIMPORT {
if targ.Type != objabi.SDYNIMPORT {
// have symbol
if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
// turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
s.P[r.Off-2] = 0x8d
r.Type = obj.R_GOTOFF
r.Type = objabi.R_GOTOFF
return true
}
@ -214,7 +214,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
s.P[r.Off-2] = 0x36
s.P[r.Off-1] = 0x68
r.Type = obj.R_ADDR
r.Type = objabi.R_ADDR
return true
}
@ -223,49 +223,49 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
}
addgotsym(ctxt, targ)
r.Type = obj.R_CONST // write r->add during relocsym
r.Type = objabi.R_CONST // write r->add during relocsym
r.Sym = nil
r.Add += int64(targ.Got)
return true
case 256 + ld.R_386_GOTOFF:
r.Type = obj.R_GOTOFF
r.Type = objabi.R_GOTOFF
return true
case 256 + ld.R_386_GOTPC:
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
r.Sym = ctxt.Syms.Lookup(".got", 0)
r.Add += 4
return true
case 256 + ld.R_386_32:
if targ.Type == obj.SDYNIMPORT {
if targ.Type == objabi.SDYNIMPORT {
ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name)
}
r.Type = obj.R_ADDR
r.Type = objabi.R_ADDR
return true
case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0:
r.Type = obj.R_ADDR
if targ.Type == obj.SDYNIMPORT {
r.Type = objabi.R_ADDR
if targ.Type == objabi.SDYNIMPORT {
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
}
return true
case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
if targ.Type == obj.SDYNIMPORT {
if targ.Type == objabi.SDYNIMPORT {
addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(targ.Plt)
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
return true
}
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
return true
case 512 + ld.MACHO_FAKE_GOTPCREL:
if targ.Type != obj.SDYNIMPORT {
if targ.Type != objabi.SDYNIMPORT {
// have symbol
// turn MOVL of GOT entry into LEAL of symbol itself
if r.Off < 2 || s.P[r.Off-2] != 0x8b {
@ -274,31 +274,31 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
}
s.P[r.Off-2] = 0x8d
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
return true
}
addgotsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".got", 0)
r.Add += int64(targ.Got)
r.Type = obj.R_PCREL
r.Type = objabi.R_PCREL
return true
}
// Handle references to ELF symbols from our own object files.
if targ.Type != obj.SDYNIMPORT {
if targ.Type != objabi.SDYNIMPORT {
return true
}
switch r.Type {
case obj.R_CALL,
obj.R_PCREL:
case objabi.R_CALL,
objabi.R_PCREL:
addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(targ.Plt)
return true
case obj.R_ADDR:
if s.Type != obj.SDATA {
case objabi.R_ADDR:
if s.Type != objabi.SDATA {
break
}
if ld.Iself {
@ -306,12 +306,12 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
rel := ctxt.Syms.Lookup(".rel", 0)
ld.Addaddrplus(ctxt, rel, s, int64(r.Off))
ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(targ.Dynid), ld.R_386_32))
r.Type = obj.R_CONST // write r->add during relocsym
r.Type = objabi.R_CONST // write r->add during relocsym
r.Sym = nil
return true
}
if ld.Headtype == obj.Hdarwin && s.Size == int64(ld.SysArch.PtrSize) && r.Off == 0 {
if ld.Headtype == objabi.Hdarwin && s.Size == int64(ld.SysArch.PtrSize) && r.Off == 0 {
// Mach-O relocations are a royal pain to lay out.
// They use a compact stateful bytecode representation
// that is too much bother to deal with.
@ -325,7 +325,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
ld.Adddynsym(ctxt, targ)
got := ctxt.Syms.Lookup(".got", 0)
s.Type = got.Type | obj.SSUB
s.Type = got.Type | objabi.SSUB
s.Outer = got
s.Sub = got.Sub
got.Sub = s
@ -336,7 +336,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true
}
if ld.Headtype == obj.Hwindows && s.Size == int64(ld.SysArch.PtrSize) {
if ld.Headtype == objabi.Hwindows && s.Size == int64(ld.SysArch.PtrSize) {
// nothing to do, the relocation will be laid out in pereloc1
return true
}
@ -353,14 +353,14 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int {
default:
return -1
case obj.R_ADDR:
case objabi.R_ADDR:
if r.Siz == 4 {
ld.Thearch.Lput(ld.R_386_32 | uint32(elfsym)<<8)
} else {
return -1
}
case obj.R_GOTPCREL:
case objabi.R_GOTPCREL:
if r.Siz == 4 {
ld.Thearch.Lput(ld.R_386_GOTPC)
if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" {
@ -371,9 +371,9 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int {
return -1
}
case obj.R_CALL:
case objabi.R_CALL:
if r.Siz == 4 {
if r.Xsym.Type == obj.SDYNIMPORT {
if r.Xsym.Type == objabi.SDYNIMPORT {
ld.Thearch.Lput(ld.R_386_PLT32 | uint32(elfsym)<<8)
} else {
ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8)
@ -382,21 +382,21 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int {
return -1
}
case obj.R_PCREL:
case objabi.R_PCREL:
if r.Siz == 4 {
ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8)
} else {
return -1
}
case obj.R_TLS_LE:
case objabi.R_TLS_LE:
if r.Siz == 4 {
ld.Thearch.Lput(ld.R_386_TLS_LE | uint32(elfsym)<<8)
} else {
return -1
}
case obj.R_TLS_IE:
case objabi.R_TLS_IE:
if r.Siz == 4 {
ld.Thearch.Lput(ld.R_386_GOTPC)
ld.Thearch.Lput(uint32(sectoff))
@ -414,7 +414,7 @@ func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
rs := r.Xsym
if rs.Type == obj.SHOSTOBJ {
if rs.Type == objabi.SHOSTOBJ {
if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type)
return -1
@ -434,11 +434,11 @@ func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
default:
return -1
case obj.R_ADDR:
case objabi.R_ADDR:
v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28
case obj.R_CALL,
obj.R_PCREL:
case objabi.R_CALL,
objabi.R_PCREL:
v |= 1 << 24 // pc-relative bit
v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28
}
@ -482,14 +482,14 @@ func pereloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) bool {
default:
return false
case obj.R_DWARFREF:
case objabi.R_DWARFREF:
v = ld.IMAGE_REL_I386_SECREL
case obj.R_ADDR:
case objabi.R_ADDR:
v = ld.IMAGE_REL_I386_DIR32
case obj.R_CALL,
obj.R_PCREL:
case objabi.R_CALL,
objabi.R_PCREL:
v = ld.IMAGE_REL_I386_REL32
}
@ -503,11 +503,11 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
return -1
}
switch r.Type {
case obj.R_CONST:
case objabi.R_CONST:
*val = r.Add
return 0
case obj.R_GOTOFF:
case objabi.R_GOTOFF:
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
return 0
}
@ -587,7 +587,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT))
s.Plt = int32(plt.Size - 16)
} else if ld.Headtype == obj.Hdarwin {
} else if ld.Headtype == objabi.Hdarwin {
// Same laziness as in 6l.
plt := ctxt.Syms.Lookup(".plt", 0)
@ -621,7 +621,7 @@ func addgotsym(ctxt *ld.Link, s *ld.Symbol) {
rel := ctxt.Syms.Lookup(".rel", 0)
ld.Addaddrplus(ctxt, rel, got, int64(s.Got))
ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_GLOB_DAT))
} else if ld.Headtype == obj.Hdarwin {
} else if ld.Headtype == objabi.Hdarwin {
ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.got", 0), uint32(s.Dynid))
} else {
ld.Errorf(s, "addgotsym: unsupported binary format")
@ -630,7 +630,7 @@ func addgotsym(ctxt *ld.Link, s *ld.Symbol) {
func asmb(ctxt *ld.Link) {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f asmb\n", obj.Cputime())
ctxt.Logf("%5.2f asmb\n", ld.Cputime())
}
if ld.Iself {
@ -648,7 +648,7 @@ func asmb(ctxt *ld.Link) {
if ld.Segrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
}
ld.Cseek(int64(ld.Segrodata.Fileoff))
@ -656,14 +656,14 @@ func asmb(ctxt *ld.Link) {
}
if ld.Segrelrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
}
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
ctxt.Logf("%5.2f datblk\n", ld.Cputime())
}
ld.Cseek(int64(ld.Segdata.Fileoff))
@ -673,7 +673,7 @@ func asmb(ctxt *ld.Link) {
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
machlink := uint32(0)
if ld.Headtype == obj.Hdarwin {
if ld.Headtype == objabi.Hdarwin {
machlink = uint32(ld.Domacholink(ctxt))
}
@ -684,7 +684,7 @@ func asmb(ctxt *ld.Link) {
if !*ld.FlagS {
// TODO: rationalize
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f sym\n", obj.Cputime())
ctxt.Logf("%5.2f sym\n", ld.Cputime())
}
switch ld.Headtype {
default:
@ -693,13 +693,13 @@ func asmb(ctxt *ld.Link) {
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
}
case obj.Hplan9:
case objabi.Hplan9:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
case objabi.Hdarwin:
symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
case obj.Hwindows:
case objabi.Hwindows:
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
}
@ -709,7 +709,7 @@ func asmb(ctxt *ld.Link) {
default:
if ld.Iself {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f elfsym\n", obj.Cputime())
ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
}
ld.Asmelfsym(ctxt)
ld.Cflush()
@ -720,7 +720,7 @@ func asmb(ctxt *ld.Link) {
}
}
case obj.Hplan9:
case objabi.Hplan9:
ld.Asmplan9sym(ctxt)
ld.Cflush()
@ -734,12 +734,12 @@ func asmb(ctxt *ld.Link) {
ld.Cflush()
}
case obj.Hwindows:
case objabi.Hwindows:
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f dwarf\n", obj.Cputime())
ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
}
case obj.Hdarwin:
case objabi.Hdarwin:
if ld.Linkmode == ld.LinkExternal {
ld.Machoemitreloc(ctxt)
}
@ -747,12 +747,12 @@ func asmb(ctxt *ld.Link) {
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f headr\n", obj.Cputime())
ctxt.Logf("%5.2f headr\n", ld.Cputime())
}
ld.Cseek(0)
switch ld.Headtype {
default:
case obj.Hplan9: /* plan9 */
case objabi.Hplan9: /* plan9 */
magic := int32(4*11*11 + 7)
ld.Lputb(uint32(magic)) /* magic */
@ -764,17 +764,17 @@ func asmb(ctxt *ld.Link) {
ld.Lputb(uint32(ld.Spsize)) /* sp offsets */
ld.Lputb(uint32(ld.Lcsize)) /* line offsets */
case obj.Hdarwin:
case objabi.Hdarwin:
ld.Asmbmacho(ctxt)
case obj.Hlinux,
obj.Hfreebsd,
obj.Hnetbsd,
obj.Hopenbsd,
obj.Hnacl:
case objabi.Hlinux,
objabi.Hfreebsd,
objabi.Hnetbsd,
objabi.Hopenbsd,
objabi.Hnacl:
ld.Asmbelf(ctxt, int64(symo))
case obj.Hwindows:
case objabi.Hwindows:
ld.Asmbpe(ctxt)
}