cmd/link: put symbol data types in new package

For #22095

Change-Id: I07c288208d94dabae164c2ca0a067402a8e5c2e6
Reviewed-on: https://go-review.googlesource.com/68331
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
David Crawshaw 2017-10-04 17:54:04 -04:00
parent 24e4a128c9
commit 475d92ba4d
36 changed files with 1536 additions and 1457 deletions

View file

@ -70,6 +70,7 @@ var bootstrapDirs = []string{
"cmd/link/internal/mips64", "cmd/link/internal/mips64",
"cmd/link/internal/ppc64", "cmd/link/internal/ppc64",
"cmd/link/internal/s390x", "cmd/link/internal/s390x",
"cmd/link/internal/sym",
"cmd/link/internal/x86", "cmd/link/internal/x86",
"debug/pe", "debug/pe",
"math/big", "math/big",

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"debug/elf" "debug/elf"
"log" "log"
) )
@ -42,8 +43,8 @@ func PADDR(x uint32) uint32 {
return x &^ 0x80000000 return x &^ 0x80000000
} }
func Addcall(ctxt *ld.Link, s *ld.Symbol, t *ld.Symbol) int64 { func Addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) int64 {
s.Attr |= ld.AttrReachable s.Attr |= sym.AttrReachable
i := s.Size i := s.Size
s.Size += 4 s.Size += 4
s.Grow(s.Size) s.Grow(s.Size)
@ -60,16 +61,16 @@ func gentext(ctxt *ld.Link) {
return return
} }
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT && ld.Buildmode != ld.BuildmodePlugin { if addmoduledata.Type == sym.STEXT && ld.Buildmode != ld.BuildmodePlugin {
// we're linking a module containing the runtime -> no need for // we're linking a module containing the runtime -> no need for
// an init function // an init function
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
o := func(op ...uint8) { o := func(op ...uint8) {
for _, op1 := range op { for _, op1 := range op {
initfunc.AddUint8(op1) initfunc.AddUint8(op1)
@ -91,28 +92,28 @@ func gentext(ctxt *ld.Link) {
} }
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
switch r.Type { switch r.Type {
default: default:
if r.Type >= 256 { if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
return false return false
} }
// Handle relocations found in ELF object files. // Handle relocations found in ELF object files.
case 256 + ld.R_X86_64_PC32: case 256 + ld.R_X86_64_PC32:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name)
} }
if targ.Type == 0 || targ.Type == ld.SXREF { if targ.Type == 0 || targ.Type == sym.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name) ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
} }
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
@ -120,10 +121,10 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_X86_64_PC64: case 256 + ld.R_X86_64_PC64:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
} }
if targ.Type == 0 || targ.Type == ld.SXREF { if targ.Type == 0 || targ.Type == sym.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name) ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
} }
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
@ -133,7 +134,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_X86_64_PLT32: case 256 + ld.R_X86_64_PLT32:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Add += 4 r.Add += 4
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt) r.Add += int64(targ.Plt)
@ -142,7 +143,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_X86_64_GOTPCREL, 256 + ld.R_X86_64_GOTPCRELX, 256 + ld.R_X86_64_REX_GOTPCRELX: case 256 + ld.R_X86_64_GOTPCREL, 256 + ld.R_X86_64_GOTPCRELX, 256 + ld.R_X86_64_REX_GOTPCRELX:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
// have symbol // have symbol
if r.Off >= 2 && s.P[r.Off-2] == 0x8b { if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
// turn MOVQ of GOT entry into LEAQ of symbol itself // turn MOVQ of GOT entry into LEAQ of symbol itself
@ -165,7 +166,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_X86_64_64: case 256 + ld.R_X86_64_64:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name)
} }
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
@ -178,13 +179,13 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// TODO: What is the difference between all these? // TODO: What is the difference between all these?
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
} }
return true return true
case 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1: case 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(targ.Plt) r.Add = int64(targ.Plt)
@ -201,13 +202,13 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
512 + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1: 512 + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name)
} }
return true return true
case 512 + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1: case 512 + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
// have symbol // have symbol
// turn MOVQ of GOT entry into LEAQ of symbol itself // turn MOVQ of GOT entry into LEAQ of symbol itself
if r.Off < 2 || s.P[r.Off-2] != 0x8b { if r.Off < 2 || s.P[r.Off-2] != 0x8b {
@ -223,7 +224,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// fall through // fall through
case 512 + ld.MACHO_X86_64_RELOC_GOT*2 + 1: case 512 + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
} }
addgotsym(ctxt, targ) addgotsym(ctxt, targ)
@ -236,7 +237,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
switch r.Type { switch r.Type {
case objabi.R_CALL, case objabi.R_CALL,
objabi.R_PCREL: objabi.R_PCREL:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
// nothing to do, the relocation will be laid out in reloc // nothing to do, the relocation will be laid out in reloc
return true return true
} }
@ -247,7 +248,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case objabi.R_ADDR: case objabi.R_ADDR:
if s.Type == ld.STEXT && ld.Iself { if s.Type == sym.STEXT && ld.Iself {
if ld.Headtype == objabi.Hsolaris { if ld.Headtype == objabi.Hsolaris {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
@ -308,7 +309,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// linking, in which case the relocation will be // linking, in which case the relocation will be
// prepared in the 'reloc' phase and passed to the // prepared in the 'reloc' phase and passed to the
// external linker in the 'asmb' phase. // external linker in the 'asmb' phase.
if s.Type != ld.SDATA && s.Type != ld.SRODATA { if s.Type != sym.SDATA && s.Type != sym.SRODATA {
break break
} }
} }
@ -345,7 +346,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
ld.Adddynsym(ctxt, targ) ld.Adddynsym(ctxt, targ)
got := ctxt.Syms.Lookup(".got", 0) got := ctxt.Syms.Lookup(".got", 0)
s.Type = got.Type | ld.SSUB s.Type = got.Type | sym.SSUB
s.Outer = got s.Outer = got
s.Sub = got.Sub s.Sub = got.Sub
got.Sub = s got.Sub = s
@ -360,7 +361,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write64(uint64(sectoff)) ctxt.Out.Write64(uint64(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -389,7 +390,7 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
} }
case objabi.R_CALL: case objabi.R_CALL:
if r.Siz == 4 { if r.Siz == 4 {
if r.Xsym.Type == ld.SDYNIMPORT { if r.Xsym.Type == sym.SDYNIMPORT {
if ctxt.DynlinkingGo() { if ctxt.DynlinkingGo() {
ctxt.Out.Write64(ld.R_X86_64_PLT32 | uint64(elfsym)<<32) ctxt.Out.Write64(ld.R_X86_64_PLT32 | uint64(elfsym)<<32)
} else { } else {
@ -403,7 +404,7 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
} }
case objabi.R_PCREL: case objabi.R_PCREL:
if r.Siz == 4 { if r.Siz == 4 {
if r.Xsym.Type == ld.SDYNIMPORT && r.Xsym.ElfType == elf.STT_FUNC { if r.Xsym.Type == sym.SDYNIMPORT && r.Xsym.ElfType == elf.STT_FUNC {
ctxt.Out.Write64(ld.R_X86_64_PLT32 | uint64(elfsym)<<32) ctxt.Out.Write64(ld.R_X86_64_PLT32 | uint64(elfsym)<<32)
} else { } else {
ctxt.Out.Write64(ld.R_X86_64_PC32 | uint64(elfsym)<<32) ctxt.Out.Write64(ld.R_X86_64_PC32 | uint64(elfsym)<<32)
@ -423,14 +424,14 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
return true return true
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
if rs.Type == ld.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL { if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL {
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -439,7 +440,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
} else { } else {
v = uint32(rs.Sect.Extnum) v = uint32(rs.Sect.Extnum)
if v == 0 { if v == 0 {
ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
return false return false
} }
} }
@ -486,13 +487,13 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
return true return true
} }
func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -523,11 +524,11 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff
return true return true
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant") log.Fatalf("unexpected relocation variant")
return t return t
} }
@ -559,7 +560,7 @@ func elfsetupplt(ctxt *ld.Link) {
} }
} }
func addpltsym(ctxt *ld.Link, s *ld.Symbol) { func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Plt >= 0 { if s.Plt >= 0 {
return return
} }
@ -627,7 +628,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
} }
} }
func addgotsym(ctxt *ld.Link, s *ld.Symbol) { func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Got >= 0 { if s.Got >= 0 {
return return
} }
@ -838,7 +839,7 @@ func asmb(ctxt *ld.Link) {
ctxt.Out.Flush() ctxt.Out.Flush()
} }
func tlsIEtoLE(s *ld.Symbol, off, size int) { func tlsIEtoLE(s *sym.Symbol, off, size int) {
// Transform the PC-relative instruction into a constant load. // Transform the PC-relative instruction into a constant load.
// That is, // That is,
// //

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"fmt" "fmt"
"log" "log"
) )
@ -64,16 +65,16 @@ func gentext(ctxt *ld.Link) {
return return
} }
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT && ld.Buildmode != ld.BuildmodePlugin { if addmoduledata.Type == sym.STEXT && ld.Buildmode != ld.BuildmodePlugin {
// we're linking a module containing the runtime -> no need for // we're linking a module containing the runtime -> no need for
// an init function // an init function
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
o := func(op uint32) { o := func(op uint32) {
initfunc.AddUint32(ctxt.Arch, op) initfunc.AddUint32(ctxt.Arch, op)
} }
@ -101,9 +102,9 @@ func gentext(ctxt *ld.Link) {
} }
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
@ -113,13 +114,13 @@ func braddoff(a int32, b int32) int32 {
return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b)) return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
switch r.Type { switch r.Type {
default: default:
if r.Type >= 256 { if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
return false return false
} }
@ -127,7 +128,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_ARM_PLT32: case 256 + ld.R_ARM_PLT32:
r.Type = objabi.R_CALLARM r.Type = objabi.R_CALLARM
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(braddoff(int32(r.Add), targ.Plt/4)) r.Add = int64(braddoff(int32(r.Add), targ.Plt/4))
@ -140,7 +141,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
case 256 + ld.R_ARM_GOT32: // R_ARM_GOT_BREL case 256 + ld.R_ARM_GOT32: // R_ARM_GOT_BREL
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
addgotsyminternal(ctxt, targ) addgotsyminternal(ctxt, targ)
} else { } else {
addgotsym(ctxt, targ) addgotsym(ctxt, targ)
@ -152,7 +153,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_ARM_GOT_PREL: // GOT(nil) + A - nil case 256 + ld.R_ARM_GOT_PREL: // GOT(nil) + A - nil
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
addgotsyminternal(ctxt, targ) addgotsyminternal(ctxt, targ)
} else { } else {
addgotsym(ctxt, targ) addgotsym(ctxt, targ)
@ -177,7 +178,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_ARM_CALL: case 256 + ld.R_ARM_CALL:
r.Type = objabi.R_CALLARM r.Type = objabi.R_CALLARM
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(braddoff(int32(r.Add), targ.Plt/4)) r.Add = int64(braddoff(int32(r.Add), targ.Plt/4))
@ -192,7 +193,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_ARM_ABS32: case 256 + ld.R_ARM_ABS32:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ.Name)
} }
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
@ -211,7 +212,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_ARM_PC24, case 256 + ld.R_ARM_PC24,
256 + ld.R_ARM_JUMP24: 256 + ld.R_ARM_JUMP24:
r.Type = objabi.R_CALLARM r.Type = objabi.R_CALLARM
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(braddoff(int32(r.Add), targ.Plt/4)) r.Add = int64(braddoff(int32(r.Add), targ.Plt/4))
@ -221,7 +222,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
} }
// Handle references to ELF symbols from our own object files. // Handle references to ELF symbols from our own object files.
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
return true return true
} }
@ -233,7 +234,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case objabi.R_ADDR: case objabi.R_ADDR:
if s.Type != ld.SDATA { if s.Type != sym.SDATA {
break break
} }
if ld.Iself { if ld.Iself {
@ -250,7 +251,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write32(uint32(sectoff)) ctxt.Out.Write32(uint32(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -321,13 +322,13 @@ func elfsetupplt(ctxt *ld.Link) {
} }
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
if r.Type == objabi.R_PCREL { if r.Type == objabi.R_PCREL {
if rs.Type == ld.SHOSTOBJ { if rs.Type == sym.SHOSTOBJ {
ld.Errorf(s, "pc-relative relocation of external symbol is not supported") ld.Errorf(s, "pc-relative relocation of external symbol is not supported")
return false return false
} }
@ -356,9 +357,9 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
return true return true
} }
if rs.Type == ld.SHOSTOBJ || r.Type == objabi.R_CALLARM { if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_CALLARM {
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -367,7 +368,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
} else { } else {
v = uint32(rs.Sect.Extnum) v = uint32(rs.Sect.Extnum)
if v == 0 { if v == 0 {
ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
return false return false
} }
} }
@ -422,7 +423,7 @@ func immrot(v uint32) uint32 {
} }
// Convert the direct jump relocation r to refer to a trampoline if the target is too far // Convert the direct jump relocation r to refer to a trampoline if the target is too far
func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) { func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
switch r.Type { switch r.Type {
case objabi.R_CALLARM: case objabi.R_CALLARM:
// r.Add is the instruction // r.Add is the instruction
@ -433,11 +434,11 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
// look up existing trampolines first. if we found one within the range // look up existing trampolines first. if we found one within the range
// of direct call, we can reuse it. otherwise create a new one. // of direct call, we can reuse it. otherwise create a new one.
offset := (signext24(r.Add&0xffffff) + 2) * 4 offset := (signext24(r.Add&0xffffff) + 2) * 4
var tramp *ld.Symbol var tramp *sym.Symbol
for i := 0; ; i++ { for i := 0; ; i++ {
name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i) name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i)
tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version)) tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
if tramp.Type == ld.SDYNIMPORT { if tramp.Type == sym.SDYNIMPORT {
// don't reuse trampoline defined in other module // don't reuse trampoline defined in other module
continue continue
} }
@ -475,12 +476,12 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
r.Done = false r.Done = false
} }
default: default:
ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
} }
} }
// generate a trampoline to target+offset // generate a trampoline to target+offset
func gentramp(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) { func gentramp(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
tramp.Size = 12 // 3 instructions tramp.Size = 12 // 3 instructions
tramp.P = make([]byte, tramp.Size) tramp.P = make([]byte, tramp.Size)
t := ld.Symaddr(target) + int64(offset) t := ld.Symaddr(target) + int64(offset)
@ -502,7 +503,7 @@ func gentramp(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) {
} }
// generate a trampoline to target+offset in position independent code // generate a trampoline to target+offset in position independent code
func gentramppic(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) { func gentramppic(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
tramp.Size = 16 // 4 instructions tramp.Size = 16 // 4 instructions
tramp.P = make([]byte, tramp.Size) tramp.P = make([]byte, tramp.Size)
o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 4) // MOVW 4(R15), R11 // R15 is actual pc + 8 o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 4) // MOVW 4(R15), R11 // R15 is actual pc + 8
@ -523,7 +524,7 @@ func gentramppic(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) {
} }
// generate a trampoline to target+offset in dynlink mode (using GOT) // generate a trampoline to target+offset in dynlink mode (using GOT)
func gentrampdyn(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) { func gentrampdyn(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
tramp.Size = 20 // 5 instructions tramp.Size = 20 // 5 instructions
o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 8) // MOVW 8(R15), R11 // R15 is actual pc + 8 o1 := uint32(0xe5900000 | 11<<12 | 15<<16 | 8) // MOVW 8(R15), R11 // R15 is actual pc + 8
o2 := uint32(0xe0800000 | 11<<12 | 15<<16 | 11) // ADD R15, R11, R11 o2 := uint32(0xe0800000 | 11<<12 | 15<<16 | 11) // ADD R15, R11, R11
@ -562,7 +563,7 @@ func gentrampdyn(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) {
} }
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
switch r.Type { switch r.Type {
case objabi.R_CALLARM: case objabi.R_CALLARM:
@ -578,7 +579,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
rs = rs.Outer rs = rs.Outer
} }
if rs.Type != ld.SHOSTOBJ && rs.Type != ld.SDYNIMPORT && rs.Sect == nil { if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name) ld.Errorf(s, "missing section for %s", rs.Name)
} }
r.Xsym = rs r.Xsym = rs
@ -642,27 +643,27 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant") log.Fatalf("unexpected relocation variant")
return t return t
} }
func addpltreloc(ctxt *ld.Link, plt *ld.Symbol, got *ld.Symbol, sym *ld.Symbol, typ objabi.RelocType) *ld.Reloc { func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) *sym.Reloc {
r := plt.AddRel() r := plt.AddRel()
r.Sym = got r.Sym = got
r.Off = int32(plt.Size) r.Off = int32(plt.Size)
r.Siz = 4 r.Siz = 4
r.Type = typ r.Type = typ
r.Add = int64(sym.Got) - 8 r.Add = int64(s.Got) - 8
plt.Attr |= ld.AttrReachable plt.Attr |= sym.AttrReachable
plt.Size += 4 plt.Size += 4
plt.Grow(plt.Size) plt.Grow(plt.Size)
return r return r
} }
func addpltsym(ctxt *ld.Link, s *ld.Symbol) { func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Plt >= 0 { if s.Plt >= 0 {
return return
} }
@ -701,7 +702,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
} }
} }
func addgotsyminternal(ctxt *ld.Link, s *ld.Symbol) { func addgotsyminternal(ctxt *ld.Link, s *sym.Symbol) {
if s.Got >= 0 { if s.Got >= 0 {
return return
} }
@ -717,7 +718,7 @@ func addgotsyminternal(ctxt *ld.Link, s *ld.Symbol) {
} }
} }
func addgotsym(ctxt *ld.Link, s *ld.Symbol) { func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Got >= 0 { if s.Got >= 0 {
return return
} }

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"log" "log"
@ -44,16 +45,16 @@ func gentext(ctxt *ld.Link) {
return return
} }
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT { if addmoduledata.Type == sym.STEXT {
// we're linking a module containing the runtime -> no need for // we're linking a module containing the runtime -> no need for
// an init function // an init function
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
o := func(op uint32) { o := func(op uint32) {
initfunc.AddUint32(ctxt.Arch, op) initfunc.AddUint32(ctxt.Arch, op)
} }
@ -81,18 +82,18 @@ func gentext(ctxt *ld.Link) {
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
log.Fatalf("adddynrel not implemented") log.Fatalf("adddynrel not implemented")
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write64(uint64(sectoff)) ctxt.Out.Write64(uint64(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -143,7 +144,7 @@ func elfsetupplt(ctxt *ld.Link) {
return return
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
@ -151,9 +152,9 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
// ld64 has a bug handling MACHO_ARM64_RELOC_UNSIGNED with !extern relocation. // ld64 has a bug handling MACHO_ARM64_RELOC_UNSIGNED with !extern relocation.
// see cmd/internal/ld/data.go for details. The workaround is that don't use !extern // see cmd/internal/ld/data.go for details. The workaround is that don't use !extern
// UNSIGNED relocation at all. // UNSIGNED relocation at all.
if rs.Type == ld.SHOSTOBJ || r.Type == objabi.R_CALLARM64 || r.Type == objabi.R_ADDRARM64 || r.Type == objabi.R_ADDR { if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_CALLARM64 || r.Type == objabi.R_ADDRARM64 || r.Type == objabi.R_ADDR {
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -162,7 +163,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
} else { } else {
v = uint32(rs.Sect.Extnum) v = uint32(rs.Sect.Extnum)
if v == 0 { if v == 0 {
ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
return false return false
} }
} }
@ -215,7 +216,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
return true return true
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
switch r.Type { switch r.Type {
default: default:
@ -237,7 +238,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So // (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp; // we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
// add + R_ADDRARM64. // add + R_ADDRARM64.
if !(r.Sym.Version != 0 || (r.Sym.Type&ld.SHIDDEN != 0) || r.Sym.Attr.Local()) && r.Sym.Type == ld.STEXT && ctxt.DynlinkingGo() { if !(r.Sym.Version != 0 || (r.Sym.Type&sym.SHIDDEN != 0) || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
if o2&0xffc00000 != 0xf9400000 { if o2&0xffc00000 != 0xf9400000 {
ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2) ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
} }
@ -261,7 +262,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
rs = rs.Outer rs = rs.Outer
} }
if rs.Type != ld.SHOSTOBJ && rs.Type != ld.SDYNIMPORT && rs.Sect == nil { if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name) ld.Errorf(s, "missing section for %s", rs.Name)
} }
r.Xsym = rs r.Xsym = rs
@ -367,7 +368,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant") log.Fatalf("unexpected relocation variant")
return -1 return -1
} }

View file

@ -33,6 +33,7 @@ package ld
import ( import (
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
@ -105,7 +106,7 @@ func hostArchive(ctxt *Link, name string) {
var load []uint64 var load []uint64
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
for _, r := range s.R { for _, r := range s.R {
if r.Sym != nil && r.Sym.Type&SMASK == SXREF { if r.Sym != nil && r.Sym.Type&sym.SMASK == sym.SXREF {
if off := armap[r.Sym.Name]; off != 0 && !loaded[off] { if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
load = append(load, off) load = append(load, off)
loaded[off] = true loaded[off] = true

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"fmt" "fmt"
"strings" "strings"
"unicode" "unicode"
@ -112,13 +113,13 @@ func deadcode(ctxt *Link) {
// (When BuildmodeShared, always keep itablinks.) // (When BuildmodeShared, always keep itablinks.)
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if strings.HasPrefix(s.Name, "go.itablink.") { if strings.HasPrefix(s.Name, "go.itablink.") {
s.Attr.Set(AttrReachable, len(s.R) == 1 && s.R[0].Sym.Attr.Reachable()) s.Attr.Set(sym.AttrReachable, len(s.R) == 1 && s.R[0].Sym.Attr.Reachable())
} }
} }
} }
// Remove dead text but keep file information (z symbols). // Remove dead text but keep file information (z symbols).
textp := make([]*Symbol, 0, len(ctxt.Textp)) textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if s.Attr.Reachable() { if s.Attr.Reachable() {
textp = append(textp, s) textp = append(textp, s)
@ -132,11 +133,11 @@ func deadcode(ctxt *Link) {
// the reflect.method struct: mtyp, ifn, and tfn. // the reflect.method struct: mtyp, ifn, and tfn.
type methodref struct { type methodref struct {
m methodsig m methodsig
src *Symbol // receiver type symbol src *sym.Symbol // receiver type symbol
r [3]*Reloc // R_METHODOFF relocations to fields of runtime.method r [3]*sym.Reloc // R_METHODOFF relocations to fields of runtime.method
} }
func (m methodref) ifn() *Symbol { return m.r[1].Sym } func (m methodref) ifn() *sym.Symbol { return m.r[1].Sym }
func (m methodref) isExported() bool { func (m methodref) isExported() bool {
for _, r := range m.m { for _, r := range m.m {
@ -148,13 +149,13 @@ func (m methodref) isExported() bool {
// deadcodepass holds state for the deadcode flood fill. // deadcodepass holds state for the deadcode flood fill.
type deadcodepass struct { type deadcodepass struct {
ctxt *Link ctxt *Link
markQueue []*Symbol // symbols to flood fill in next pass markQueue []*sym.Symbol // symbols to flood fill in next pass
ifaceMethod map[methodsig]bool // methods declared in reached interfaces ifaceMethod map[methodsig]bool // methods declared in reached interfaces
markableMethods []methodref // methods of reached types markableMethods []methodref // methods of reached types
reflectMethod bool reflectMethod bool
} }
func (d *deadcodepass) cleanupReloc(r *Reloc) { func (d *deadcodepass) cleanupReloc(r *sym.Reloc) {
if r.Sym.Attr.Reachable() { if r.Sym.Attr.Reachable() {
r.Type = objabi.R_ADDROFF r.Type = objabi.R_ADDROFF
} else { } else {
@ -167,7 +168,7 @@ func (d *deadcodepass) cleanupReloc(r *Reloc) {
} }
// mark appends a symbol to the mark queue for flood filling. // mark appends a symbol to the mark queue for flood filling.
func (d *deadcodepass) mark(s, parent *Symbol) { func (d *deadcodepass) mark(s, parent *sym.Symbol) {
if s == nil || s.Attr.Reachable() { if s == nil || s.Attr.Reachable() {
return return
} }
@ -181,7 +182,7 @@ func (d *deadcodepass) mark(s, parent *Symbol) {
} }
fmt.Printf("%s -> %s\n", p, s.Name) fmt.Printf("%s -> %s\n", p, s.Name)
} }
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Reachparent = parent s.Reachparent = parent
d.markQueue = append(d.markQueue, s) d.markQueue = append(d.markQueue, s)
} }
@ -208,7 +209,7 @@ func (d *deadcodepass) init() {
// Mark all symbols defined in this library as reachable when // Mark all symbols defined in this library as reachable when
// building a shared library. // building a shared library.
for _, s := range d.ctxt.Syms.Allsym { for _, s := range d.ctxt.Syms.Allsym {
if s.Type != 0 && s.Type != SDYNIMPORT { if s.Type != 0 && s.Type != sym.SDYNIMPORT {
d.mark(s, nil) d.mark(s, nil)
} }
} }
@ -257,7 +258,7 @@ func (d *deadcodepass) flood() {
for len(d.markQueue) > 0 { for len(d.markQueue) > 0 {
s := d.markQueue[0] s := d.markQueue[0]
d.markQueue = d.markQueue[1:] d.markQueue = d.markQueue[1:]
if s.Type == STEXT { if s.Type == sym.STEXT {
if d.ctxt.Debugvlog > 1 { if d.ctxt.Debugvlog > 1 {
d.ctxt.Logf("marktext %s\n", s.Name) d.ctxt.Logf("marktext %s\n", s.Name)
} }

View file

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"debug/elf" "debug/elf"
"fmt" "fmt"
) )
@ -28,7 +29,7 @@ const (
tflagExtraStar = 1 << 1 tflagExtraStar = 1 << 1
) )
func decodeReloc(s *Symbol, off int32) *Reloc { func decodeReloc(s *sym.Symbol, off int32) *sym.Reloc {
for i := range s.R { for i := range s.R {
if s.R[i].Off == off { if s.R[i].Off == off {
return &s.R[i] return &s.R[i]
@ -37,7 +38,7 @@ func decodeReloc(s *Symbol, off int32) *Reloc {
return nil return nil
} }
func decodeRelocSym(s *Symbol, off int32) *Symbol { func decodeRelocSym(s *sym.Symbol, off int32) *sym.Symbol {
r := decodeReloc(s, off) r := decodeReloc(s, off)
if r == nil { if r == nil {
return nil return nil
@ -64,27 +65,27 @@ func structfieldSize(arch *sys.Arch) int { return 3 * arch.PtrSize } // ru
func uncommonSize() int { return 4 + 2 + 2 + 4 + 4 } // runtime.uncommontype func uncommonSize() int { return 4 + 2 + 2 + 4 + 4 } // runtime.uncommontype
// Type.commonType.kind // Type.commonType.kind
func decodetypeKind(arch *sys.Arch, s *Symbol) uint8 { func decodetypeKind(arch *sys.Arch, s *sym.Symbol) uint8 {
return s.P[2*arch.PtrSize+7] & objabi.KindMask // 0x13 / 0x1f return s.P[2*arch.PtrSize+7] & objabi.KindMask // 0x13 / 0x1f
} }
// Type.commonType.kind // Type.commonType.kind
func decodetypeUsegcprog(arch *sys.Arch, s *Symbol) uint8 { func decodetypeUsegcprog(arch *sys.Arch, s *sym.Symbol) uint8 {
return s.P[2*arch.PtrSize+7] & objabi.KindGCProg // 0x13 / 0x1f return s.P[2*arch.PtrSize+7] & objabi.KindGCProg // 0x13 / 0x1f
} }
// Type.commonType.size // Type.commonType.size
func decodetypeSize(arch *sys.Arch, s *Symbol) int64 { func decodetypeSize(arch *sys.Arch, s *sym.Symbol) int64 {
return int64(decodeInuxi(arch, s.P, arch.PtrSize)) // 0x8 / 0x10 return int64(decodeInuxi(arch, s.P, arch.PtrSize)) // 0x8 / 0x10
} }
// Type.commonType.ptrdata // Type.commonType.ptrdata
func decodetypePtrdata(arch *sys.Arch, s *Symbol) int64 { func decodetypePtrdata(arch *sys.Arch, s *sym.Symbol) int64 {
return int64(decodeInuxi(arch, s.P[arch.PtrSize:], arch.PtrSize)) // 0x8 / 0x10 return int64(decodeInuxi(arch, s.P[arch.PtrSize:], arch.PtrSize)) // 0x8 / 0x10
} }
// Type.commonType.tflag // Type.commonType.tflag
func decodetypeHasUncommon(arch *sys.Arch, s *Symbol) bool { func decodetypeHasUncommon(arch *sys.Arch, s *sym.Symbol) bool {
return s.P[2*arch.PtrSize+4]&tflagUncommon != 0 return s.P[2*arch.PtrSize+4]&tflagUncommon != 0
} }
@ -103,8 +104,8 @@ func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
} }
// Type.commonType.gc // Type.commonType.gc
func decodetypeGcprog(ctxt *Link, s *Symbol) []byte { func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
addr := decodetypeGcprogShlib(ctxt, s) addr := decodetypeGcprogShlib(ctxt, s)
sect := findShlibSection(ctxt, s.File, addr) sect := findShlibSection(ctxt, s.File, addr)
if sect != nil { if sect != nil {
@ -122,7 +123,7 @@ func decodetypeGcprog(ctxt *Link, s *Symbol) []byte {
return decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)).P return decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)).P
} }
func decodetypeGcprogShlib(ctxt *Link, s *Symbol) uint64 { func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
if ctxt.Arch.Family == sys.ARM64 { if ctxt.Arch.Family == sys.ARM64 {
for _, shlib := range ctxt.Shlibs { for _, shlib := range ctxt.Shlibs {
if shlib.Path == s.File { if shlib.Path == s.File {
@ -134,8 +135,8 @@ func decodetypeGcprogShlib(ctxt *Link, s *Symbol) uint64 {
return decodeInuxi(ctxt.Arch, s.P[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize) return decodeInuxi(ctxt.Arch, s.P[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
} }
func decodetypeGcmask(ctxt *Link, s *Symbol) []byte { func decodetypeGcmask(ctxt *Link, s *sym.Symbol) []byte {
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
addr := decodetypeGcprogShlib(ctxt, s) addr := decodetypeGcprogShlib(ctxt, s)
ptrdata := decodetypePtrdata(ctxt.Arch, s) ptrdata := decodetypePtrdata(ctxt.Arch, s)
sect := findShlibSection(ctxt, s.File, addr) sect := findShlibSection(ctxt, s.File, addr)
@ -152,48 +153,48 @@ func decodetypeGcmask(ctxt *Link, s *Symbol) []byte {
} }
// Type.ArrayType.elem and Type.SliceType.Elem // Type.ArrayType.elem and Type.SliceType.Elem
func decodetypeArrayElem(arch *sys.Arch, s *Symbol) *Symbol { func decodetypeArrayElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30 return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
} }
func decodetypeArrayLen(arch *sys.Arch, s *Symbol) int64 { func decodetypeArrayLen(arch *sys.Arch, s *sym.Symbol) int64 {
return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
} }
// Type.PtrType.elem // Type.PtrType.elem
func decodetypePtrElem(arch *sys.Arch, s *Symbol) *Symbol { func decodetypePtrElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30 return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
} }
// Type.MapType.key, elem // Type.MapType.key, elem
func decodetypeMapKey(arch *sys.Arch, s *Symbol) *Symbol { func decodetypeMapKey(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30 return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
} }
func decodetypeMapValue(arch *sys.Arch, s *Symbol) *Symbol { func decodetypeMapValue(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
return decodeRelocSym(s, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38 return decodeRelocSym(s, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38
} }
// Type.ChanType.elem // Type.ChanType.elem
func decodetypeChanElem(arch *sys.Arch, s *Symbol) *Symbol { func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30 return decodeRelocSym(s, int32(commonsize(arch))) // 0x1c / 0x30
} }
// Type.FuncType.dotdotdot // Type.FuncType.dotdotdot
func decodetypeFuncDotdotdot(arch *sys.Arch, s *Symbol) bool { func decodetypeFuncDotdotdot(arch *sys.Arch, s *sym.Symbol) bool {
return uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2))&(1<<15) != 0 return uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2))&(1<<15) != 0
} }
// Type.FuncType.inCount // Type.FuncType.inCount
func decodetypeFuncInCount(arch *sys.Arch, s *Symbol) int { func decodetypeFuncInCount(arch *sys.Arch, s *sym.Symbol) int {
return int(decodeInuxi(arch, s.P[commonsize(arch):], 2)) return int(decodeInuxi(arch, s.P[commonsize(arch):], 2))
} }
func decodetypeFuncOutCount(arch *sys.Arch, s *Symbol) int { func decodetypeFuncOutCount(arch *sys.Arch, s *sym.Symbol) int {
return int(uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2)) & (1<<15 - 1)) return int(uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2)) & (1<<15 - 1))
} }
func decodetypeFuncInType(arch *sys.Arch, s *Symbol, i int) *Symbol { func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
uadd := commonsize(arch) + 4 uadd := commonsize(arch) + 4
if arch.PtrSize == 8 { if arch.PtrSize == 8 {
uadd += 4 uadd += 4
@ -204,16 +205,16 @@ func decodetypeFuncInType(arch *sys.Arch, s *Symbol, i int) *Symbol {
return decodeRelocSym(s, int32(uadd+i*arch.PtrSize)) return decodeRelocSym(s, int32(uadd+i*arch.PtrSize))
} }
func decodetypeFuncOutType(arch *sys.Arch, s *Symbol, i int) *Symbol { func decodetypeFuncOutType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
return decodetypeFuncInType(arch, s, i+decodetypeFuncInCount(arch, s)) return decodetypeFuncInType(arch, s, i+decodetypeFuncInCount(arch, s))
} }
// Type.StructType.fields.Slice::length // Type.StructType.fields.Slice::length
func decodetypeStructFieldCount(arch *sys.Arch, s *Symbol) int { func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
return int(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) return int(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
} }
func decodetypeStructFieldArrayOff(arch *sys.Arch, s *Symbol, i int) int { func decodetypeStructFieldArrayOff(arch *sys.Arch, s *sym.Symbol, i int) int {
off := commonsize(arch) + 4*arch.PtrSize off := commonsize(arch) + 4*arch.PtrSize
if decodetypeHasUncommon(arch, s) { if decodetypeHasUncommon(arch, s) {
off += uncommonSize() off += uncommonSize()
@ -223,7 +224,7 @@ func decodetypeStructFieldArrayOff(arch *sys.Arch, s *Symbol, i int) int {
} }
// decodetypeStr returns the contents of an rtype's str field (a nameOff). // decodetypeStr returns the contents of an rtype's str field (a nameOff).
func decodetypeStr(arch *sys.Arch, s *Symbol) string { func decodetypeStr(arch *sys.Arch, s *sym.Symbol) string {
str := decodetypeName(s, 4*arch.PtrSize+8) str := decodetypeName(s, 4*arch.PtrSize+8)
if s.P[2*arch.PtrSize+4]&tflagExtraStar != 0 { if s.P[2*arch.PtrSize+4]&tflagExtraStar != 0 {
return str[1:] return str[1:]
@ -232,7 +233,7 @@ func decodetypeStr(arch *sys.Arch, s *Symbol) string {
} }
// decodetypeName decodes the name from a reflect.name. // decodetypeName decodes the name from a reflect.name.
func decodetypeName(s *Symbol, off int) string { func decodetypeName(s *sym.Symbol, off int) string {
r := decodeReloc(s, int32(off)) r := decodeReloc(s, int32(off))
if r == nil { if r == nil {
return "" return ""
@ -243,27 +244,27 @@ func decodetypeName(s *Symbol, off int) string {
return string(data[3 : 3+namelen]) return string(data[3 : 3+namelen])
} }
func decodetypeStructFieldName(arch *sys.Arch, s *Symbol, i int) string { func decodetypeStructFieldName(arch *sys.Arch, s *sym.Symbol, i int) string {
off := decodetypeStructFieldArrayOff(arch, s, i) off := decodetypeStructFieldArrayOff(arch, s, i)
return decodetypeName(s, off) return decodetypeName(s, off)
} }
func decodetypeStructFieldType(arch *sys.Arch, s *Symbol, i int) *Symbol { func decodetypeStructFieldType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
off := decodetypeStructFieldArrayOff(arch, s, i) off := decodetypeStructFieldArrayOff(arch, s, i)
return decodeRelocSym(s, int32(off+arch.PtrSize)) return decodeRelocSym(s, int32(off+arch.PtrSize))
} }
func decodetypeStructFieldOffs(arch *sys.Arch, s *Symbol, i int) int64 { func decodetypeStructFieldOffs(arch *sys.Arch, s *sym.Symbol, i int) int64 {
return decodetypeStructFieldOffsAnon(arch, s, i) >> 1 return decodetypeStructFieldOffsAnon(arch, s, i) >> 1
} }
func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *Symbol, i int) int64 { func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
off := decodetypeStructFieldArrayOff(arch, s, i) off := decodetypeStructFieldArrayOff(arch, s, i)
return int64(decodeInuxi(arch, s.P[off+2*arch.PtrSize:], arch.PtrSize)) return int64(decodeInuxi(arch, s.P[off+2*arch.PtrSize:], arch.PtrSize))
} }
// InterfaceType.methods.length // InterfaceType.methods.length
func decodetypeIfaceMethodCount(arch *sys.Arch, s *Symbol) int64 { func decodetypeIfaceMethodCount(arch *sys.Arch, s *sym.Symbol) int64 {
return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
} }
@ -290,7 +291,7 @@ const (
// the function type. // the function type.
// //
// Conveniently this is the layout of both runtime.method and runtime.imethod. // Conveniently this is the layout of both runtime.method and runtime.imethod.
func decodeMethodSig(arch *sys.Arch, s *Symbol, off, size, count int) []methodsig { func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []methodsig {
var buf bytes.Buffer var buf bytes.Buffer
var methods []methodsig var methods []methodsig
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
@ -322,7 +323,7 @@ func decodeMethodSig(arch *sys.Arch, s *Symbol, off, size, count int) []methodsi
return methods return methods
} }
func decodeIfaceMethods(arch *sys.Arch, s *Symbol) []methodsig { func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
if decodetypeKind(arch, s)&kindMask != kindInterface { if decodetypeKind(arch, s)&kindMask != kindInterface {
panic(fmt.Sprintf("symbol %q is not an interface", s.Name)) panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
} }
@ -339,7 +340,7 @@ func decodeIfaceMethods(arch *sys.Arch, s *Symbol) []methodsig {
return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods) return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods)
} }
func decodetypeMethods(arch *sys.Arch, s *Symbol) []methodsig { func decodetypeMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
if !decodetypeHasUncommon(arch, s) { if !decodetypeHasUncommon(arch, s) {
panic(fmt.Sprintf("no methods on %q", s.Name)) panic(fmt.Sprintf("no methods on %q", s.Name))
} }

View file

@ -17,6 +17,7 @@ import (
"cmd/internal/dwarf" "cmd/internal/dwarf"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"fmt" "fmt"
"log" "log"
"os" "os"
@ -31,37 +32,37 @@ func (c dwctxt) PtrSize() int {
return c.linkctxt.Arch.PtrSize return c.linkctxt.Arch.PtrSize
} }
func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) { func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) {
ls := s.(*Symbol) ls := s.(*sym.Symbol)
ls.addUintXX(c.linkctxt.Arch, uint64(i), size) ls.AddUintXX(c.linkctxt.Arch, uint64(i), size)
} }
func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) { func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) {
ls := s.(*Symbol) ls := s.(*sym.Symbol)
ls.AddBytes(b) ls.AddBytes(b)
} }
func (c dwctxt) AddString(s dwarf.Sym, v string) { func (c dwctxt) AddString(s dwarf.Sym, v string) {
Addstring(s.(*Symbol), v) Addstring(s.(*sym.Symbol), v)
} }
func (c dwctxt) SymValue(s dwarf.Sym) int64 { func (c dwctxt) SymValue(s dwarf.Sym) int64 {
return s.(*Symbol).Value return s.(*sym.Symbol).Value
} }
func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
if value != 0 { if value != 0 {
value -= (data.(*Symbol)).Value value -= (data.(*sym.Symbol)).Value
} }
s.(*Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*Symbol), value) s.(*sym.Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value)
} }
func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
ls := s.(*Symbol) ls := s.(*sym.Symbol)
switch size { switch size {
default: default:
Errorf(ls, "invalid size %d in adddwarfref\n", size) Errorf(ls, "invalid size %d in adddwarfref\n", size)
fallthrough fallthrough
case c.linkctxt.Arch.PtrSize: case c.linkctxt.Arch.PtrSize:
ls.AddAddr(c.linkctxt.Arch, t.(*Symbol)) ls.AddAddr(c.linkctxt.Arch, t.(*sym.Symbol))
case 4: case 4:
ls.AddAddrPlus4(t.(*Symbol), 0) ls.AddAddrPlus4(t.(*sym.Symbol), 0)
} }
r := &ls.R[len(ls.R)-1] r := &ls.R[len(ls.R)-1]
r.Type = objabi.R_DWARFREF r.Type = objabi.R_DWARFREF
@ -70,11 +71,11 @@ func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64
var gdbscript string var gdbscript string
var dwarfp []*Symbol var dwarfp []*sym.Symbol
func writeabbrev(ctxt *Link) *Symbol { func writeabbrev(ctxt *Link) *sym.Symbol {
s := ctxt.Syms.Lookup(".debug_abbrev", 0) s := ctxt.Syms.Lookup(".debug_abbrev", 0)
s.Type = SDWARFSECT s.Type = sym.SDWARFSECT
s.AddBytes(dwarf.GetAbbrev()) s.AddBytes(dwarf.GetAbbrev())
return s return s
} }
@ -136,10 +137,10 @@ func newdie(ctxt *Link, parent *dwarf.DWDie, abbrev int, name string, version in
if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) { if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) {
if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 { if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 {
sym := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version) s := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version)
sym.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
sym.Type = SDWARFINFO s.Type = sym.SDWARFINFO
die.Sym = sym die.Sym = s
} }
} }
@ -162,7 +163,7 @@ func walktypedef(die *dwarf.DWDie) *dwarf.DWDie {
return die return die
} }
func walksymtypedef(ctxt *Link, s *Symbol) *Symbol { func walksymtypedef(ctxt *Link, s *sym.Symbol) *sym.Symbol {
if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil { if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil {
return t return t
} }
@ -187,18 +188,18 @@ func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie {
// Used to avoid string allocation when looking up dwarf symbols // Used to avoid string allocation when looking up dwarf symbols
var prefixBuf = []byte(dwarf.InfoPrefix) var prefixBuf = []byte(dwarf.InfoPrefix)
func find(ctxt *Link, name string) *Symbol { func find(ctxt *Link, name string) *sym.Symbol {
n := append(prefixBuf, name...) n := append(prefixBuf, name...)
// The string allocation below is optimized away because it is only used in a map lookup. // The string allocation below is optimized away because it is only used in a map lookup.
s := ctxt.Syms.ROLookup(string(n), 0) s := ctxt.Syms.ROLookup(string(n), 0)
prefixBuf = n[:len(dwarf.InfoPrefix)] prefixBuf = n[:len(dwarf.InfoPrefix)]
if s != nil && s.Type == SDWARFINFO { if s != nil && s.Type == sym.SDWARFINFO {
return s return s
} }
return nil return nil
} }
func mustFind(ctxt *Link, name string) *Symbol { func mustFind(ctxt *Link, name string) *sym.Symbol {
r := find(ctxt, name) r := find(ctxt, name)
if r == nil { if r == nil {
Exitf("dwarf find: cannot find %s", name) Exitf("dwarf find: cannot find %s", name)
@ -206,7 +207,7 @@ func mustFind(ctxt *Link, name string) *Symbol {
return r return r
} }
func adddwarfref(ctxt *Link, s *Symbol, t *Symbol, size int) int64 { func adddwarfref(ctxt *Link, s *sym.Symbol, t *sym.Symbol, size int) int64 {
var result int64 var result int64
switch size { switch size {
default: default:
@ -222,14 +223,14 @@ func adddwarfref(ctxt *Link, s *Symbol, t *Symbol, size int) int64 {
return result return result
} }
func newrefattr(die *dwarf.DWDie, attr uint16, ref *Symbol) *dwarf.DWAttr { func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr {
if ref == nil { if ref == nil {
return nil return nil
} }
return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref) return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
} }
func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol { func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
for ; die != nil; die = die.Link { for ; die != nil; die = die.Link {
syms = putdie(linkctxt, ctxt, syms, die) syms = putdie(linkctxt, ctxt, syms, die)
} }
@ -238,14 +239,14 @@ func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDi
return syms return syms
} }
func dtolsym(s dwarf.Sym) *Symbol { func dtolsym(s dwarf.Sym) *sym.Symbol {
if s == nil { if s == nil {
return nil return nil
} }
return s.(*Symbol) return s.(*sym.Symbol)
} }
func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol { func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
s := dtolsym(die.Sym) s := dtolsym(die.Sym)
if s == nil { if s == nil {
s = syms[len(syms)-1] s = syms[len(syms)-1]
@ -253,7 +254,7 @@ func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
syms = append(syms, s) syms = append(syms, s)
} }
dwarf.Uleb128put(ctxt, s, int64(die.Abbrev)) dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
@ -292,13 +293,13 @@ func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
// GDB doesn't like FORM_addr for AT_location, so emit a // GDB doesn't like FORM_addr for AT_location, so emit a
// location expression that evals to a const. // location expression that evals to a const.
func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *Symbol) { func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *sym.Symbol) {
newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym) newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym)
// below // below
} }
// Lookup predefined types // Lookup predefined types
func lookupOrDiag(ctxt *Link, n string) *Symbol { func lookupOrDiag(ctxt *Link, n string) *sym.Symbol {
s := ctxt.Syms.ROLookup(n, 0) s := ctxt.Syms.ROLookup(n, 0)
if s == nil || s.Size == 0 { if s == nil || s.Size == 0 {
Exitf("dwarf: missing type: %s", n) Exitf("dwarf: missing type: %s", n)
@ -325,10 +326,10 @@ func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) {
Errorf(nil, "dwarf: bad def in dotypedef") Errorf(nil, "dwarf: bad def in dotypedef")
} }
sym := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0) s := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0)
sym.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
sym.Type = SDWARFINFO s.Type = sym.SDWARFINFO
def.Sym = sym def.Sym = s
// The typedef entry must be created after the def, // The typedef entry must be created after the def,
// so that future lookups will find the typedef instead // so that future lookups will find the typedef instead
@ -336,11 +337,11 @@ func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) {
// circular definition loops, so that gdb can understand them. // circular definition loops, so that gdb can understand them.
die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0) die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0)
newrefattr(die, dwarf.DW_AT_type, sym) newrefattr(die, dwarf.DW_AT_type, s)
} }
// Define gotype, for composite ones recurse into constituents. // Define gotype, for composite ones recurse into constituents.
func defgotype(ctxt *Link, gotype *Symbol) *Symbol { func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol {
if gotype == nil { if gotype == nil {
return mustFind(ctxt, "<unspecified>") return mustFind(ctxt, "<unspecified>")
} }
@ -358,10 +359,10 @@ func defgotype(ctxt *Link, gotype *Symbol) *Symbol {
return sdie return sdie
} }
return newtype(ctxt, gotype).Sym.(*Symbol) return newtype(ctxt, gotype).Sym.(*sym.Symbol)
} }
func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie { func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
name := gotype.Name[5:] // could also decode from Type.string name := gotype.Name[5:] // could also decode from Type.string
kind := decodetypeKind(ctxt.Arch, gotype) kind := decodetypeKind(ctxt.Arch, gotype)
bytesize := decodetypeSize(ctxt.Arch, gotype) bytesize := decodetypeSize(ctxt.Arch, gotype)
@ -433,7 +434,7 @@ func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie {
newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "void")) newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "void"))
nfields := decodetypeFuncInCount(ctxt.Arch, gotype) nfields := decodetypeFuncInCount(ctxt.Arch, gotype)
var fld *dwarf.DWDie var fld *dwarf.DWDie
var s *Symbol var s *sym.Symbol
for i := 0; i < nfields; i++ { for i := 0; i < nfields; i++ {
s = decodetypeFuncInType(ctxt.Arch, gotype, i) s = decodetypeFuncInType(ctxt.Arch, gotype, i)
fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0) fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
@ -455,7 +456,7 @@ func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie {
dotypedef(ctxt, &dwtypes, name, die) dotypedef(ctxt, &dwtypes, name, die)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype)) nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype))
var s *Symbol var s *sym.Symbol
if nfields == 0 { if nfields == 0 {
s = lookupOrDiag(ctxt, "type.runtime.eface") s = lookupOrDiag(ctxt, "type.runtime.eface")
} else { } else {
@ -529,12 +530,12 @@ func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie {
return die return die
} }
func nameFromDIESym(dwtype *Symbol) string { func nameFromDIESym(dwtype *sym.Symbol) string {
return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def") return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def")
} }
// Find or construct *T given T. // Find or construct *T given T.
func defptrto(ctxt *Link, dwtype *Symbol) *Symbol { func defptrto(ctxt *Link, dwtype *sym.Symbol) *sym.Symbol {
ptrname := "*" + nameFromDIESym(dwtype) ptrname := "*" + nameFromDIESym(dwtype)
die := find(ctxt, ptrname) die := find(ctxt, ptrname)
if die == nil { if die == nil {
@ -570,7 +571,7 @@ func copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) {
// Search children (assumed to have TAG_member) for the one named // Search children (assumed to have TAG_member) for the one named
// field and set its AT_type to dwtype // field and set its AT_type to dwtype
func substitutetype(structdie *dwarf.DWDie, field string, dwtype *Symbol) { func substitutetype(structdie *dwarf.DWDie, field string, dwtype *sym.Symbol) {
child := findchild(structdie, field) child := findchild(structdie, field)
if child == nil { if child == nil {
Exitf("dwarf substitutetype: %s does not have member %s", Exitf("dwarf substitutetype: %s does not have member %s",
@ -620,7 +621,7 @@ func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
continue continue
} }
copychildren(ctxt, die, prototype) copychildren(ctxt, die, prototype)
elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*Symbol) elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*sym.Symbol)
substitutetype(die, "array", defptrto(ctxt, elem)) substitutetype(die, "array", defptrto(ctxt, elem))
} }
} }
@ -644,11 +645,11 @@ const (
BucketSize = 8 BucketSize = 8
) )
func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *Symbol { func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *sym.Symbol {
name := mkinternaltypename(typename, keyname, valname) name := mkinternaltypename(typename, keyname, valname)
symname := dwarf.InfoPrefix + name symname := dwarf.InfoPrefix + name
s := ctxt.Syms.ROLookup(symname, 0) s := ctxt.Syms.ROLookup(symname, 0)
if s != nil && s.Type == SDWARFINFO { if s != nil && s.Type == sym.SDWARFINFO {
return s return s
} }
die := newdie(ctxt, &dwtypes, abbrev, name, 0) die := newdie(ctxt, &dwtypes, abbrev, name, 0)
@ -668,7 +669,7 @@ func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
if die.Abbrev != dwarf.DW_ABRV_MAPTYPE { if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
continue continue
} }
gotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol) gotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
keytype := decodetypeMapKey(ctxt.Arch, gotype) keytype := decodetypeMapKey(ctxt.Arch, gotype)
valtype := decodetypeMapValue(ctxt.Arch, gotype) valtype := decodetypeMapValue(ctxt.Arch, gotype)
keysize, valsize := decodetypeSize(ctxt.Arch, keytype), decodetypeSize(ctxt.Arch, valtype) keysize, valsize := decodetypeSize(ctxt.Arch, keytype), decodetypeSize(ctxt.Arch, valtype)
@ -764,7 +765,7 @@ func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
if die.Abbrev != dwarf.DW_ABRV_CHANTYPE { if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
continue continue
} }
elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol) elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
elemname := elemgotype.Name[5:] elemname := elemgotype.Name[5:]
elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype)) elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype))
@ -797,30 +798,30 @@ func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
} }
// For use with pass.c::genasmsym // For use with pass.c::genasmsym
func defdwsymb(ctxt *Link, sym *Symbol, s string, t SymbolType, v int64, gotype *Symbol) { func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, gotype *sym.Symbol) {
if strings.HasPrefix(s, "go.string.") { if strings.HasPrefix(str, "go.string.") {
return return
} }
if strings.HasPrefix(s, "runtime.gcbits.") { if strings.HasPrefix(str, "runtime.gcbits.") {
return return
} }
if strings.HasPrefix(s, "type.") && s != "type.*" && !strings.HasPrefix(s, "type..") { if strings.HasPrefix(str, "type.") && str != "type.*" && !strings.HasPrefix(str, "type..") {
defgotype(ctxt, sym) defgotype(ctxt, s)
return return
} }
var dv *dwarf.DWDie var dv *dwarf.DWDie
var dt *Symbol var dt *sym.Symbol
switch t { switch t {
default: default:
return return
case DataSym, BSSSym: case DataSym, BSSSym:
dv = newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, s, int(sym.Version)) dv = newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
newabslocexprattr(dv, v, sym) newabslocexprattr(dv, v, s)
if sym.Version == 0 { if s.Version == 0 {
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0) newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
} }
fallthrough fallthrough
@ -847,7 +848,7 @@ func movetomodule(parent *dwarf.DWDie) {
} }
// If the pcln table contains runtime/proc.go, use that to set gdbscript path. // If the pcln table contains runtime/proc.go, use that to set gdbscript path.
func finddebugruntimepath(s *Symbol) { func finddebugruntimepath(s *sym.Symbol) {
if gdbscript != "" { if gdbscript != "" {
return return
} }
@ -875,7 +876,7 @@ const (
OPCODE_BASE = 10 OPCODE_BASE = 10
) )
func putpclcdelta(linkctxt *Link, ctxt dwarf.Context, s *Symbol, deltaPC uint64, deltaLC int64) { func putpclcdelta(linkctxt *Link, ctxt dwarf.Context, s *sym.Symbol, deltaPC uint64, deltaLC int64) {
// Choose a special opcode that minimizes the number of bytes needed to // Choose a special opcode that minimizes the number of bytes needed to
// encode the remaining PC delta and LC delta. // encode the remaining PC delta and LC delta.
var opcode int64 var opcode int64
@ -976,9 +977,9 @@ func getCompilationDir() string {
return "/" return "/"
} }
func importInfoSymbol(ctxt *Link, dsym *Symbol) { func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
dsym.Attr |= AttrNotInSymbolTable | AttrReachable dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
dsym.Type = SDWARFINFO dsym.Type = sym.SDWARFINFO
for _, r := range dsym.R { for _, r := range dsym.R {
if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 { if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
if Buildmode == BuildmodeShared { if Buildmode == BuildmodeShared {
@ -991,20 +992,20 @@ func importInfoSymbol(ctxt *Link, dsym *Symbol) {
} }
} }
func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) { func writelines(ctxt *Link, syms []*sym.Symbol) ([]*sym.Symbol, []*sym.Symbol) {
var dwarfctxt dwarf.Context = dwctxt{ctxt} var dwarfctxt dwarf.Context = dwctxt{ctxt}
ls := ctxt.Syms.Lookup(".debug_line", 0) ls := ctxt.Syms.Lookup(".debug_line", 0)
ls.Type = SDWARFSECT ls.Type = sym.SDWARFSECT
ls.R = ls.R[:0] ls.R = ls.R[:0]
syms = append(syms, ls) syms = append(syms, ls)
var funcs []*Symbol var funcs []*sym.Symbol
unitstart := int64(-1) unitstart := int64(-1)
headerstart := int64(-1) headerstart := int64(-1)
headerend := int64(-1) headerend := int64(-1)
epc := int64(0) epc := int64(0)
var epcs *Symbol var epcs *sym.Symbol
var dwinfo *dwarf.DWDie var dwinfo *dwarf.DWDie
lang := dwarf.DW_LANG_Go lang := dwarf.DW_LANG_Go
@ -1161,10 +1162,10 @@ func appendPCDeltaCFA(arch *sys.Arch, b []byte, deltapc, cfa int64) []byte {
return b return b
} }
func writeframes(ctxt *Link, syms []*Symbol) []*Symbol { func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
var dwarfctxt dwarf.Context = dwctxt{ctxt} var dwarfctxt dwarf.Context = dwctxt{ctxt}
fs := ctxt.Syms.Lookup(".debug_frame", 0) fs := ctxt.Syms.Lookup(".debug_frame", 0)
fs.Type = SDWARFSECT fs.Type = sym.SDWARFSECT
fs.R = fs.R[:0] fs.R = fs.R[:0]
syms = append(syms, fs) syms = append(syms, fs)
@ -1267,29 +1268,29 @@ func writeframes(ctxt *Link, syms []*Symbol) []*Symbol {
fs.AddUint32(ctxt.Arch, 0) // CIE offset fs.AddUint32(ctxt.Arch, 0) // CIE offset
} }
fs.AddAddr(ctxt.Arch, s) fs.AddAddr(ctxt.Arch, s)
fs.addUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
fs.AddBytes(deltaBuf) fs.AddBytes(deltaBuf)
} }
return syms return syms
} }
func writeranges(ctxt *Link, syms []*Symbol) []*Symbol { func writeranges(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
empty := true empty := true
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version)) rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version))
if rangeSym.Size == 0 { if rangeSym.Size == 0 {
continue continue
} }
rangeSym.Attr |= AttrReachable | AttrNotInSymbolTable rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
rangeSym.Type = SDWARFRANGE rangeSym.Type = sym.SDWARFRANGE
syms = append(syms, rangeSym) syms = append(syms, rangeSym)
empty = false empty = false
} }
if !empty { if !empty {
// PE does not like empty sections // PE does not like empty sections
rangesec := ctxt.Syms.Lookup(".debug_ranges", 0) rangesec := ctxt.Syms.Lookup(".debug_ranges", 0)
rangesec.Type = SDWARFRANGE rangesec.Type = sym.SDWARFRANGE
rangesec.Attr |= AttrReachable rangesec.Attr |= sym.AttrReachable
rangesec.R = rangesec.R[:0] rangesec.R = rangesec.R[:0]
syms = append(syms, rangesec) syms = append(syms, rangesec)
@ -1304,11 +1305,11 @@ const (
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
) )
func writeinfo(ctxt *Link, syms []*Symbol, funcs, consts []*Symbol, abbrevsym *Symbol) []*Symbol { func writeinfo(ctxt *Link, syms []*sym.Symbol, funcs, consts []*sym.Symbol, abbrevsym *sym.Symbol) []*sym.Symbol {
infosec := ctxt.Syms.Lookup(".debug_info", 0) infosec := ctxt.Syms.Lookup(".debug_info", 0)
infosec.R = infosec.R[:0] infosec.R = infosec.R[:0]
infosec.Type = SDWARFINFO infosec.Type = sym.SDWARFINFO
infosec.Attr |= AttrReachable infosec.Attr |= sym.AttrReachable
syms = append(syms, infosec) syms = append(syms, infosec)
arangessec := ctxt.Syms.Lookup(".dwarfaranges", 0) arangessec := ctxt.Syms.Lookup(".dwarfaranges", 0)
@ -1333,7 +1334,7 @@ func writeinfo(ctxt *Link, syms []*Symbol, funcs, consts []*Symbol, abbrevsym *S
dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev)) dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev))
dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr) dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr)
cu := []*Symbol{s} cu := []*sym.Symbol{s}
if funcs != nil { if funcs != nil {
cu = append(cu, funcs...) cu = append(cu, funcs...)
funcs = nil funcs = nil
@ -1373,9 +1374,9 @@ func ispubtype(die *dwarf.DWDie) bool {
return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
} }
func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*Symbol) []*Symbol { func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*sym.Symbol) []*sym.Symbol {
s := ctxt.Syms.Lookup(sname, 0) s := ctxt.Syms.Lookup(sname, 0)
s.Type = SDWARFSECT s.Type = sym.SDWARFSECT
syms = append(syms, s) syms = append(syms, s)
for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link { for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
@ -1413,9 +1414,9 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*S
* emit .debug_aranges. _info must have been written before, * emit .debug_aranges. _info must have been written before,
* because we need die->offs of dwarf.DW_globals. * because we need die->offs of dwarf.DW_globals.
*/ */
func writearanges(ctxt *Link, syms []*Symbol) []*Symbol { func writearanges(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
s := ctxt.Syms.Lookup(".debug_aranges", 0) s := ctxt.Syms.Lookup(".debug_aranges", 0)
s.Type = SDWARFSECT s.Type = sym.SDWARFSECT
// The first tuple is aligned to a multiple of the size of a single tuple // The first tuple is aligned to a multiple of the size of a single tuple
// (twice the size of an address) // (twice the size of an address)
headersize := int(Rnd(4+2+4+1+1, int64(ctxt.Arch.PtrSize*2))) // don't count unit_length field itself headersize := int(Rnd(4+2+4+1+1, int64(ctxt.Arch.PtrSize*2))) // don't count unit_length field itself
@ -1444,10 +1445,10 @@ func writearanges(ctxt *Link, syms []*Symbol) []*Symbol {
s.AddUint8(0) s.AddUint8(0)
} }
s.AddAddrPlus(ctxt.Arch, b.Data.(*Symbol), b.Value-(b.Data.(*Symbol)).Value) s.AddAddrPlus(ctxt.Arch, b.Data.(*sym.Symbol), b.Value-(b.Data.(*sym.Symbol)).Value)
s.addUintXX(ctxt.Arch, uint64(e.Value-b.Value), ctxt.Arch.PtrSize) s.AddUintXX(ctxt.Arch, uint64(e.Value-b.Value), ctxt.Arch.PtrSize)
s.addUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) s.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize)
s.addUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) s.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize)
} }
if s.Size > 0 { if s.Size > 0 {
syms = append(syms, s) syms = append(syms, s)
@ -1455,7 +1456,7 @@ func writearanges(ctxt *Link, syms []*Symbol) []*Symbol {
return syms return syms
} }
func writegdbscript(ctxt *Link, syms []*Symbol) []*Symbol { func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
if Linkmode == LinkExternal && Headtype == objabi.Hwindows && Buildmode == BuildmodeCArchive { if Linkmode == LinkExternal && Headtype == objabi.Hwindows && Buildmode == BuildmodeCArchive {
// gcc on Windows places .debug_gdb_scripts in the wrong location, which // gcc on Windows places .debug_gdb_scripts in the wrong location, which
// causes the program not to run. See https://golang.org/issue/20183 // causes the program not to run. See https://golang.org/issue/20183
@ -1468,7 +1469,7 @@ func writegdbscript(ctxt *Link, syms []*Symbol) []*Symbol {
if gdbscript != "" { if gdbscript != "" {
s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0) s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0)
s.Type = SDWARFSECT s.Type = sym.SDWARFSECT
syms = append(syms, s) syms = append(syms, s)
s.AddUint8(1) // magic 1 byte? s.AddUint8(1) // magic 1 byte?
Addstring(s, gdbscript) Addstring(s, gdbscript)
@ -1556,7 +1557,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
genasmsym(ctxt, defdwsymb) genasmsym(ctxt, defdwsymb)
var consts []*Symbol var consts []*sym.Symbol
for _, lib := range ctxt.Library { for _, lib := range ctxt.Library {
if s := ctxt.Syms.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil { if s := ctxt.Syms.Lookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil {
importInfoSymbol(ctxt, s) importInfoSymbol(ctxt, s)
@ -1565,7 +1566,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
} }
abbrev := writeabbrev(ctxt) abbrev := writeabbrev(ctxt)
syms := []*Symbol{abbrev} syms := []*sym.Symbol{abbrev}
syms, funcs := writelines(ctxt, syms) syms, funcs := writelines(ctxt, syms)
syms = writeframes(ctxt, syms) syms = writeframes(ctxt, syms)
@ -1581,7 +1582,7 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
movetomodule(&dwtypes) movetomodule(&dwtypes)
movetomodule(&dwglobals) movetomodule(&dwglobals)
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT // Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
// (but we need to generate dies before writepub) // (but we need to generate dies before writepub)
infosyms := writeinfo(ctxt, nil, funcs, consts, abbrev) infosyms := writeinfo(ctxt, nil, funcs, consts, abbrev)
@ -1595,12 +1596,12 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
dwarfp = syms dwarfp = syms
} }
func collectlocs(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol { func collectlocs(ctxt *Link, syms []*sym.Symbol, funcs []*sym.Symbol) []*sym.Symbol {
empty := true empty := true
for _, fn := range funcs { for _, fn := range funcs {
for _, reloc := range fn.R { for _, reloc := range fn.R {
if reloc.Type == objabi.R_DWARFREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) { if reloc.Type == objabi.R_DWARFREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
reloc.Sym.Attr |= AttrReachable | AttrNotInSymbolTable reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
syms = append(syms, reloc.Sym) syms = append(syms, reloc.Sym)
empty = false empty = false
// One location list entry per function, but many relocations to it. Don't duplicate. // One location list entry per function, but many relocations to it. Don't duplicate.
@ -1612,8 +1613,8 @@ func collectlocs(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol {
if !empty { if !empty {
locsym := ctxt.Syms.Lookup(".debug_loc", 0) locsym := ctxt.Syms.Lookup(".debug_loc", 0)
locsym.R = locsym.R[:0] locsym.R = locsym.R[:0]
locsym.Type = SDWARFLOC locsym.Type = sym.SDWARFLOC
locsym.Attr |= AttrReachable locsym.Attr |= sym.AttrReachable
syms = append(syms, locsym) syms = append(syms, locsym)
} }
return syms return syms
@ -1622,7 +1623,7 @@ func collectlocs(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol {
/* /*
* Elf. * Elf.
*/ */
func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) { func dwarfaddshstrings(ctxt *Link, shstrtab *sym.Symbol) {
if *FlagW { // disable dwarf if *FlagW { // disable dwarf
return return
} }
@ -1658,20 +1659,20 @@ func dwarfaddelfsectionsyms(ctxt *Link) {
if Linkmode != LinkExternal { if Linkmode != LinkExternal {
return return
} }
sym := ctxt.Syms.Lookup(".debug_info", 0) s := ctxt.Syms.Lookup(".debug_info", 0)
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
sym = ctxt.Syms.Lookup(".debug_abbrev", 0) s = ctxt.Syms.Lookup(".debug_abbrev", 0)
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
sym = ctxt.Syms.Lookup(".debug_line", 0) s = ctxt.Syms.Lookup(".debug_line", 0)
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
sym = ctxt.Syms.Lookup(".debug_frame", 0) s = ctxt.Syms.Lookup(".debug_frame", 0)
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
sym = ctxt.Syms.Lookup(".debug_loc", 0) s = ctxt.Syms.Lookup(".debug_loc", 0)
if sym.Sect != nil { if s.Sect != nil {
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
} }
sym = ctxt.Syms.Lookup(".debug_ranges", 0) s = ctxt.Syms.Lookup(".debug_ranges", 0)
if sym.Sect != nil { if s.Sect != nil {
putelfsectionsym(ctxt.Out, sym, sym.Sect.Elfsect.shnum) putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum)
} }
} }

View file

@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"crypto/sha1" "crypto/sha1"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
@ -809,7 +810,7 @@ type ElfShdr struct {
addralign uint64 addralign uint64
entsize uint64 entsize uint64
shnum int shnum int
secsym *Symbol secsym *sym.Symbol
} }
/* /*
@ -1060,7 +1061,7 @@ func elfwriteshdrs(out *OutBuf) uint32 {
return uint32(ehdr.shnum) * ELF32SHDRSIZE return uint32(ehdr.shnum) * ELF32SHDRSIZE
} }
func elfsetstring(s *Symbol, str string, off int) { func elfsetstring(s *sym.Symbol, str string, off int) {
if nelfstr >= len(elfstr) { if nelfstr >= len(elfstr) {
Errorf(s, "too many elf strings") Errorf(s, "too many elf strings")
errorexit() errorexit()
@ -1175,7 +1176,7 @@ func elfhash(name string) uint32 {
return h return h
} }
func Elfwritedynent(ctxt *Link, s *Symbol, tag int, val uint64) { func Elfwritedynent(ctxt *Link, s *sym.Symbol, tag int, val uint64) {
if elf64 { if elf64 {
s.AddUint64(ctxt.Arch, uint64(tag)) s.AddUint64(ctxt.Arch, uint64(tag))
s.AddUint64(ctxt.Arch, val) s.AddUint64(ctxt.Arch, val)
@ -1185,11 +1186,11 @@ func Elfwritedynent(ctxt *Link, s *Symbol, tag int, val uint64) {
} }
} }
func elfwritedynentsym(ctxt *Link, s *Symbol, tag int, t *Symbol) { func elfwritedynentsym(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
Elfwritedynentsymplus(ctxt, s, tag, t, 0) Elfwritedynentsymplus(ctxt, s, tag, t, 0)
} }
func Elfwritedynentsymplus(ctxt *Link, s *Symbol, tag int, t *Symbol, add int64) { func Elfwritedynentsymplus(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol, add int64) {
if elf64 { if elf64 {
s.AddUint64(ctxt.Arch, uint64(tag)) s.AddUint64(ctxt.Arch, uint64(tag))
} else { } else {
@ -1198,7 +1199,7 @@ func Elfwritedynentsymplus(ctxt *Link, s *Symbol, tag int, t *Symbol, add int64)
s.AddAddrPlus(ctxt.Arch, t, add) s.AddAddrPlus(ctxt.Arch, t, add)
} }
func elfwritedynentsymsize(ctxt *Link, s *Symbol, tag int, t *Symbol) { func elfwritedynentsymsize(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
if elf64 { if elf64 {
s.AddUint64(ctxt.Arch, uint64(tag)) s.AddUint64(ctxt.Arch, uint64(tag))
} else { } else {
@ -1446,8 +1447,8 @@ func elfdynhash(ctxt *Link) {
nsym := Nelfsym nsym := Nelfsym
s := ctxt.Syms.Lookup(".hash", 0) s := ctxt.Syms.Lookup(".hash", 0)
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
i := nsym i := nsym
nbucket := 1 nbucket := 1
@ -1575,7 +1576,7 @@ func elfdynhash(ctxt *Link) {
Elfwritedynent(ctxt, s, DT_NULL, 0) Elfwritedynent(ctxt, s, DT_NULL, 0)
} }
func elfphload(seg *Segment) *ElfPhdr { func elfphload(seg *sym.Segment) *ElfPhdr {
ph := newElfPhdr() ph := newElfPhdr()
ph.type_ = PT_LOAD ph.type_ = PT_LOAD
if seg.Rwx&4 != 0 { if seg.Rwx&4 != 0 {
@ -1597,7 +1598,7 @@ func elfphload(seg *Segment) *ElfPhdr {
return ph return ph
} }
func elfphrelro(seg *Segment) { func elfphrelro(seg *sym.Segment) {
ph := newElfPhdr() ph := newElfPhdr()
ph.type_ = PT_GNU_RELRO ph.type_ = PT_GNU_RELRO
ph.vaddr = seg.Vaddr ph.vaddr = seg.Vaddr
@ -1640,20 +1641,20 @@ func elfshnamedup(name string) *ElfShdr {
return nil return nil
} }
func elfshalloc(sect *Section) *ElfShdr { func elfshalloc(sect *sym.Section) *ElfShdr {
sh := elfshname(sect.Name) sh := elfshname(sect.Name)
sect.Elfsect = sh sect.Elfsect = sh
return sh return sh
} }
func elfshbits(sect *Section) *ElfShdr { func elfshbits(sect *sym.Section) *ElfShdr {
var sh *ElfShdr var sh *ElfShdr
if sect.Name == ".text" { if sect.Name == ".text" {
if sect.Elfsect == nil { if sect.Elfsect == nil {
sect.Elfsect = elfshnamedup(sect.Name) sect.Elfsect = elfshnamedup(sect.Name)
} }
sh = sect.Elfsect sh = sect.Elfsect.(*ElfShdr)
} else { } else {
sh = elfshalloc(sect) sh = elfshalloc(sect)
} }
@ -1712,7 +1713,7 @@ func elfshbits(sect *Section) *ElfShdr {
return sh return sh
} }
func elfshreloc(arch *sys.Arch, sect *Section) *ElfShdr { func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
// If main section is SHT_NOBITS, nothing to relocate. // If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab or notes. // Also nothing to relocate in .shstrtab or notes.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@ -1721,7 +1722,7 @@ func elfshreloc(arch *sys.Arch, sect *Section) *ElfShdr {
if sect.Name == ".shstrtab" || sect.Name == ".tbss" { if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
return nil return nil
} }
if sect.Elfsect.type_ == SHT_NOTE { if sect.Elfsect.(*ElfShdr).type_ == SHT_NOTE {
return nil return nil
} }
@ -1737,7 +1738,7 @@ func elfshreloc(arch *sys.Arch, sect *Section) *ElfShdr {
// its own .rela.text. // its own .rela.text.
if sect.Name == ".text" { if sect.Name == ".text" {
if sh.info != 0 && sh.info != uint32(sect.Elfsect.shnum) { if sh.info != 0 && sh.info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
sh = elfshnamedup(elfRelType + sect.Name) sh = elfshnamedup(elfRelType + sect.Name)
} }
} }
@ -1748,14 +1749,14 @@ func elfshreloc(arch *sys.Arch, sect *Section) *ElfShdr {
sh.entsize += uint64(arch.RegSize) sh.entsize += uint64(arch.RegSize)
} }
sh.link = uint32(elfshname(".symtab").shnum) sh.link = uint32(elfshname(".symtab").shnum)
sh.info = uint32(sect.Elfsect.shnum) sh.info = uint32(sect.Elfsect.(*ElfShdr).shnum)
sh.off = sect.Reloff sh.off = sect.Reloff
sh.size = sect.Rellen sh.size = sect.Rellen
sh.addralign = uint64(arch.RegSize) sh.addralign = uint64(arch.RegSize)
return sh return sh
} }
func elfrelocsect(ctxt *Link, sect *Section, syms []*Symbol) { func elfrelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
// If main section is SHT_NOBITS, nothing to relocate. // If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab. // Also nothing to relocate in .shstrtab.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@ -1777,30 +1778,30 @@ func elfrelocsect(ctxt *Link, sect *Section, syms []*Symbol) {
} }
eaddr := int32(sect.Vaddr + sect.Length) eaddr := int32(sect.Vaddr + sect.Length)
for _, sym := range syms { for _, s := range syms {
if !sym.Attr.Reachable() { if !s.Attr.Reachable() {
continue continue
} }
if sym.Value >= int64(eaddr) { if s.Value >= int64(eaddr) {
break break
} }
for ri := 0; ri < len(sym.R); ri++ { for ri := 0; ri < len(s.R); ri++ {
r := &sym.R[ri] r := &s.R[ri]
if r.Done { if r.Done {
continue continue
} }
if r.Xsym == nil { if r.Xsym == nil {
Errorf(sym, "missing xsym in relocation %#v %#v", r.Sym.Name, sym) Errorf(s, "missing xsym in relocation %#v %#v", r.Sym.Name, s)
continue continue
} }
if r.Xsym.ElfsymForReloc() == 0 { if r.Xsym.ElfsymForReloc() == 0 {
Errorf(sym, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type, RelocName(ctxt.Arch, r.Type), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Sym.Type) Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Sym.Type)
} }
if !r.Xsym.Attr.Reachable() { if !r.Xsym.Attr.Reachable() {
Errorf(sym, "unreachable reloc %d (%s) target %v", r.Type, RelocName(ctxt.Arch, r.Type), r.Xsym.Name) Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
} }
if !Thearch.Elfreloc1(ctxt, r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) { if !Thearch.Elfreloc1(ctxt, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
Errorf(sym, "unsupported obj reloc %d (%s)/%d to %s", r.Type, RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name) Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
} }
} }
} }
@ -1837,8 +1838,8 @@ func Elfemitreloc(ctxt *Link) {
func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) { func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
s := ctxt.Syms.Lookup(sectionName, 0) s := ctxt.Syms.Lookup(sectionName, 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
// namesz // namesz
s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME))) s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
// descsz // descsz
@ -1867,8 +1868,8 @@ func (ctxt *Link) doelf() {
/* predefine strings we need for section headers */ /* predefine strings we need for section headers */
shstrtab := ctxt.Syms.Lookup(".shstrtab", 0) shstrtab := ctxt.Syms.Lookup(".shstrtab", 0)
shstrtab.Type = SELFROSECT shstrtab.Type = sym.SELFROSECT
shstrtab.Attr |= AttrReachable shstrtab.Attr |= sym.AttrReachable
Addstring(shstrtab, "") Addstring(shstrtab, "")
Addstring(shstrtab, ".text") Addstring(shstrtab, ".text")
@ -1975,8 +1976,8 @@ func (ctxt *Link) doelf() {
/* dynamic symbol table - first entry all zeros */ /* dynamic symbol table - first entry all zeros */
s := ctxt.Syms.Lookup(".dynsym", 0) s := ctxt.Syms.Lookup(".dynsym", 0)
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
if elf64 { if elf64 {
s.Size += ELF64SYMSIZE s.Size += ELF64SYMSIZE
} else { } else {
@ -1986,8 +1987,8 @@ func (ctxt *Link) doelf() {
/* dynamic string table */ /* dynamic string table */
s = ctxt.Syms.Lookup(".dynstr", 0) s = ctxt.Syms.Lookup(".dynstr", 0)
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
if s.Size == 0 { if s.Size == 0 {
Addstring(s, "") Addstring(s, "")
} }
@ -1995,62 +1996,62 @@ func (ctxt *Link) doelf() {
/* relocation table */ /* relocation table */
s = ctxt.Syms.Lookup(elfRelType, 0) s = ctxt.Syms.Lookup(elfRelType, 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
/* global offset table */ /* global offset table */
s = ctxt.Syms.Lookup(".got", 0) s = ctxt.Syms.Lookup(".got", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFGOT // writable s.Type = sym.SELFGOT // writable
/* ppc64 glink resolver */ /* ppc64 glink resolver */
if ctxt.Arch.Family == sys.PPC64 { if ctxt.Arch.Family == sys.PPC64 {
s := ctxt.Syms.Lookup(".glink", 0) s := ctxt.Syms.Lookup(".glink", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFRXSECT s.Type = sym.SELFRXSECT
} }
/* hash */ /* hash */
s = ctxt.Syms.Lookup(".hash", 0) s = ctxt.Syms.Lookup(".hash", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s = ctxt.Syms.Lookup(".got.plt", 0) s = ctxt.Syms.Lookup(".got.plt", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFSECT // writable s.Type = sym.SELFSECT // writable
s = ctxt.Syms.Lookup(".plt", 0) s = ctxt.Syms.Lookup(".plt", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
if ctxt.Arch.Family == sys.PPC64 { if ctxt.Arch.Family == sys.PPC64 {
// In the ppc64 ABI, .plt is a data section // In the ppc64 ABI, .plt is a data section
// written by the dynamic linker. // written by the dynamic linker.
s.Type = SELFSECT s.Type = sym.SELFSECT
} else { } else {
s.Type = SELFRXSECT s.Type = sym.SELFRXSECT
} }
Thearch.Elfsetupplt(ctxt) Thearch.Elfsetupplt(ctxt)
s = ctxt.Syms.Lookup(elfRelType+".plt", 0) s = ctxt.Syms.Lookup(elfRelType+".plt", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s = ctxt.Syms.Lookup(".gnu.version", 0) s = ctxt.Syms.Lookup(".gnu.version", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
s = ctxt.Syms.Lookup(".gnu.version_r", 0) s = ctxt.Syms.Lookup(".gnu.version_r", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFROSECT s.Type = sym.SELFROSECT
/* define dynamic elf table */ /* define dynamic elf table */
s = ctxt.Syms.Lookup(".dynamic", 0) s = ctxt.Syms.Lookup(".dynamic", 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SELFSECT // writable s.Type = sym.SELFSECT // writable
/* /*
* .dynamic table * .dynamic table
@ -2102,10 +2103,10 @@ func (ctxt *Link) doelf() {
// The go.link.abihashbytes symbol will be pointed at the appropriate // The go.link.abihashbytes symbol will be pointed at the appropriate
// part of the .note.go.abihash section in data.go:func address(). // part of the .note.go.abihash section in data.go:func address().
s := ctxt.Syms.Lookup("go.link.abihashbytes", 0) s := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
s.Attr |= AttrLocal s.Attr |= sym.AttrLocal
s.Type = SRODATA s.Type = sym.SRODATA
s.Attr |= AttrSpecial s.Attr |= sym.AttrSpecial
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Size = int64(sha1.Size) s.Size = int64(sha1.Size)
sort.Sort(byPkg(ctxt.Library)) sort.Sort(byPkg(ctxt.Library))
@ -2128,7 +2129,7 @@ func (ctxt *Link) doelf() {
} }
// Do not write DT_NULL. elfdynhash will finish it. // Do not write DT_NULL. elfdynhash will finish it.
func shsym(sh *ElfShdr, s *Symbol) { func shsym(sh *ElfShdr, s *sym.Symbol) {
addr := Symaddr(s) addr := Symaddr(s)
if sh.flags&SHF_ALLOC != 0 { if sh.flags&SHF_ALLOC != 0 {
sh.addr = uint64(addr) sh.addr = uint64(addr)
@ -2579,7 +2580,7 @@ elfobj:
elfshreloc(ctxt.Arch, sect) elfshreloc(ctxt.Arch, sect)
} }
for _, s := range dwarfp { for _, s := range dwarfp {
if len(s.R) > 0 || s.Type == SDWARFINFO || s.Type == SDWARFLOC { if len(s.R) > 0 || s.Type == sym.SDWARFINFO || s.Type == sym.SDWARFLOC {
elfshreloc(ctxt.Arch, s.Sect) elfshreloc(ctxt.Arch, s.Sect)
} }
} }
@ -2682,7 +2683,7 @@ elfobj:
} }
} }
func elfadddynsym(ctxt *Link, s *Symbol) { func elfadddynsym(ctxt *Link, s *sym.Symbol) {
if elf64 { if elf64 {
s.Dynid = int32(Nelfsym) s.Dynid = int32(Nelfsym)
Nelfsym++ Nelfsym++
@ -2695,7 +2696,7 @@ func elfadddynsym(ctxt *Link, s *Symbol) {
/* type */ /* type */
t := STB_GLOBAL << 4 t := STB_GLOBAL << 4
if s.Attr.CgoExport() && s.Type&SMASK == STEXT { if s.Attr.CgoExport() && s.Type&sym.SMASK == sym.STEXT {
t |= STT_FUNC t |= STT_FUNC
} else { } else {
t |= STT_OBJECT t |= STT_OBJECT
@ -2706,14 +2707,14 @@ func elfadddynsym(ctxt *Link, s *Symbol) {
d.AddUint8(0) d.AddUint8(0)
/* section where symbol is defined */ /* section where symbol is defined */
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
d.AddUint16(ctxt.Arch, SHN_UNDEF) d.AddUint16(ctxt.Arch, SHN_UNDEF)
} else { } else {
d.AddUint16(ctxt.Arch, 1) d.AddUint16(ctxt.Arch, 1)
} }
/* value */ /* value */
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
d.AddUint64(ctxt.Arch, 0) d.AddUint64(ctxt.Arch, 0)
} else { } else {
d.AddAddr(ctxt.Arch, s) d.AddAddr(ctxt.Arch, s)
@ -2737,7 +2738,7 @@ func elfadddynsym(ctxt *Link, s *Symbol) {
d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name))) d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name)))
/* value */ /* value */
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
d.AddUint32(ctxt.Arch, 0) d.AddUint32(ctxt.Arch, 0)
} else { } else {
d.AddAddr(ctxt.Arch, s) d.AddAddr(ctxt.Arch, s)
@ -2750,9 +2751,9 @@ func elfadddynsym(ctxt *Link, s *Symbol) {
t := STB_GLOBAL << 4 t := STB_GLOBAL << 4
// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386. // TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
if ctxt.Arch.Family == sys.I386 && s.Attr.CgoExport() && s.Type&SMASK == STEXT { if ctxt.Arch.Family == sys.I386 && s.Attr.CgoExport() && s.Type&sym.SMASK == sym.STEXT {
t |= STT_FUNC t |= STT_FUNC
} else if ctxt.Arch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type&SMASK == STEXT { } else if ctxt.Arch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type&sym.SMASK == sym.STEXT {
t |= STT_FUNC t |= STT_FUNC
} else { } else {
t |= STT_OBJECT t |= STT_OBJECT
@ -2761,7 +2762,7 @@ func elfadddynsym(ctxt *Link, s *Symbol) {
d.AddUint8(0) d.AddUint8(0)
/* shndx */ /* shndx */
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
d.AddUint16(ctxt.Arch, SHN_UNDEF) d.AddUint16(ctxt.Arch, SHN_UNDEF)
} else { } else {
d.AddUint16(ctxt.Arch, 1) d.AddUint16(ctxt.Arch, 1)

View file

@ -10,6 +10,7 @@ import (
"bytes" "bytes"
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/link/internal/sym"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -128,7 +129,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
var next string var next string
var q string var q string
var lib string var lib string
var s *Symbol var s *sym.Symbol
p0 := "" p0 := ""
for ; p != ""; p = next { for ; p != ""; p = next {
@ -184,12 +185,12 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
remote, q = remote[:i], remote[i+1:] remote, q = remote[:i], remote[i+1:]
} }
s = ctxt.Syms.Lookup(local, 0) s = ctxt.Syms.Lookup(local, 0)
if s.Type == 0 || s.Type == SXREF || s.Type == SHOSTOBJ { if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ {
s.Dynimplib = lib s.Dynimplib = lib
s.Extname = remote s.Extname = remote
s.Dynimpvers = q s.Dynimpvers = q
if s.Type != SHOSTOBJ { if s.Type != sym.SHOSTOBJ {
s.Type = SDYNIMPORT s.Type = sym.SDYNIMPORT
} }
havedynamic = 1 havedynamic = 1
} }
@ -203,7 +204,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
} }
local := f[1] local := f[1]
s = ctxt.Syms.Lookup(local, 0) s = ctxt.Syms.Lookup(local, 0)
s.Type = SHOSTOBJ s.Type = sym.SHOSTOBJ
s.Size = 0 s.Size = 0
continue continue
} }
@ -248,9 +249,9 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
} }
if f[0] == "cgo_export_static" { if f[0] == "cgo_export_static" {
s.Attr |= AttrCgoExportStatic s.Attr |= sym.AttrCgoExportStatic
} else { } else {
s.Attr |= AttrCgoExportDynamic s.Attr |= sym.AttrCgoExportDynamic
} }
continue continue
} }
@ -308,7 +309,7 @@ func adddynlib(ctxt *Link, lib string) {
} }
} }
func Adddynsym(ctxt *Link, s *Symbol) { func Adddynsym(ctxt *Link, s *sym.Symbol) {
if s.Dynid >= 0 || Linkmode == LinkExternal { if s.Dynid >= 0 || Linkmode == LinkExternal {
return return
} }
@ -329,8 +330,8 @@ func fieldtrack(ctxt *Link) {
var buf bytes.Buffer var buf bytes.Buffer
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if strings.HasPrefix(s.Name, "go.track.") { if strings.HasPrefix(s.Name, "go.track.") {
s.Attr |= AttrSpecial // do not lay out in data segment s.Attr |= sym.AttrSpecial // do not lay out in data segment
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
if s.Attr.Reachable() { if s.Attr.Reachable() {
buf.WriteString(s.Name[9:]) buf.WriteString(s.Name[9:])
for p := s.Reachparent; p != nil; p = p.Reachparent { for p := s.Reachparent; p != nil; p = p.Reachparent {
@ -340,7 +341,7 @@ func fieldtrack(ctxt *Link) {
buf.WriteString("\n") buf.WriteString("\n")
} }
s.Type = SCONST s.Type = sym.SCONST
s.Value = 0 s.Value = 0
} }
} }
@ -353,7 +354,7 @@ func fieldtrack(ctxt *Link) {
return return
} }
addstrdata(ctxt, *flagFieldTrack, buf.String()) addstrdata(ctxt, *flagFieldTrack, buf.String())
s.Type = SDATA s.Type = sym.SDATA
} }
func (ctxt *Link) addexport() { func (ctxt *Link) addexport() {

View file

@ -5,6 +5,7 @@ import (
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
@ -266,7 +267,7 @@ type ElfSect struct {
align uint64 align uint64
entsize uint64 entsize uint64
base []byte base []byte
sym *Symbol sym *sym.Symbol
} }
type ElfObj struct { type ElfObj struct {
@ -305,7 +306,7 @@ type ElfSym struct {
type_ uint8 type_ uint8
other uint8 other uint8
shndx uint16 shndx uint16
sym *Symbol sym *sym.Symbol
} }
var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'} var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
@ -711,21 +712,21 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
return return
case ElfSectFlagAlloc: case ElfSectFlagAlloc:
s.Type = SRODATA s.Type = sym.SRODATA
case ElfSectFlagAlloc + ElfSectFlagWrite: case ElfSectFlagAlloc + ElfSectFlagWrite:
if sect.type_ == ElfSectNobits { if sect.type_ == ElfSectNobits {
s.Type = SNOPTRBSS s.Type = sym.SNOPTRBSS
} else { } else {
s.Type = SNOPTRDATA s.Type = sym.SNOPTRDATA
} }
case ElfSectFlagAlloc + ElfSectFlagExec: case ElfSectFlagAlloc + ElfSectFlagExec:
s.Type = STEXT s.Type = sym.STEXT
} }
if sect.name == ".got" || sect.name == ".toc" { if sect.name == ".got" || sect.name == ".toc" {
s.Type = SELFGOT s.Type = sym.SELFGOT
} }
if sect.type_ == ElfSectProgbits { if sect.type_ == ElfSectProgbits {
s.P = sect.base s.P = sect.base
@ -739,57 +740,57 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
// enter sub-symbols into symbol table. // enter sub-symbols into symbol table.
// symbol 0 is the null symbol. // symbol 0 is the null symbol.
symbols := make([]*Symbol, elfobj.nsymtab) symbols := make([]*sym.Symbol, elfobj.nsymtab)
for i := 1; i < elfobj.nsymtab; i++ { for i := 1; i < elfobj.nsymtab; i++ {
var sym ElfSym var elfsym ElfSym
if err := readelfsym(ctxt, elfobj, i, &sym, 1, localSymVersion); err != nil { if err := readelfsym(ctxt, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
Errorf(nil, "%s: malformed elf file: %v", pn, err) Errorf(nil, "%s: malformed elf file: %v", pn, err)
return return
} }
symbols[i] = sym.sym symbols[i] = elfsym.sym
if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone && sym.type_ != ElfSymTypeCommon { if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
continue continue
} }
if sym.shndx == ElfSymShnCommon || sym.type_ == ElfSymTypeCommon { if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
s := sym.sym s := elfsym.sym
if uint64(s.Size) < sym.size { if uint64(s.Size) < elfsym.size {
s.Size = int64(sym.size) s.Size = int64(elfsym.size)
} }
if s.Type == 0 || s.Type == SXREF { if s.Type == 0 || s.Type == sym.SXREF {
s.Type = SNOPTRBSS s.Type = sym.SNOPTRBSS
} }
continue continue
} }
if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
continue continue
} }
// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
if sym.sym == nil { if elfsym.sym == nil {
continue continue
} }
sect = &elfobj.sect[sym.shndx] sect = &elfobj.sect[elfsym.shndx]
if sect.sym == nil { if sect.sym == nil {
if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
continue continue
} }
if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" { if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
// This reportedly happens with clang 3.7 on ARM. // This reportedly happens with clang 3.7 on ARM.
// See issue 13139. // See issue 13139.
continue continue
} }
if strings.HasPrefix(sym.name, ".LASF") { // gcc on s390x does this if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
continue continue
} }
Errorf(sym.sym, "%s: sym#%d: ignoring symbol in section %d (type %d)", pn, i, sym.shndx, sym.type_) Errorf(elfsym.sym, "%s: sym#%d: ignoring symbol in section %d (type %d)", pn, i, elfsym.shndx, elfsym.type_)
continue continue
} }
s := sym.sym s := elfsym.sym
if s.Outer != nil { if s.Outer != nil {
if s.Attr.DuplicateOK() { if s.Attr.DuplicateOK() {
continue continue
@ -799,26 +800,26 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
s.Sub = sect.sym.Sub s.Sub = sect.sym.Sub
sect.sym.Sub = s sect.sym.Sub = s
s.Type = sect.sym.Type | s.Type&^SMASK | SSUB s.Type = sect.sym.Type | s.Type&^sym.SMASK | sym.SSUB
if !s.Attr.CgoExportDynamic() { if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport s.Dynimplib = "" // satisfy dynimport
} }
s.Value = int64(sym.value) s.Value = int64(elfsym.value)
s.Size = int64(sym.size) s.Size = int64(elfsym.size)
s.Outer = sect.sym s.Outer = sect.sym
if sect.sym.Type == STEXT { if sect.sym.Type == sym.STEXT {
if s.Attr.External() && !s.Attr.DuplicateOK() { if s.Attr.External() && !s.Attr.DuplicateOK() {
Errorf(s, "%s: duplicate symbol definition", pn) Errorf(s, "%s: duplicate symbol definition", pn)
} }
s.Attr |= AttrExternal s.Attr |= sym.AttrExternal
} }
if elfobj.machine == ElfMachPower64 { if elfobj.machine == ElfMachPower64 {
flag := int(sym.other) >> 5 flag := int(elfsym.other) >> 5
if 2 <= flag && flag <= 6 { if 2 <= flag && flag <= 6 {
s.Localentry = 1 << uint(flag-2) s.Localentry = 1 << uint(flag-2)
} else if flag == 7 { } else if flag == 7 {
Errorf(s, "%s: invalid sym.other 0x%x", pn, sym.other) Errorf(s, "%s: invalid sym.other 0x%x", pn, elfsym.other)
} }
} }
} }
@ -833,17 +834,17 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
if s.Sub != nil { if s.Sub != nil {
s.Sub = listsort(s.Sub) s.Sub = listsort(s.Sub)
} }
if s.Type == STEXT { if s.Type == sym.STEXT {
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
for s = s.Sub; s != nil; s = s.Sub { for s = s.Sub; s != nil; s = s.Sub {
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
} }
} }
@ -868,7 +869,7 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
rela = 1 rela = 1
} }
n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
r := make([]Reloc, n) r := make([]sym.Reloc, n)
p := rsect.base p := rsect.base
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
var add uint64 var add uint64
@ -908,18 +909,18 @@ func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
rp.Sym = nil rp.Sym = nil
} else { } else {
var sym ElfSym var elfsym ElfSym
if err := readelfsym(ctxt, elfobj, int(info>>32), &sym, 0, 0); err != nil { if err := readelfsym(ctxt, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
Errorf(nil, "%s: malformed elf file: %v", pn, err) Errorf(nil, "%s: malformed elf file: %v", pn, err)
return return
} }
sym.sym = symbols[info>>32] elfsym.sym = symbols[info>>32]
if sym.sym == nil { if elfsym.sym == nil {
Errorf(nil, "%s: malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", pn, sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_) Errorf(nil, "%s: malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", pn, sect.sym.Name, j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
return return
} }
rp.Sym = sym.sym rp.Sym = elfsym.sym
} }
rp.Type = 256 + objabi.RelocType(info) rp.Type = 256 + objabi.RelocType(info)
@ -985,7 +986,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
return nil return nil
} }
func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, localSymVersion int) (err error) { func readelfsym(ctxt *Link, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
if i >= elfobj.nsymtab || i < 0 { if i >= elfobj.nsymtab || i < 0 {
err = fmt.Errorf("invalid elf symbol index") err = fmt.Errorf("invalid elf symbol index")
return err return err
@ -998,44 +999,44 @@ func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, loc
if elfobj.is64 != 0 { if elfobj.is64 != 0 {
b := new(ElfSymBytes64) b := new(ElfSymBytes64)
binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b) binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
sym.value = elfobj.e.Uint64(b.Value[:]) elfsym.value = elfobj.e.Uint64(b.Value[:])
sym.size = elfobj.e.Uint64(b.Size[:]) elfsym.size = elfobj.e.Uint64(b.Size[:])
sym.shndx = elfobj.e.Uint16(b.Shndx[:]) elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
sym.bind = b.Info >> 4 elfsym.bind = b.Info >> 4
sym.type_ = b.Info & 0xf elfsym.type_ = b.Info & 0xf
sym.other = b.Other elfsym.other = b.Other
} else { } else {
b := new(ElfSymBytes) b := new(ElfSymBytes)
binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b) binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
sym.value = uint64(elfobj.e.Uint32(b.Value[:])) elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
sym.size = uint64(elfobj.e.Uint32(b.Size[:])) elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
sym.shndx = elfobj.e.Uint16(b.Shndx[:]) elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
sym.bind = b.Info >> 4 elfsym.bind = b.Info >> 4
sym.type_ = b.Info & 0xf elfsym.type_ = b.Info & 0xf
sym.other = b.Other elfsym.other = b.Other
} }
var s *Symbol var s *sym.Symbol
if sym.name == "_GLOBAL_OFFSET_TABLE_" { if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
sym.name = ".got" elfsym.name = ".got"
} }
if sym.name == ".TOC." { if elfsym.name == ".TOC." {
// Magic symbol on ppc64. Will be set to this object // Magic symbol on ppc64. Will be set to this object
// file's .got+0x8000. // file's .got+0x8000.
sym.bind = ElfSymBindLocal elfsym.bind = ElfSymBindLocal
} }
switch sym.type_ { switch elfsym.type_ {
case ElfSymTypeSection: case ElfSymTypeSection:
s = elfobj.sect[sym.shndx].sym s = elfobj.sect[elfsym.shndx].sym
case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon: case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
switch sym.bind { switch elfsym.bind {
case ElfSymBindGlobal: case ElfSymBindGlobal:
if needSym != 0 { if needSym != 0 {
s = ctxt.Syms.Lookup(sym.name, 0) s = ctxt.Syms.Lookup(elfsym.name, 0)
// for global scoped hidden symbols we should insert it into // for global scoped hidden symbols we should insert it into
// symbol hash table, but mark them as hidden. // symbol hash table, but mark them as hidden.
@ -1044,25 +1045,25 @@ func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, loc
// TODO(minux): correctly handle __i686.get_pc_thunk.bx without // TODO(minux): correctly handle __i686.get_pc_thunk.bx without
// set dupok generally. See http://codereview.appspot.com/5823055/ // set dupok generally. See http://codereview.appspot.com/5823055/
// comment #5 for details. // comment #5 for details.
if s != nil && sym.other == 2 { if s != nil && elfsym.other == 2 {
s.Type |= SHIDDEN s.Type |= sym.SHIDDEN
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
} }
} }
case ElfSymBindLocal: case ElfSymBindLocal:
if ctxt.Arch.Family == sys.ARM && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { if ctxt.Arch.Family == sys.ARM && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d")) {
// binutils for arm generate these mapping // binutils for arm generate these mapping
// symbols, ignore these // symbols, ignore these
break break
} }
if sym.name == ".TOC." { if elfsym.name == ".TOC." {
// We need to be able to look this up, // We need to be able to look this up,
// so put it in the hash table. // so put it in the hash table.
if needSym != 0 { if needSym != 0 {
s = ctxt.Syms.Lookup(sym.name, localSymVersion) s = ctxt.Syms.Lookup(elfsym.name, localSymVersion)
s.Type |= SHIDDEN s.Type |= sym.SHIDDEN
} }
break break
@ -1072,34 +1073,34 @@ func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, loc
// local names and hidden global names are unique // local names and hidden global names are unique
// and should only be referenced by their index, not name, so we // and should only be referenced by their index, not name, so we
// don't bother to add them into the hash table // don't bother to add them into the hash table
s = ctxt.Syms.newsym(sym.name, localSymVersion) s = ctxt.Syms.Newsym(elfsym.name, localSymVersion)
s.Type |= SHIDDEN s.Type |= sym.SHIDDEN
} }
case ElfSymBindWeak: case ElfSymBindWeak:
if needSym != 0 { if needSym != 0 {
s = ctxt.Syms.Lookup(sym.name, 0) s = ctxt.Syms.Lookup(elfsym.name, 0)
if sym.other == 2 { if elfsym.other == 2 {
s.Type |= SHIDDEN s.Type |= sym.SHIDDEN
} }
} }
default: default:
err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind) err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
return err return err
} }
} }
if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection { if s != nil && s.Type == 0 && elfsym.type_ != ElfSymTypeSection {
s.Type = SXREF s.Type = sym.SXREF
} }
sym.sym = s elfsym.sym = s
return nil return nil
} }
type rbyoff []Reloc type rbyoff []sym.Reloc
func (x rbyoff) Len() int { func (x rbyoff) Len() int {
return len(x) return len(x)

View file

@ -4,6 +4,7 @@ import (
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
@ -92,7 +93,7 @@ type ldMachoSect struct {
flags uint32 flags uint32
res1 uint32 res1 uint32
res2 uint32 res2 uint32
sym *Symbol sym *sym.Symbol
rel []ldMachoRel rel []ldMachoRel
} }
@ -123,7 +124,7 @@ type ldMachoSym struct {
desc uint16 desc uint16
kind int8 kind int8
value uint64 value uint64
sym *Symbol sym *sym.Symbol
} }
type ldMachoDysymtab struct { type ldMachoDysymtab struct {
@ -428,15 +429,14 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
var sect *ldMachoSect var sect *ldMachoSect
var rel *ldMachoRel var rel *ldMachoRel
var rpi int var rpi int
var s *Symbol var s *sym.Symbol
var s1 *Symbol var s1 *sym.Symbol
var outer *Symbol var outer *sym.Symbol
var c *ldMachoCmd var c *ldMachoCmd
var symtab *ldMachoSymtab var symtab *ldMachoSymtab
var dsymtab *ldMachoDysymtab var dsymtab *ldMachoDysymtab
var sym *ldMachoSym var r []sym.Reloc
var r []Reloc var rp *sym.Reloc
var rp *Reloc
var name string var name string
localSymVersion := ctxt.Syms.IncVersion() localSymVersion := ctxt.Syms.IncVersion()
@ -597,16 +597,16 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
if sect.segname == "__TEXT" { if sect.segname == "__TEXT" {
if sect.name == "__text" { if sect.name == "__text" {
s.Type = STEXT s.Type = sym.STEXT
} else { } else {
s.Type = SRODATA s.Type = sym.SRODATA
} }
} else { } else {
if sect.name == "__bss" { if sect.name == "__bss" {
s.Type = SNOPTRBSS s.Type = sym.SNOPTRBSS
s.P = s.P[:0] s.P = s.P[:0]
} else { } else {
s.Type = SNOPTRDATA s.Type = sym.SNOPTRDATA
} }
} }
@ -616,35 +616,35 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
// enter sub-symbols into symbol table. // enter sub-symbols into symbol table.
// have to guess sizes from next symbol. // have to guess sizes from next symbol.
for i := 0; uint32(i) < symtab.nsym; i++ { for i := 0; uint32(i) < symtab.nsym; i++ {
sym = &symtab.sym[i] machsym := &symtab.sym[i]
if sym.type_&N_STAB != 0 { if machsym.type_&N_STAB != 0 {
continue continue
} }
// TODO: check sym->type against outer->type. // TODO: check sym->type against outer->type.
name = sym.name name = machsym.name
if name[0] == '_' && name[1] != '\x00' { if name[0] == '_' && name[1] != '\x00' {
name = name[1:] name = name[1:]
} }
v := 0 v := 0
if sym.type_&N_EXT == 0 { if machsym.type_&N_EXT == 0 {
v = localSymVersion v = localSymVersion
} }
s = ctxt.Syms.Lookup(name, v) s = ctxt.Syms.Lookup(name, v)
if sym.type_&N_EXT == 0 { if machsym.type_&N_EXT == 0 {
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
} }
sym.sym = s machsym.sym = s
if sym.sectnum == 0 { // undefined if machsym.sectnum == 0 { // undefined
continue continue
} }
if uint32(sym.sectnum) > c.seg.nsect { if uint32(machsym.sectnum) > c.seg.nsect {
err = fmt.Errorf("reference to invalid section %d", sym.sectnum) err = fmt.Errorf("reference to invalid section %d", machsym.sectnum)
goto bad goto bad
} }
sect = &c.seg.sect[sym.sectnum-1] sect = &c.seg.sect[machsym.sectnum-1]
outer = sect.sym outer = sect.sym
if outer == nil { if outer == nil {
err = fmt.Errorf("reference to invalid section %s/%s", sect.segname, sect.name) err = fmt.Errorf("reference to invalid section %s/%s", sect.segname, sect.name)
@ -658,22 +658,22 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
} }
s.Type = outer.Type | SSUB s.Type = outer.Type | sym.SSUB
s.Sub = outer.Sub s.Sub = outer.Sub
outer.Sub = s outer.Sub = s
s.Outer = outer s.Outer = outer
s.Value = int64(sym.value - sect.addr) s.Value = int64(machsym.value - sect.addr)
if !s.Attr.CgoExportDynamic() { if !s.Attr.CgoExportDynamic() {
s.Dynimplib = "" // satisfy dynimport s.Dynimplib = "" // satisfy dynimport
} }
if outer.Type == STEXT { if outer.Type == sym.STEXT {
if s.Attr.External() && !s.Attr.DuplicateOK() { if s.Attr.External() && !s.Attr.DuplicateOK() {
Errorf(s, "%s: duplicate symbol definition", pn) Errorf(s, "%s: duplicate symbol definition", pn)
} }
s.Attr |= AttrExternal s.Attr |= sym.AttrExternal
} }
sym.sym = s machsym.sym = s
} }
// Sort outer lists by address, adding to textp. // Sort outer lists by address, adding to textp.
@ -697,17 +697,17 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
} }
} }
if s.Type == STEXT { if s.Type == sym.STEXT {
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
for s1 = s.Sub; s1 != nil; s1 = s1.Sub { for s1 = s.Sub; s1 != nil; s1 = s1.Sub {
if s1.Attr.OnList() { if s1.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s1.Name) log.Fatalf("symbol %s listed multiple times", s1.Name)
} }
s1.Attr |= AttrOnList s1.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s1) ctxt.Textp = append(ctxt.Textp, s1)
} }
} }
@ -724,7 +724,7 @@ func ldmacho(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
if sect.rel == nil { if sect.rel == nil {
continue continue
} }
r = make([]Reloc, sect.nreloc) r = make([]sym.Reloc, sect.nreloc)
rpi = 0 rpi = 0
Reloc: Reloc:
for j = 0; uint32(j) < sect.nreloc; j++ { for j = 0; uint32(j) < sect.nreloc; j++ {

View file

@ -8,6 +8,7 @@ import (
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"debug/pe" "debug/pe"
"errors" "errors"
"fmt" "fmt"
@ -132,7 +133,7 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
localSymVersion := ctxt.Syms.IncVersion() localSymVersion := ctxt.Syms.IncVersion()
sectsyms := make(map[*pe.Section]*Symbol) sectsyms := make(map[*pe.Section]*sym.Symbol)
sectdata := make(map[*pe.Section][]byte) sectdata := make(map[*pe.Section][]byte)
// Some input files are archives containing multiple of // Some input files are archives containing multiple of
@ -167,22 +168,22 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
switch sect.Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE) { switch sect.Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE) {
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: //.rdata case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: //.rdata
s.Type = SRODATA s.Type = sym.SRODATA
case IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.bss case IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.bss
s.Type = SNOPTRBSS s.Type = sym.SNOPTRBSS
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.data case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.data
s.Type = SNOPTRDATA s.Type = sym.SNOPTRDATA
case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: //.text case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: //.text
s.Type = STEXT s.Type = sym.STEXT
default: default:
return fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) return fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
} }
if s.Type != SNOPTRBSS { if s.Type != sym.SNOPTRBSS {
data, err := sect.Data() data, err := sect.Data()
if err != nil { if err != nil {
return err return err
@ -214,7 +215,7 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
continue continue
} }
rs := make([]Reloc, rsect.NumberOfRelocations) rs := make([]sym.Reloc, rsect.NumberOfRelocations)
for j, r := range rsect.Relocs { for j, r := range rsect.Relocs {
rp := &rs[j] rp := &rs[j]
if int(r.SymbolTableIndex) >= len(f.COFFSymbols) { if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
@ -314,11 +315,11 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
} }
if pesym.SectionNumber == 0 { // extern if pesym.SectionNumber == 0 { // extern
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
s.Plt = -2 // flag for dynimport in PE object files. s.Plt = -2 // flag for dynimport in PE object files.
} }
if s.Type == SXREF && pesym.Value > 0 { // global data if s.Type == sym.SXREF && pesym.Value > 0 { // global data
s.Type = SNOPTRDATA s.Type = sym.SNOPTRDATA
s.Size = int64(pesym.Value) s.Size = int64(pesym.Value)
} }
@ -346,15 +347,15 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
sectsym := sectsyms[sect] sectsym := sectsyms[sect]
s.Sub = sectsym.Sub s.Sub = sectsym.Sub
sectsym.Sub = s sectsym.Sub = s
s.Type = sectsym.Type | SSUB s.Type = sectsym.Type | sym.SSUB
s.Value = int64(pesym.Value) s.Value = int64(pesym.Value)
s.Size = 4 s.Size = 4
s.Outer = sectsym s.Outer = sectsym
if sectsym.Type == STEXT { if sectsym.Type == sym.STEXT {
if s.Attr.External() && !s.Attr.DuplicateOK() { if s.Attr.External() && !s.Attr.DuplicateOK() {
Errorf(s, "%s: duplicate symbol definition", pn) Errorf(s, "%s: duplicate symbol definition", pn)
} }
s.Attr |= AttrExternal s.Attr |= sym.AttrExternal
} }
} }
@ -368,17 +369,17 @@ func ldpeError(ctxt *Link, input *bio.Reader, pkg string, length int64, pn strin
if s.Sub != nil { if s.Sub != nil {
s.Sub = listsort(s.Sub) s.Sub = listsort(s.Sub)
} }
if s.Type == STEXT { if s.Type == sym.STEXT {
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
for s = s.Sub; s != nil; s = s.Sub { for s = s.Sub; s != nil; s = s.Sub {
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
} }
} }
@ -391,14 +392,14 @@ func issect(s *pe.COFFSymbol) bool {
return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.' return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
} }
func readpesym(ctxt *Link, f *pe.File, sym *pe.COFFSymbol, sectsyms map[*pe.Section]*Symbol, localSymVersion int) (*Symbol, error) { func readpesym(ctxt *Link, f *pe.File, pesym *pe.COFFSymbol, sectsyms map[*pe.Section]*sym.Symbol, localSymVersion int) (*sym.Symbol, error) {
symname, err := sym.FullName(f.StringTable) symname, err := pesym.FullName(f.StringTable)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var name string var name string
if issect(sym) { if issect(pesym) {
name = sectsyms[f.Sections[sym.SectionNumber-1]].Name name = sectsyms[f.Sections[pesym.SectionNumber-1]].Name
} else { } else {
name = symname name = symname
if strings.HasPrefix(name, "__imp_") { if strings.HasPrefix(name, "__imp_") {
@ -414,27 +415,27 @@ func readpesym(ctxt *Link, f *pe.File, sym *pe.COFFSymbol, sectsyms map[*pe.Sect
name = name[:i] name = name[:i]
} }
var s *Symbol var s *sym.Symbol
switch sym.Type { switch pesym.Type {
default: default:
return nil, fmt.Errorf("%s: invalid symbol type %d", symname, sym.Type) return nil, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL: case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
switch sym.StorageClass { switch pesym.StorageClass {
case IMAGE_SYM_CLASS_EXTERNAL: //global case IMAGE_SYM_CLASS_EXTERNAL: //global
s = ctxt.Syms.Lookup(name, 0) s = ctxt.Syms.Lookup(name, 0)
case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL: case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
s = ctxt.Syms.Lookup(name, localSymVersion) s = ctxt.Syms.Lookup(name, localSymVersion)
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
default: default:
return nil, fmt.Errorf("%s: invalid symbol binding %d", symname, sym.StorageClass) return nil, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
} }
} }
if s != nil && s.Type == 0 && (sym.StorageClass != IMAGE_SYM_CLASS_STATIC || sym.Value != 0) { if s != nil && s.Type == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
s.Type = SXREF s.Type = sym.SXREF
} }
if strings.HasPrefix(symname, "__imp_") { if strings.HasPrefix(symname, "__imp_") {
s.Got = -2 // flag for __imp_ s.Got = -2 // flag for __imp_

View file

@ -36,6 +36,7 @@ import (
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"crypto/sha1" "crypto/sha1"
"debug/elf" "debug/elf"
"encoding/base64" "encoding/base64"
@ -97,17 +98,17 @@ type Arch struct {
Openbsddynld string Openbsddynld string
Dragonflydynld string Dragonflydynld string
Solarisdynld string Solarisdynld string
Adddynrel func(*Link, *Symbol, *Reloc) bool Adddynrel func(*Link, *sym.Symbol, *sym.Reloc) bool
Archinit func(*Link) Archinit func(*Link)
Archreloc func(*Link, *Reloc, *Symbol, *int64) bool Archreloc func(*Link, *sym.Reloc, *sym.Symbol, *int64) bool
Archrelocvariant func(*Link, *Reloc, *Symbol, int64) int64 Archrelocvariant func(*Link, *sym.Reloc, *sym.Symbol, int64) int64
Trampoline func(*Link, *Reloc, *Symbol) Trampoline func(*Link, *sym.Reloc, *sym.Symbol)
Asmb func(*Link) Asmb func(*Link)
Elfreloc1 func(*Link, *Reloc, int64) bool Elfreloc1 func(*Link, *sym.Reloc, int64) bool
Elfsetupplt func(*Link) Elfsetupplt func(*Link)
Gentext func(*Link) Gentext func(*Link)
Machoreloc1 func(*sys.Arch, *OutBuf, *Symbol, *Reloc, int64) bool Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
PEreloc1 func(*sys.Arch, *OutBuf, *Symbol, *Reloc, int64) bool PEreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
// TLSIEtoLE converts a TLS Initial Executable relocation to // TLSIEtoLE converts a TLS Initial Executable relocation to
// a TLS Local Executable relocation. // a TLS Local Executable relocation.
@ -115,7 +116,7 @@ type Arch struct {
// This is possible when a TLS IE relocation refers to a local // This is possible when a TLS IE relocation refers to a local
// symbol in an executable, which is typical when internally // symbol in an executable, which is typical when internally
// linking PIE binaries. // linking PIE binaries.
TLSIEtoLE func(s *Symbol, off, size int) TLSIEtoLE func(s *sym.Symbol, off, size int)
} }
var ( var (
@ -126,37 +127,10 @@ var (
Symsize int32 Symsize int32
) )
// Terrible but standard terminology.
// A segment describes a block of file to load into memory.
// A section further describes the pieces of that block for
// use in debuggers and such.
const ( const (
MINFUNC = 16 // minimum size for a function MINFUNC = 16 // minimum size for a function
) )
type Segment struct {
Rwx uint8 // permission as usual unix bits (5 = r-x etc)
Vaddr uint64 // virtual address
Length uint64 // length in memory
Fileoff uint64 // file offset
Filelen uint64 // length on disk
Sections []*Section
}
type Section struct {
Rwx uint8
Extnum int16
Align int32
Name string
Vaddr uint64
Length uint64
Seg *Segment
Elfsect *ElfShdr
Reloff uint64
Rellen uint64
}
// DynlinkingGo returns whether we are producing Go code that can live // DynlinkingGo returns whether we are producing Go code that can live
// in separate shared libraries linked together at runtime. // in separate shared libraries linked together at runtime.
func (ctxt *Link) DynlinkingGo() bool { func (ctxt *Link) DynlinkingGo() bool {
@ -183,7 +157,7 @@ func UseRelro() bool {
} }
var ( var (
dynexp []*Symbol dynexp []*sym.Symbol
dynlib []string dynlib []string
ldflag []string ldflag []string
havedynamic int havedynamic int
@ -201,11 +175,11 @@ var (
) )
var ( var (
Segtext Segment Segtext sym.Segment
Segrodata Segment Segrodata sym.Segment
Segrelrodata Segment Segrelrodata sym.Segment
Segdata Segment Segdata sym.Segment
Segdwarf Segment Segdwarf sym.Segment
) )
/* whence for ldpkg */ /* whence for ldpkg */
@ -359,11 +333,11 @@ func (ctxt *Link) loadlib() {
switch Buildmode { switch Buildmode {
case BuildmodeCShared, BuildmodePlugin: case BuildmodeCShared, BuildmodePlugin:
s := ctxt.Syms.Lookup("runtime.islibrary", 0) s := ctxt.Syms.Lookup("runtime.islibrary", 0)
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1) s.AddUint8(1)
case BuildmodeCArchive: case BuildmodeCArchive:
s := ctxt.Syms.Lookup("runtime.isarchive", 0) s := ctxt.Syms.Lookup("runtime.isarchive", 0)
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1) s.AddUint8(1)
} }
@ -414,7 +388,7 @@ func (ctxt *Link) loadlib() {
if Linkmode == LinkExternal && ctxt.Arch.Family == sys.PPC64 { if Linkmode == LinkExternal && ctxt.Arch.Family == sys.PPC64 {
toc := ctxt.Syms.Lookup(".TOC.", 0) toc := ctxt.Syms.Lookup(".TOC.", 0)
toc.Type = SDYNIMPORT toc.Type = sym.SDYNIMPORT
} }
if Linkmode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil { if Linkmode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil {
@ -438,13 +412,13 @@ func (ctxt *Link) loadlib() {
// Drop all the cgo_import_static declarations. // Drop all the cgo_import_static declarations.
// Turns out we won't be needing them. // Turns out we won't be needing them.
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if s.Type == SHOSTOBJ { if s.Type == sym.SHOSTOBJ {
// If a symbol was marked both // If a symbol was marked both
// cgo_import_static and cgo_import_dynamic, // cgo_import_static and cgo_import_dynamic,
// then we want to make it cgo_import_dynamic // then we want to make it cgo_import_dynamic
// now. // now.
if s.Extname != "" && s.Dynimplib != "" && !s.Attr.CgoExport() { if s.Extname != "" && s.Dynimplib != "" && !s.Attr.CgoExport() {
s.Type = SDYNIMPORT s.Type = sym.SDYNIMPORT
} else { } else {
s.Type = 0 s.Type = 0
} }
@ -457,22 +431,22 @@ func (ctxt *Link) loadlib() {
// runtime.tlsg is used for external linking on platforms that do not define // runtime.tlsg is used for external linking on platforms that do not define
// a variable to hold g in assembly (currently only intel). // a variable to hold g in assembly (currently only intel).
if tlsg.Type == 0 { if tlsg.Type == 0 {
tlsg.Type = STLSBSS tlsg.Type = sym.STLSBSS
tlsg.Size = int64(ctxt.Arch.PtrSize) tlsg.Size = int64(ctxt.Arch.PtrSize)
} else if tlsg.Type != SDYNIMPORT { } else if tlsg.Type != sym.SDYNIMPORT {
Errorf(nil, "runtime declared tlsg variable %v", tlsg.Type) Errorf(nil, "runtime declared tlsg variable %v", tlsg.Type)
} }
tlsg.Attr |= AttrReachable tlsg.Attr |= sym.AttrReachable
ctxt.Tlsg = tlsg ctxt.Tlsg = tlsg
var moduledata *Symbol var moduledata *sym.Symbol
if Buildmode == BuildmodePlugin { if Buildmode == BuildmodePlugin {
moduledata = ctxt.Syms.Lookup("local.pluginmoduledata", 0) moduledata = ctxt.Syms.Lookup("local.pluginmoduledata", 0)
moduledata.Attr |= AttrLocal moduledata.Attr |= sym.AttrLocal
} else { } else {
moduledata = ctxt.Syms.Lookup("runtime.firstmoduledata", 0) moduledata = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
} }
if moduledata.Type != 0 && moduledata.Type != SDYNIMPORT { if moduledata.Type != 0 && moduledata.Type != sym.SDYNIMPORT {
// If the module (toolchain-speak for "executable or shared // If the module (toolchain-speak for "executable or shared
// library") we are linking contains the runtime package, it // library") we are linking contains the runtime package, it
// will define the runtime.firstmoduledata symbol and we // will define the runtime.firstmoduledata symbol and we
@ -484,14 +458,14 @@ func (ctxt *Link) loadlib() {
// recording the value of GOARM. // recording the value of GOARM.
if ctxt.Arch.Family == sys.ARM { if ctxt.Arch.Family == sys.ARM {
s := ctxt.Syms.Lookup("runtime.goarm", 0) s := ctxt.Syms.Lookup("runtime.goarm", 0)
s.Type = SRODATA s.Type = sym.SRODATA
s.Size = 0 s.Size = 0
s.AddUint8(uint8(objabi.GOARM)) s.AddUint8(uint8(objabi.GOARM))
} }
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) { if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
s := ctxt.Syms.Lookup("runtime.framepointer_enabled", 0) s := ctxt.Syms.Lookup("runtime.framepointer_enabled", 0)
s.Type = SRODATA s.Type = sym.SRODATA
s.Size = 0 s.Size = 0
s.AddUint8(1) s.AddUint8(1)
} }
@ -499,19 +473,19 @@ func (ctxt *Link) loadlib() {
// If OTOH the module does not contain the runtime package, // If OTOH the module does not contain the runtime package,
// create a local symbol for the moduledata. // create a local symbol for the moduledata.
moduledata = ctxt.Syms.Lookup("local.moduledata", 0) moduledata = ctxt.Syms.Lookup("local.moduledata", 0)
moduledata.Attr |= AttrLocal moduledata.Attr |= sym.AttrLocal
} }
// In all cases way we mark the moduledata as noptrdata to hide it from // In all cases way we mark the moduledata as noptrdata to hide it from
// the GC. // the GC.
moduledata.Type = SNOPTRDATA moduledata.Type = sym.SNOPTRDATA
moduledata.Attr |= AttrReachable moduledata.Attr |= sym.AttrReachable
ctxt.Moduledata = moduledata ctxt.Moduledata = moduledata
// Now that we know the link mode, trim the dynexp list. // Now that we know the link mode, trim the dynexp list.
x := AttrCgoExportDynamic x := sym.AttrCgoExportDynamic
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
x = AttrCgoExportStatic x = sym.AttrCgoExportStatic
} }
w := 0 w := 0
for i := 0; i < len(dynexp); i++ { for i := 0; i < len(dynexp); i++ {
@ -531,7 +505,7 @@ func (ctxt *Link) loadlib() {
any := false any := false
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
for _, r := range s.R { for _, r := range s.R {
if r.Sym != nil && r.Sym.Type&SMASK == SXREF && r.Sym.Name != ".got" { if r.Sym != nil && r.Sym.Type&sym.SMASK == sym.SXREF && r.Sym.Name != ".got" {
any = true any = true
break break
} }
@ -618,8 +592,8 @@ func (ctxt *Link) loadlib() {
if ctxt.Arch == sys.Arch386 { if ctxt.Arch == sys.Arch386 {
if (Buildmode == BuildmodeCArchive && Iself) || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE || ctxt.DynlinkingGo() { if (Buildmode == BuildmodeCArchive && Iself) || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE || ctxt.DynlinkingGo() {
got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0) got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
got.Type = SDYNIMPORT got.Type = sym.SDYNIMPORT
got.Attr |= AttrReachable got.Attr |= sym.AttrReachable
} }
} }
@ -638,7 +612,7 @@ func (ctxt *Link) loadlib() {
for _, s := range lib.dupTextSyms { for _, s := range lib.dupTextSyms {
if !s.Attr.OnList() { if !s.Attr.OnList() {
ctxt.Textp = append(ctxt.Textp, s) ctxt.Textp = append(ctxt.Textp, s)
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
// dupok symbols may be defined in multiple packages. its // dupok symbols may be defined in multiple packages. its
// associated package is chosen sort of arbitrarily (the // associated package is chosen sort of arbitrarily (the
// first containing package that the linker loads). canonicalize // first containing package that the linker loads). canonicalize
@ -654,9 +628,9 @@ func (ctxt *Link) loadlib() {
// We might have overwritten some functions above (this tends to happen for the // We might have overwritten some functions above (this tends to happen for the
// autogenerated type equality/hashing functions) and we don't want to generated // autogenerated type equality/hashing functions) and we don't want to generated
// pcln table entries for these any more so remove them from Textp. // pcln table entries for these any more so remove them from Textp.
textp := make([]*Symbol, 0, len(ctxt.Textp)) textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if s.Type != SDYNIMPORT { if s.Type != sym.SDYNIMPORT {
textp = append(textp, s) textp = append(textp, s)
} }
} }
@ -676,12 +650,12 @@ func (ctxt *Link) loadlib() {
// packages. All Go binaries contain these symbols, but only only // packages. All Go binaries contain these symbols, but only only
// those programs loaded dynamically in multiple parts need these // those programs loaded dynamically in multiple parts need these
// symbols to have entries in the symbol table. // symbols to have entries in the symbol table.
func typeSymbolMangling(syms *Symbols) bool { func typeSymbolMangling(syms *sym.Symbols) bool {
return Buildmode == BuildmodeShared || *FlagLinkshared || Buildmode == BuildmodePlugin || syms.ROLookup("plugin.Open", 0) != nil return Buildmode == BuildmodeShared || *FlagLinkshared || Buildmode == BuildmodePlugin || syms.ROLookup("plugin.Open", 0) != nil
} }
// typeSymbolMangle mangles the given symbol name into something shorter. // typeSymbolMangle mangles the given symbol name into something shorter.
func typeSymbolMangle(syms *Symbols, name string) string { func typeSymbolMangle(syms *sym.Symbols, name string) string {
if !typeSymbolMangling(syms) { if !typeSymbolMangling(syms) {
return name return name
} }
@ -1181,7 +1155,7 @@ func (l *Link) hostlink() {
// Do not let the host linker generate COPY relocations. These // Do not let the host linker generate COPY relocations. These
// can move symbols out of sections that rely on stable offsets // can move symbols out of sections that rely on stable offsets
// from the beginning of the section (like STYPE). // from the beginning of the section (like sym.STYPE).
argv = append(argv, "-Wl,-znocopyreloc") argv = append(argv, "-Wl,-znocopyreloc")
if l.Arch.InFamily(sys.ARM, sys.ARM64) { if l.Arch.InFamily(sys.ARM, sys.ARM64) {
@ -1626,7 +1600,7 @@ func ldshlibsyms(ctxt *Link, shlib string) {
Errorf(nil, "cannot read symbols from shared library: %s", libpath) Errorf(nil, "cannot read symbols from shared library: %s", libpath)
return return
} }
gcdataLocations := make(map[uint64]*Symbol) gcdataLocations := make(map[uint64]*sym.Symbol)
for _, elfsym := range syms { for _, elfsym := range syms {
if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
continue continue
@ -1636,10 +1610,10 @@ func ldshlibsyms(ctxt *Link, shlib string) {
// libraries, any non-dynimport symbols we find that duplicate symbols // libraries, any non-dynimport symbols we find that duplicate symbols
// already loaded should be ignored (the symbols from the .a files // already loaded should be ignored (the symbols from the .a files
// "win"). // "win").
if lsym.Type != 0 && lsym.Type != SDYNIMPORT { if lsym.Type != 0 && lsym.Type != sym.SDYNIMPORT {
continue continue
} }
lsym.Type = SDYNIMPORT lsym.Type = sym.SDYNIMPORT
lsym.ElfType = elf.ST_TYPE(elfsym.Info) lsym.ElfType = elf.ST_TYPE(elfsym.Info)
lsym.Size = int64(elfsym.Size) lsym.Size = int64(elfsym.Size)
if elfsym.Section != elf.SHN_UNDEF { if elfsym.Section != elf.SHN_UNDEF {
@ -1653,7 +1627,7 @@ func ldshlibsyms(ctxt *Link, shlib string) {
} }
} }
} }
gcdataAddresses := make(map[*Symbol]uint64) gcdataAddresses := make(map[*sym.Symbol]uint64)
if ctxt.Arch.Family == sys.ARM64 { if ctxt.Arch.Family == sys.ARM64 {
for _, sect := range f.Sections { for _, sect := range f.Sections {
if sect.Type == elf.SHT_RELA { if sect.Type == elf.SHT_RELA {
@ -1682,8 +1656,8 @@ func ldshlibsyms(ctxt *Link, shlib string) {
ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses}) ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
} }
func addsection(arch *sys.Arch, seg *Segment, name string, rwx int) *Section { func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
sect := new(Section) sect := new(sym.Section)
sect.Rwx = uint8(rwx) sect.Rwx = uint8(rwx)
sect.Name = name sect.Name = name
sect.Seg = seg sect.Seg = seg
@ -1713,12 +1687,12 @@ func Be32(b []byte) uint32 {
} }
type chain struct { type chain struct {
sym *Symbol sym *sym.Symbol
up *chain up *chain
limit int // limit on entry to sym limit int // limit on entry to sym
} }
var morestack *Symbol var morestack *sym.Symbol
// TODO: Record enough information in new object files to // TODO: Record enough information in new object files to
// allow stack checks here. // allow stack checks here.
@ -1785,7 +1759,7 @@ func stkcheck(ctxt *Link, up *chain, depth int) int {
if s.Attr.StackCheck() { if s.Attr.StackCheck() {
return 0 return 0
} }
s.Attr |= AttrStackCheck s.Attr |= sym.AttrStackCheck
} }
if depth > 100 { if depth > 100 {
@ -1799,7 +1773,7 @@ func stkcheck(ctxt *Link, up *chain, depth int) int {
// should never be called directly. // should never be called directly.
// onlyctxt.Diagnose the direct caller. // onlyctxt.Diagnose the direct caller.
// TODO(mwhudson): actually think about this. // TODO(mwhudson): actually think about this.
if depth == 1 && s.Type != SXREF && !ctxt.DynlinkingGo() && if depth == 1 && s.Type != sym.SXREF && !ctxt.DynlinkingGo() &&
Buildmode != BuildmodeCArchive && Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared && Buildmode != BuildmodePlugin { Buildmode != BuildmodeCArchive && Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared && Buildmode != BuildmodePlugin {
Errorf(s, "call to external function") Errorf(s, "call to external function")
@ -1845,7 +1819,7 @@ func stkcheck(ctxt *Link, up *chain, depth int) int {
endr := len(s.R) endr := len(s.R)
var ch1 chain var ch1 chain
var pcsp Pciter var pcsp Pciter
var r *Reloc var r *sym.Reloc
for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) { for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc). // pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
@ -1947,11 +1921,11 @@ const (
AutoSym = 'a' AutoSym = 'a'
) )
func genasmsym(ctxt *Link, put func(*Link, *Symbol, string, SymbolType, int64, *Symbol)) { func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64, *sym.Symbol)) {
// These symbols won't show up in the first loop below because we // These symbols won't show up in the first loop below because we
// skip STEXT symbols. Normal STEXT symbols are emitted by walking textp. // skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
s := ctxt.Syms.Lookup("runtime.text", 0) s := ctxt.Syms.Lookup("runtime.text", 0)
if s.Type == STEXT { if s.Type == sym.STEXT {
// We've already included this symbol in ctxt.Textp // We've already included this symbol in ctxt.Textp
// if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin. // if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin.
// See data.go:/textaddress // See data.go:/textaddress
@ -1975,14 +1949,14 @@ func genasmsym(ctxt *Link, put func(*Link, *Symbol, string, SymbolType, int64, *
if s == nil { if s == nil {
break break
} }
if s.Type == STEXT { if s.Type == sym.STEXT {
put(ctxt, s, s.Name, TextSym, s.Value, nil) put(ctxt, s, s.Name, TextSym, s.Value, nil)
} }
n++ n++
} }
s = ctxt.Syms.Lookup("runtime.etext", 0) s = ctxt.Syms.Lookup("runtime.etext", 0)
if s.Type == STEXT { if s.Type == sym.STEXT {
// We've already included this symbol in ctxt.Textp // We've already included this symbol in ctxt.Textp
// if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin. // if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin.
// See data.go:/textaddress // See data.go:/textaddress
@ -1998,36 +1972,36 @@ func genasmsym(ctxt *Link, put func(*Link, *Symbol, string, SymbolType, int64, *
if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." { if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
continue continue
} }
switch s.Type & SMASK { switch s.Type & sym.SMASK {
case SCONST, case sym.SCONST,
SRODATA, sym.SRODATA,
SSYMTAB, sym.SSYMTAB,
SPCLNTAB, sym.SPCLNTAB,
SINITARR, sym.SINITARR,
SDATA, sym.SDATA,
SNOPTRDATA, sym.SNOPTRDATA,
SELFROSECT, sym.SELFROSECT,
SMACHOGOT, sym.SMACHOGOT,
STYPE, sym.STYPE,
SSTRING, sym.SSTRING,
SGOSTRING, sym.SGOSTRING,
SGOFUNC, sym.SGOFUNC,
SGCBITS, sym.SGCBITS,
STYPERELRO, sym.STYPERELRO,
SSTRINGRELRO, sym.SSTRINGRELRO,
SGOSTRINGRELRO, sym.SGOSTRINGRELRO,
SGOFUNCRELRO, sym.SGOFUNCRELRO,
SGCBITSRELRO, sym.SGCBITSRELRO,
SRODATARELRO, sym.SRODATARELRO,
STYPELINK, sym.STYPELINK,
SITABLINK, sym.SITABLINK,
SWINDOWS: sym.SWINDOWS:
if !s.Attr.Reachable() { if !s.Attr.Reachable() {
continue continue
} }
put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype) put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype)
case SBSS, SNOPTRBSS: case sym.SBSS, sym.SNOPTRBSS:
if !s.Attr.Reachable() { if !s.Attr.Reachable() {
continue continue
} }
@ -2036,18 +2010,18 @@ func genasmsym(ctxt *Link, put func(*Link, *Symbol, string, SymbolType, int64, *
} }
put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype) put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
case SHOSTOBJ: case sym.SHOSTOBJ:
if Headtype == objabi.Hwindows || Iself { if Headtype == objabi.Hwindows || Iself {
put(ctxt, s, s.Name, UndefinedSym, s.Value, nil) put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
} }
case SDYNIMPORT: case sym.SDYNIMPORT:
if !s.Attr.Reachable() { if !s.Attr.Reachable() {
continue continue
} }
put(ctxt, s, s.Extname, UndefinedSym, 0, nil) put(ctxt, s, s.Extname, UndefinedSym, 0, nil)
case STLSBSS: case sym.STLSBSS:
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype) put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype)
} }
@ -2103,23 +2077,23 @@ func genasmsym(ctxt *Link, put func(*Link, *Symbol, string, SymbolType, int64, *
} }
} }
func Symaddr(s *Symbol) int64 { func Symaddr(s *sym.Symbol) int64 {
if !s.Attr.Reachable() { if !s.Attr.Reachable() {
Errorf(s, "unreachable symbol in symaddr") Errorf(s, "unreachable symbol in symaddr")
} }
return s.Value return s.Value
} }
func (ctxt *Link) xdefine(p string, t SymKind, v int64) { func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
s := ctxt.Syms.Lookup(p, 0) s := ctxt.Syms.Lookup(p, 0)
s.Type = t s.Type = t
s.Value = v s.Value = v
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Attr |= AttrSpecial s.Attr |= sym.AttrSpecial
s.Attr |= AttrLocal s.Attr |= sym.AttrLocal
} }
func datoff(s *Symbol, addr int64) int64 { func datoff(s *sym.Symbol, addr int64) int64 {
if uint64(addr) >= Segdata.Vaddr { if uint64(addr) >= Segdata.Vaddr {
return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
} }
@ -2139,21 +2113,21 @@ func Entryvalue(ctxt *Link) int64 {
if s.Type == 0 { if s.Type == 0 {
return *FlagTextAddr return *FlagTextAddr
} }
if s.Type != STEXT { if s.Type != sym.STEXT {
Errorf(s, "entry not text") Errorf(s, "entry not text")
} }
return s.Value return s.Value
} }
func undefsym(ctxt *Link, s *Symbol) { func undefsym(ctxt *Link, s *sym.Symbol) {
var r *Reloc var r *sym.Reloc
for i := 0; i < len(s.R); i++ { for i := 0; i < len(s.R); i++ {
r = &s.R[i] r = &s.R[i]
if r.Sym == nil { // happens for some external ARM relocs if r.Sym == nil { // happens for some external ARM relocs
continue continue
} }
if r.Sym.Type == Sxxx || r.Sym.Type == SXREF { if r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF {
Errorf(s, "undefined: %q", r.Sym.Name) Errorf(s, "undefined: %q", r.Sym.Name)
} }
if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF { if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
@ -2180,14 +2154,14 @@ func (ctxt *Link) callgraph() {
} }
var i int var i int
var r *Reloc var r *sym.Reloc
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
for i = 0; i < len(s.R); i++ { for i = 0; i < len(s.R); i++ {
r = &s.R[i] r = &s.R[i]
if r.Sym == nil { if r.Sym == nil {
continue continue
} }
if (r.Type == objabi.R_CALL || r.Type == objabi.R_CALLARM || r.Type == objabi.R_CALLPOWER || r.Type == objabi.R_CALLMIPS) && r.Sym.Type == STEXT { if (r.Type == objabi.R_CALL || r.Type == objabi.R_CALLARM || r.Type == objabi.R_CALLPOWER || r.Type == objabi.R_CALLMIPS) && r.Sym.Type == sym.STEXT {
ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name) ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name)
} }
} }

View file

@ -34,124 +34,17 @@ import (
"bufio" "bufio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"debug/elf" "debug/elf"
"fmt" "fmt"
) )
// Attribute is a set of common symbol attributes.
type Attribute int16
const (
// AttrDuplicateOK marks a symbol that can be present in multiple object
// files.
AttrDuplicateOK Attribute = 1 << iota
// AttrExternal marks function symbols loaded from host object files.
AttrExternal
// AttrNoSplit marks functions that cannot split the stack; the linker
// cares because it checks that there are no call chains of nosplit
// functions that require more than StackLimit bytes (see
// lib.go:dostkcheck)
AttrNoSplit
// AttrReachable marks symbols that are transitively referenced from the
// entry points. Unreachable symbols are not written to the output.
AttrReachable
// AttrCgoExportDynamic and AttrCgoExportStatic mark symbols referenced
// by directives written by cgo (in response to //export directives in
// the source).
AttrCgoExportDynamic
AttrCgoExportStatic
// AttrSpecial marks symbols that do not have their address (i.e. Value)
// computed by the usual mechanism of data.go:dodata() &
// data.go:address().
AttrSpecial
// AttrStackCheck is used by dostkcheck to only check each NoSplit
// function's stack usage once.
AttrStackCheck
// AttrNotInSymbolTable marks symbols that are not written to the symbol table.
AttrNotInSymbolTable
// AttrOnList marks symbols that are on some list (such as the list of
// all text symbols, or one of the lists of data symbols) and is
// consulted to avoid bugs where a symbol is put on a list twice.
AttrOnList
// AttrLocal marks symbols that are only visible within the module
// (executable or shared library) being linked. Only relevant when
// dynamically linking Go code.
AttrLocal
// AttrReflectMethod marks certain methods from the reflect package that
// can be used to call arbitrary methods. If no symbol with this bit set
// is marked as reachable, more dead code elimination can be done.
AttrReflectMethod
// AttrMakeTypelink Amarks types that should be added to the typelink
// table. See typelinks.go:typelinks().
AttrMakeTypelink
// AttrShared marks symbols compiled with the -shared option.
AttrShared
// 14 attributes defined so far.
)
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
func (a Attribute) External() bool { return a&AttrExternal != 0 }
func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 }
func (a Attribute) Reachable() bool { return a&AttrReachable != 0 }
func (a Attribute) CgoExportDynamic() bool { return a&AttrCgoExportDynamic != 0 }
func (a Attribute) CgoExportStatic() bool { return a&AttrCgoExportStatic != 0 }
func (a Attribute) Special() bool { return a&AttrSpecial != 0 }
func (a Attribute) StackCheck() bool { return a&AttrStackCheck != 0 }
func (a Attribute) NotInSymbolTable() bool { return a&AttrNotInSymbolTable != 0 }
func (a Attribute) OnList() bool { return a&AttrOnList != 0 }
func (a Attribute) Local() bool { return a&AttrLocal != 0 }
func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 }
func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 }
func (a Attribute) Shared() bool { return a&AttrShared != 0 }
func (a Attribute) CgoExport() bool {
return a.CgoExportDynamic() || a.CgoExportStatic()
}
func (a *Attribute) Set(flag Attribute, value bool) {
if value {
*a |= flag
} else {
*a &^= flag
}
}
// Reloc is a relocation.
//
// The typical Reloc rewrites part of a symbol at offset Off to address Sym.
// A Reloc is stored in a slice on the Symbol it rewrites.
//
// Relocations are generated by the compiler as the type
// cmd/internal/obj.Reloc, which is encoded into the object file wire
// format and decoded by the linker into this type. A separate type is
// used to hold linker-specific state about the relocation.
//
// Some relocations are created by cmd/link.
type Reloc struct {
Off int32 // offset to rewrite
Siz uint8 // number of bytes to rewrite, 1, 2, or 4
Done bool // set to true when relocation is complete
Variant RelocVariant // variation on Type
Type objabi.RelocType // the relocation type
Add int64 // addend
Xadd int64 // addend passed to external linker
Sym *Symbol // symbol the relocation addresses
Xsym *Symbol // symbol passed to external linker
}
type Auto struct {
Asym *Symbol
Gotype *Symbol
Aoffset int32
Name int16
}
type Shlib struct { type Shlib struct {
Path string Path string
Hash []byte Hash []byte
Deps []string Deps []string
File *elf.File File *elf.File
gcdataAddresses map[*Symbol]uint64 gcdataAddresses map[*sym.Symbol]uint64
} }
// Link holds the context for writing object code from a compiler // Link holds the context for writing object code from a compiler
@ -159,7 +52,7 @@ type Shlib struct {
type Link struct { type Link struct {
Out *OutBuf Out *OutBuf
Syms *Symbols Syms *sym.Symbols
Arch *sys.Arch Arch *sys.Arch
Debugvlog int Debugvlog int
@ -167,20 +60,20 @@ type Link struct {
Loaded bool // set after all inputs have been loaded as symbols Loaded bool // set after all inputs have been loaded as symbols
Tlsg *Symbol Tlsg *sym.Symbol
Libdir []string Libdir []string
Library []*Library Library []*Library
LibraryByPkg map[string]*Library LibraryByPkg map[string]*Library
Shlibs []Shlib Shlibs []Shlib
Tlsoffset int Tlsoffset int
Textp []*Symbol Textp []*sym.Symbol
Filesyms []*Symbol Filesyms []*sym.Symbol
Moduledata *Symbol Moduledata *sym.Symbol
PackageFile map[string]string PackageFile map[string]string
PackageShlib map[string]string PackageShlib map[string]string
tramps []*Symbol // trampolines tramps []*sym.Symbol // trampolines
} }
// The smallest possible offset from the hardware stack pointer to a local // The smallest possible offset from the hardware stack pointer to a local
@ -214,8 +107,8 @@ type Library struct {
hash string hash string
importStrings []string importStrings []string
imports []*Library imports []*Library
textp []*Symbol // text symbols defined in this library textp []*sym.Symbol // text symbols defined in this library
dupTextSyms []*Symbol // dupok text symbols defined in this library dupTextSyms []*sym.Symbol // dupok text symbols defined in this library
} }
func (l Library) String() string { func (l Library) String() string {
@ -233,35 +126,8 @@ func (l *Library) addImports(ctxt *Link, pn string) {
l.importStrings = nil l.importStrings = nil
} }
type FuncInfo struct {
Args int32
Locals int32
Autom []Auto
Pcsp Pcdata
Pcfile Pcdata
Pcline Pcdata
Pcinline Pcdata
Pcdata []Pcdata
Funcdata []*Symbol
Funcdataoff []int64
File []*Symbol
InlTree []InlinedCall
}
// InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
type InlinedCall struct {
Parent int32 // index of parent in InlTree
File *Symbol // file of the inlined call
Line int32 // line number of the inlined call
Func *Symbol // function that was inlined
}
type Pcdata struct {
P []byte
}
type Pciter struct { type Pciter struct {
d Pcdata d sym.Pcdata
p []byte p []byte
pc uint32 pc uint32
nextpc uint32 nextpc uint32
@ -270,66 +136,3 @@ type Pciter struct {
start int start int
done int done int
} }
// RelocVariant is a linker-internal variation on a relocation.
type RelocVariant uint8
const (
RV_NONE RelocVariant = iota
RV_POWER_LO
RV_POWER_HI
RV_POWER_HA
RV_POWER_DS
// RV_390_DBL is a s390x-specific relocation variant that indicates that
// the value to be placed into the relocatable field should first be
// divided by 2.
RV_390_DBL
RV_CHECK_OVERFLOW RelocVariant = 1 << 7
RV_TYPE_MASK RelocVariant = RV_CHECK_OVERFLOW - 1
)
func RelocName(arch *sys.Arch, r objabi.RelocType) string {
// We didn't have some relocation types at Go1.4.
// Uncomment code when we include those in bootstrap code.
switch {
case r >= 512: // Mach-O
// nr := (r - 512)>>1
// switch ctxt.Arch.Family {
// case sys.AMD64:
// return macho.RelocTypeX86_64(nr).String()
// case sys.ARM:
// return macho.RelocTypeARM(nr).String()
// case sys.ARM64:
// return macho.RelocTypeARM64(nr).String()
// case sys.I386:
// return macho.RelocTypeGeneric(nr).String()
// default:
// panic("unreachable")
// }
case r >= 256: // ELF
nr := r - 256
switch arch.Family {
case sys.AMD64:
return elf.R_X86_64(nr).String()
case sys.ARM:
return elf.R_ARM(nr).String()
case sys.ARM64:
return elf.R_AARCH64(nr).String()
case sys.I386:
return elf.R_386(nr).String()
case sys.MIPS, sys.MIPS64:
// return elf.R_MIPS(nr).String()
case sys.PPC64:
// return elf.R_PPC64(nr).String()
case sys.S390X:
// return elf.R_390(nr).String()
default:
panic("unreachable")
}
}
return r.String()
}

View file

@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"sort" "sort"
"strings" "strings"
) )
@ -169,7 +170,7 @@ const (
var nkind [NumSymKind]int var nkind [NumSymKind]int
var sortsym []*Symbol var sortsym []*sym.Symbol
var nsortsym int var nsortsym int
@ -346,32 +347,32 @@ func (ctxt *Link) domacho() {
// empirically, string table must begin with " \x00". // empirically, string table must begin with " \x00".
s := ctxt.Syms.Lookup(".machosymstr", 0) s := ctxt.Syms.Lookup(".machosymstr", 0)
s.Type = SMACHOSYMSTR s.Type = sym.SMACHOSYMSTR
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.AddUint8(' ') s.AddUint8(' ')
s.AddUint8('\x00') s.AddUint8('\x00')
s = ctxt.Syms.Lookup(".machosymtab", 0) s = ctxt.Syms.Lookup(".machosymtab", 0)
s.Type = SMACHOSYMTAB s.Type = sym.SMACHOSYMTAB
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
if Linkmode != LinkExternal { if Linkmode != LinkExternal {
s := ctxt.Syms.Lookup(".plt", 0) // will be __symbol_stub s := ctxt.Syms.Lookup(".plt", 0) // will be __symbol_stub
s.Type = SMACHOPLT s.Type = sym.SMACHOPLT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s = ctxt.Syms.Lookup(".got", 0) // will be __nl_symbol_ptr s = ctxt.Syms.Lookup(".got", 0) // will be __nl_symbol_ptr
s.Type = SMACHOGOT s.Type = sym.SMACHOGOT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Align = 4 s.Align = 4
s = ctxt.Syms.Lookup(".linkedit.plt", 0) // indirect table for .plt s = ctxt.Syms.Lookup(".linkedit.plt", 0) // indirect table for .plt
s.Type = SMACHOINDIRECTPLT s.Type = sym.SMACHOINDIRECTPLT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s = ctxt.Syms.Lookup(".linkedit.got", 0) // indirect table for .got s = ctxt.Syms.Lookup(".linkedit.got", 0) // indirect table for .got
s.Type = SMACHOINDIRECTGOT s.Type = sym.SMACHOINDIRECTGOT
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
} }
} }
@ -396,7 +397,7 @@ func machoadddynlib(lib string) {
dylib = append(dylib, lib) dylib = append(dylib, lib)
} }
func machoshbits(ctxt *Link, mseg *MachoSeg, sect *Section, segname string) { func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) {
buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1) buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
var msect *MachoSect var msect *MachoSect
@ -647,8 +648,8 @@ func Asmbmacho(ctxt *Link) {
} }
} }
func symkind(s *Symbol) int { func symkind(s *sym.Symbol) int {
if s.Type == SDYNIMPORT { if s.Type == sym.SDYNIMPORT {
return SymKindUndef return SymKindUndef
} }
if s.Attr.CgoExport() { if s.Attr.CgoExport() {
@ -657,7 +658,7 @@ func symkind(s *Symbol) int {
return SymKindLocal return SymKindLocal
} }
func addsym(ctxt *Link, s *Symbol, name string, type_ SymbolType, addr int64, gotype *Symbol) { func addsym(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
if s == nil { if s == nil {
return return
} }
@ -678,7 +679,7 @@ func addsym(ctxt *Link, s *Symbol, name string, type_ SymbolType, addr int64, go
nsortsym++ nsortsym++
} }
type machoscmp []*Symbol type machoscmp []*sym.Symbol
func (x machoscmp) Len() int { func (x machoscmp) Len() int {
return len(x) return len(x)
@ -704,7 +705,7 @@ func (x machoscmp) Less(i, j int) bool {
func machogenasmsym(ctxt *Link) { func machogenasmsym(ctxt *Link) {
genasmsym(ctxt, addsym) genasmsym(ctxt, addsym)
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if s.Type == SDYNIMPORT || s.Type == SHOSTOBJ { if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
if s.Attr.Reachable() { if s.Attr.Reachable() {
addsym(ctxt, s, "", DataSym, 0, nil) addsym(ctxt, s, "", DataSym, 0, nil)
} }
@ -717,10 +718,10 @@ func machosymorder(ctxt *Link) {
// So we sort them here and pre-allocate dynid for them // So we sort them here and pre-allocate dynid for them
// See https://golang.org/issue/4029 // See https://golang.org/issue/4029
for i := 0; i < len(dynexp); i++ { for i := 0; i < len(dynexp); i++ {
dynexp[i].Attr |= AttrReachable dynexp[i].Attr |= sym.AttrReachable
} }
machogenasmsym(ctxt) machogenasmsym(ctxt)
sortsym = make([]*Symbol, nsortsym) sortsym = make([]*sym.Symbol, nsortsym)
nsortsym = 0 nsortsym = 0
machogenasmsym(ctxt) machogenasmsym(ctxt)
sort.Sort(machoscmp(sortsym[:nsortsym])) sort.Sort(machoscmp(sortsym[:nsortsym]))
@ -733,7 +734,7 @@ func machosymorder(ctxt *Link) {
// //
// When dynamically linking, all non-local variables and plugin-exported // When dynamically linking, all non-local variables and plugin-exported
// symbols need to be exported. // symbols need to be exported.
func machoShouldExport(ctxt *Link, s *Symbol) bool { func machoShouldExport(ctxt *Link, s *sym.Symbol) bool {
if !ctxt.DynlinkingGo() || s.Attr.Local() { if !ctxt.DynlinkingGo() || s.Attr.Local() {
return false return false
} }
@ -752,7 +753,7 @@ func machoShouldExport(ctxt *Link, s *Symbol) bool {
if strings.HasPrefix(s.Name, "go.link.pkghash") { if strings.HasPrefix(s.Name, "go.link.pkghash") {
return true return true
} }
return s.Type >= SELFSECT // only writable sections return s.Type >= sym.SELFSECT // only writable sections
} }
func machosymtab(ctxt *Link) { func machosymtab(ctxt *Link) {
@ -780,11 +781,11 @@ func machosymtab(ctxt *Link) {
// replace "·" as ".", because DTrace cannot handle it. // replace "·" as ".", because DTrace cannot handle it.
Addstring(symstr, strings.Replace(s.Extname, "·", ".", -1)) Addstring(symstr, strings.Replace(s.Extname, "·", ".", -1))
if s.Type == SDYNIMPORT || s.Type == SHOSTOBJ { if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
symtab.AddUint8(0x01) // type N_EXT, external symbol symtab.AddUint8(0x01) // type N_EXT, external symbol
symtab.AddUint8(0) // no section symtab.AddUint8(0) // no section
symtab.AddUint16(ctxt.Arch, 0) // desc symtab.AddUint16(ctxt.Arch, 0) // desc
symtab.addUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value symtab.AddUintXX(ctxt.Arch, 0, ctxt.Arch.PtrSize) // no value
} else { } else {
if s.Attr.CgoExport() || export { if s.Attr.CgoExport() || export {
symtab.AddUint8(0x0f) symtab.AddUint8(0x0f)
@ -802,7 +803,7 @@ func machosymtab(ctxt *Link) {
symtab.AddUint8(uint8(o.Sect.Extnum)) symtab.AddUint8(uint8(o.Sect.Extnum))
} }
symtab.AddUint16(ctxt.Arch, 0) // desc symtab.AddUint16(ctxt.Arch, 0) // desc
symtab.addUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize) symtab.AddUintXX(ctxt.Arch, uint64(Symaddr(s)), ctxt.Arch.PtrSize)
} }
} }
} }
@ -889,7 +890,7 @@ func Domacholink(ctxt *Link) int64 {
return Rnd(int64(size), int64(*FlagRound)) return Rnd(int64(size), int64(*FlagRound))
} }
func machorelocsect(ctxt *Link, sect *Section, syms []*Symbol) { func machorelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
// If main section has no bits, nothing to relocate. // If main section has no bits, nothing to relocate.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return return
@ -907,27 +908,27 @@ func machorelocsect(ctxt *Link, sect *Section, syms []*Symbol) {
} }
eaddr := int32(sect.Vaddr + sect.Length) eaddr := int32(sect.Vaddr + sect.Length)
for _, sym := range syms { for _, s := range syms {
if !sym.Attr.Reachable() { if !s.Attr.Reachable() {
continue continue
} }
if sym.Value >= int64(eaddr) { if s.Value >= int64(eaddr) {
break break
} }
for ri := 0; ri < len(sym.R); ri++ { for ri := 0; ri < len(s.R); ri++ {
r := &sym.R[ri] r := &s.R[ri]
if r.Done { if r.Done {
continue continue
} }
if r.Xsym == nil { if r.Xsym == nil {
Errorf(sym, "missing xsym in relocation") Errorf(s, "missing xsym in relocation")
continue continue
} }
if !r.Xsym.Attr.Reachable() { if !r.Xsym.Attr.Reachable() {
Errorf(sym, "unreachable reloc %d (%s) target %v", r.Type, RelocName(ctxt.Arch, r.Type), r.Xsym.Name) Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
} }
if !Thearch.Machoreloc1(ctxt.Arch, ctxt.Out, sym, r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) { if !Thearch.Machoreloc1(ctxt.Arch, ctxt.Out, s, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
Errorf(sym, "unsupported obj reloc %d (%s)/%d to %s", r.Type, RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name) Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
} }
} }
} }

View file

@ -13,6 +13,7 @@ import (
"cmd/internal/dwarf" "cmd/internal/dwarf"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"io" "io"
"log" "log"
"strconv" "strconv"
@ -30,27 +31,27 @@ var emptyPkg = []byte(`"".`)
type objReader struct { type objReader struct {
rd *bufio.Reader rd *bufio.Reader
arch *sys.Arch arch *sys.Arch
syms *Symbols syms *sym.Symbols
lib *Library lib *Library
pn string pn string
dupSym *Symbol dupSym *sym.Symbol
localSymVersion int localSymVersion int
// rdBuf is used by readString and readSymName as scratch for reading strings. // rdBuf is used by readString and readSymName as scratch for reading strings.
rdBuf []byte rdBuf []byte
// List of symbol references for the file being read. // List of symbol references for the file being read.
refs []*Symbol refs []*sym.Symbol
data []byte data []byte
reloc []Reloc reloc []sym.Reloc
pcdata []Pcdata pcdata []sym.Pcdata
autom []Auto autom []sym.Auto
funcdata []*Symbol funcdata []*sym.Symbol
funcdataoff []int64 funcdataoff []int64
file []*Symbol file []*sym.Symbol
} }
func LoadObjFile(arch *sys.Arch, syms *Symbols, f *bio.Reader, lib *Library, length int64, pn string) { func LoadObjFile(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *Library, length int64, pn string) {
start := f.Offset() start := f.Offset()
r := &objReader{ r := &objReader{
rd: f.Reader, rd: f.Reader,
@ -58,7 +59,7 @@ func LoadObjFile(arch *sys.Arch, syms *Symbols, f *bio.Reader, lib *Library, len
arch: arch, arch: arch,
syms: syms, syms: syms,
pn: pn, pn: pn,
dupSym: &Symbol{Name: ".dup"}, dupSym: &sym.Symbol{Name: ".dup"},
localSymVersion: syms.IncVersion(), localSymVersion: syms.IncVersion(),
} }
r.loadObjFile() r.loadObjFile()
@ -90,8 +91,8 @@ func (r *objReader) loadObjFile() {
r.lib.importStrings = append(r.lib.importStrings, lib) r.lib.importStrings = append(r.lib.importStrings, lib)
} }
// Symbol references // sym.Symbol references
r.refs = []*Symbol{nil} // zeroth ref is nil r.refs = []*sym.Symbol{nil} // zeroth ref is nil
for { for {
c, err := r.rd.Peek(1) c, err := r.rd.Peek(1)
if err != nil { if err != nil {
@ -134,16 +135,16 @@ func (r *objReader) readSlices() {
n := r.readInt() n := r.readInt()
r.data = make([]byte, n) r.data = make([]byte, n)
n = r.readInt() n = r.readInt()
r.reloc = make([]Reloc, n) r.reloc = make([]sym.Reloc, n)
n = r.readInt() n = r.readInt()
r.pcdata = make([]Pcdata, n) r.pcdata = make([]sym.Pcdata, n)
n = r.readInt() n = r.readInt()
r.autom = make([]Auto, n) r.autom = make([]sym.Auto, n)
n = r.readInt() n = r.readInt()
r.funcdata = make([]*Symbol, n) r.funcdata = make([]*sym.Symbol, n)
r.funcdataoff = make([]int64, n) r.funcdataoff = make([]int64, n)
n = r.readInt() n = r.readInt()
r.file = make([]*Symbol, n) r.file = make([]*sym.Symbol, n)
} }
// Symbols are prefixed so their content doesn't get confused with the magic footer. // Symbols are prefixed so their content doesn't get confused with the magic footer.
@ -158,7 +159,7 @@ func (r *objReader) readSym() {
if c, err = r.rd.ReadByte(); err != nil { if c, err = r.rd.ReadByte(); err != nil {
log.Fatalln("error reading input: ", err) log.Fatalln("error reading input: ", err)
} }
t := abiSymKindToSymKind[c] t := sym.AbiSymKindToSymKind[c]
s := r.readSymIndex() s := r.readSymIndex()
flags := r.readInt() flags := r.readInt()
dupok := flags&1 != 0 dupok := flags&1 != 0
@ -171,9 +172,9 @@ func (r *objReader) readSym() {
pkg := objabi.PathToPrefix(r.lib.Pkg) pkg := objabi.PathToPrefix(r.lib.Pkg)
isdup := false isdup := false
var dup *Symbol var dup *sym.Symbol
if s.Type != 0 && s.Type != SXREF { if s.Type != 0 && s.Type != sym.SXREF {
if (t == SDATA || t == SBSS || t == SNOPTRBSS) && len(data) == 0 && nreloc == 0 { if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 {
if s.Size < int64(size) { if s.Size < int64(size) {
s.Size = int64(size) s.Size = int64(size)
} }
@ -183,10 +184,10 @@ func (r *objReader) readSym() {
return return
} }
if (s.Type == SDATA || s.Type == SBSS || s.Type == SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 { if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 {
goto overwrite goto overwrite
} }
if s.Type != SBSS && s.Type != SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() { if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() {
log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn) log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn)
} }
if len(s.P) > 0 { if len(s.P) > 0 {
@ -199,23 +200,23 @@ func (r *objReader) readSym() {
overwrite: overwrite:
s.File = pkg s.File = pkg
if dupok { if dupok {
s.Attr |= AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
} }
if t == SXREF { if t == sym.SXREF {
log.Fatalf("bad sxref") log.Fatalf("bad sxref")
} }
if t == 0 { if t == 0 {
log.Fatalf("missing type for %s in %s", s.Name, r.pn) log.Fatalf("missing type for %s in %s", s.Name, r.pn)
} }
if t == SBSS && (s.Type == SRODATA || s.Type == SNOPTRBSS) { if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
t = s.Type t = s.Type
} }
s.Type = t s.Type = t
if s.Size < int64(size) { if s.Size < int64(size) {
s.Size = int64(size) s.Size = int64(size)
} }
s.Attr.Set(AttrLocal, local) s.Attr.Set(sym.AttrLocal, local)
s.Attr.Set(AttrMakeTypelink, makeTypelink) s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
if typ != nil { if typ != nil {
s.Gotype = typ s.Gotype = typ
} }
@ -230,7 +231,7 @@ overwrite:
} }
for i := 0; i < nreloc; i++ { for i := 0; i < nreloc; i++ {
s.R[i] = Reloc{ s.R[i] = sym.Reloc{
Off: r.readInt32(), Off: r.readInt32(),
Siz: r.readUint8(), Siz: r.readUint8(),
Type: objabi.RelocType(r.readInt32()), Type: objabi.RelocType(r.readInt32()),
@ -240,21 +241,21 @@ overwrite:
} }
} }
if s.Type == STEXT { if s.Type == sym.STEXT {
s.FuncInfo = new(FuncInfo) s.FuncInfo = new(sym.FuncInfo)
pc := s.FuncInfo pc := s.FuncInfo
pc.Args = r.readInt32() pc.Args = r.readInt32()
pc.Locals = r.readInt32() pc.Locals = r.readInt32()
if r.readUint8() != 0 { if r.readUint8() != 0 {
s.Attr |= AttrNoSplit s.Attr |= sym.AttrNoSplit
} }
flags := r.readInt() flags := r.readInt()
if flags&(1<<2) != 0 { if flags&(1<<2) != 0 {
s.Attr |= AttrReflectMethod s.Attr |= sym.AttrReflectMethod
} }
if flags&(1<<3) != 0 { if flags&(1<<3) != 0 {
s.Attr |= AttrShared s.Attr |= sym.AttrShared
} }
n := r.readInt() n := r.readInt()
pc.Autom = r.autom[:n:n] pc.Autom = r.autom[:n:n]
@ -263,7 +264,7 @@ overwrite:
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
pc.Autom[i] = Auto{ pc.Autom[i] = sym.Auto{
Asym: r.readSymIndex(), Asym: r.readSymIndex(),
Aoffset: r.readInt32(), Aoffset: r.readInt32(),
Name: r.readInt16(), Name: r.readInt16(),
@ -305,7 +306,7 @@ overwrite:
pc.File[i] = r.readSymIndex() pc.File[i] = r.readSymIndex()
} }
n = r.readInt() n = r.readInt()
pc.InlTree = make([]InlinedCall, n) pc.InlTree = make([]sym.InlinedCall, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
pc.InlTree[i].Parent = r.readInt32() pc.InlTree[i].Parent = r.readInt32()
pc.InlTree[i].File = r.readSymIndex() pc.InlTree[i].File = r.readSymIndex()
@ -317,7 +318,7 @@ overwrite:
if s.Attr.OnList() { if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name) log.Fatalf("symbol %s listed multiple times", s.Name)
} }
s.Attr |= AttrOnList s.Attr |= sym.AttrOnList
r.lib.textp = append(r.lib.textp, s) r.lib.textp = append(r.lib.textp, s)
} else { } else {
// there may ba a dup in another package // there may ba a dup in another package
@ -329,12 +330,12 @@ overwrite:
} }
} }
} }
if s.Type == SDWARFINFO { if s.Type == sym.SDWARFINFO {
r.patchDWARFName(s) r.patchDWARFName(s)
} }
} }
func (r *objReader) patchDWARFName(s *Symbol) { func (r *objReader) patchDWARFName(s *sym.Symbol) {
// This is kind of ugly. Really the package name should not // This is kind of ugly. Really the package name should not
// even be included here. // even be included here.
if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION { if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION {
@ -392,8 +393,8 @@ func (r *objReader) readRef() {
if err != nil { if err != nil {
log.Panicf("failed to parse $-symbol %s: %v", s.Name, err) log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
} }
s.Type = SRODATA s.Type = sym.SRODATA
s.Attr |= AttrLocal s.Attr |= sym.AttrLocal
switch s.Name[:5] { switch s.Name[:5] {
case "$f32.": case "$f32.":
if uint64(uint32(x)) != x { if uint64(uint32(x)) != x {
@ -405,10 +406,10 @@ func (r *objReader) readRef() {
default: default:
log.Panicf("unrecognized $-symbol: %s", s.Name) log.Panicf("unrecognized $-symbol: %s", s.Name)
} }
s.Attr.Set(AttrReachable, false) s.Attr.Set(sym.AttrReachable, false)
} }
if strings.HasPrefix(s.Name, "runtime.gcbits.") { if strings.HasPrefix(s.Name, "runtime.gcbits.") {
s.Attr |= AttrLocal s.Attr |= sym.AttrLocal
} }
} }
@ -521,7 +522,7 @@ func (r *objReader) readSymName() string {
} }
// Reads the index of a symbol reference and resolves it to a symbol // Reads the index of a symbol reference and resolves it to a symbol
func (r *objReader) readSymIndex() *Symbol { func (r *objReader) readSymIndex() *sym.Symbol {
i := r.readInt() i := r.readInt()
return r.refs[i] return r.refs[i]
} }

View file

@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/src" "cmd/internal/src"
"cmd/link/internal/sym"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
@ -58,7 +59,7 @@ func pciternext(it *Pciter) {
it.nextpc = it.pc + v*it.pcscale it.nextpc = it.pc + v*it.pcscale
} }
func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) { func pciterinit(ctxt *Link, it *Pciter, d *sym.Pcdata) {
it.d = *d it.d = *d
it.p = it.d.P it.p = it.d.P
it.pc = 0 it.pc = 0
@ -70,7 +71,7 @@ func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) {
pciternext(it) pciternext(it)
} }
func addvarint(d *Pcdata, val uint32) { func addvarint(d *sym.Pcdata, val uint32) {
n := int32(0) n := int32(0)
for v := val; v >= 0x80; v >>= 7 { for v := val; v >= 0x80; v >>= 7 {
n++ n++
@ -92,7 +93,7 @@ func addvarint(d *Pcdata, val uint32) {
p[0] = byte(v) p[0] = byte(v)
} }
func addpctab(ctxt *Link, ftab *Symbol, off int32, d *Pcdata) int32 { func addpctab(ctxt *Link, ftab *sym.Symbol, off int32, d *sym.Pcdata) int32 {
var start int32 var start int32
if len(d.P) > 0 { if len(d.P) > 0 {
start = int32(len(ftab.P)) start = int32(len(ftab.P))
@ -101,7 +102,7 @@ func addpctab(ctxt *Link, ftab *Symbol, off int32, d *Pcdata) int32 {
return int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(start))) return int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(start)))
} }
func ftabaddstring(ctxt *Link, ftab *Symbol, s string) int32 { func ftabaddstring(ctxt *Link, ftab *sym.Symbol, s string) int32 {
n := int32(len(s)) + 1 n := int32(len(s)) + 1
start := int32(len(ftab.P)) start := int32(len(ftab.P))
ftab.Grow(int64(start) + int64(n) + 1) ftab.Grow(int64(start) + int64(n) + 1)
@ -110,18 +111,18 @@ func ftabaddstring(ctxt *Link, ftab *Symbol, s string) int32 {
} }
// numberfile assigns a file number to the file if it hasn't been assigned already. // numberfile assigns a file number to the file if it hasn't been assigned already.
func numberfile(ctxt *Link, file *Symbol) { func numberfile(ctxt *Link, file *sym.Symbol) {
if file.Type != SFILEPATH { if file.Type != sym.SFILEPATH {
ctxt.Filesyms = append(ctxt.Filesyms, file) ctxt.Filesyms = append(ctxt.Filesyms, file)
file.Value = int64(len(ctxt.Filesyms)) file.Value = int64(len(ctxt.Filesyms))
file.Type = SFILEPATH file.Type = sym.SFILEPATH
path := file.Name[len(src.FileSymPrefix):] path := file.Name[len(src.FileSymPrefix):]
file.Name = expandGoroot(path) file.Name = expandGoroot(path)
} }
} }
func renumberfiles(ctxt *Link, files []*Symbol, d *Pcdata) { func renumberfiles(ctxt *Link, files []*sym.Symbol, d *sym.Pcdata) {
var f *Symbol var f *sym.Symbol
// Give files numbers. // Give files numbers.
for i := 0; i < len(files); i++ { for i := 0; i < len(files); i++ {
@ -130,7 +131,7 @@ func renumberfiles(ctxt *Link, files []*Symbol, d *Pcdata) {
} }
newval := int32(-1) newval := int32(-1)
var out Pcdata var out sym.Pcdata
var it Pciter var it Pciter
for pciterinit(ctxt, &it, d); it.done == 0; pciternext(&it) { for pciterinit(ctxt, &it, d); it.done == 0; pciternext(&it) {
// value delta // value delta
@ -163,7 +164,7 @@ func renumberfiles(ctxt *Link, files []*Symbol, d *Pcdata) {
// onlycsymbol reports whether this is a cgo symbol provided by the // onlycsymbol reports whether this is a cgo symbol provided by the
// runtime and only used from C code. // runtime and only used from C code.
func onlycsymbol(s *Symbol) bool { func onlycsymbol(s *sym.Symbol) bool {
switch s.Name { switch s.Name {
case "_cgo_topofstack", "_cgo_panic", "crosscall2": case "_cgo_topofstack", "_cgo_panic", "crosscall2":
return true return true
@ -171,7 +172,7 @@ func onlycsymbol(s *Symbol) bool {
return false return false
} }
func emitPcln(s *Symbol) bool { func emitPcln(s *sym.Symbol) bool {
if s == nil { if s == nil {
return true return true
} }
@ -180,7 +181,7 @@ func emitPcln(s *Symbol) bool {
} }
// We want to generate func table entries only for the "lowest level" symbols, // We want to generate func table entries only for the "lowest level" symbols,
// not containers of subsymbols. // not containers of subsymbols.
if s.Type&SCONTAINER != 0 { if s.Type&sym.SCONTAINER != 0 {
return false return false
} }
return true return true
@ -189,20 +190,20 @@ func emitPcln(s *Symbol) bool {
// pclntab initializes the pclntab symbol with // pclntab initializes the pclntab symbol with
// runtime function and file name information. // runtime function and file name information.
var pclntabZpcln FuncInfo var pclntabZpcln sym.FuncInfo
// These variables are used to initialize runtime.firstmoduledata, see symtab.go:symtab. // These variables are used to initialize runtime.firstmoduledata, see symtab.go:symtab.
var pclntabNfunc int32 var pclntabNfunc int32
var pclntabFiletabOffset int32 var pclntabFiletabOffset int32
var pclntabPclntabOffset int32 var pclntabPclntabOffset int32
var pclntabFirstFunc *Symbol var pclntabFirstFunc *sym.Symbol
var pclntabLastFunc *Symbol var pclntabLastFunc *sym.Symbol
func (ctxt *Link) pclntab() { func (ctxt *Link) pclntab() {
funcdataBytes := int64(0) funcdataBytes := int64(0)
ftab := ctxt.Syms.Lookup("runtime.pclntab", 0) ftab := ctxt.Syms.Lookup("runtime.pclntab", 0)
ftab.Type = SPCLNTAB ftab.Type = sym.SPCLNTAB
ftab.Attr |= AttrReachable ftab.Attr |= sym.AttrReachable
// See golang.org/s/go12symtab for the format. Briefly: // See golang.org/s/go12symtab for the format. Briefly:
// 8-byte header // 8-byte header
@ -212,10 +213,10 @@ func (ctxt *Link) pclntab() {
// offset to file table [4 bytes] // offset to file table [4 bytes]
nfunc := int32(0) nfunc := int32(0)
// Find container symbols, mark them with SCONTAINER // Find container symbols, mark them with sym.SCONTAINER
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if s.Outer != nil { if s.Outer != nil {
s.Outer.Type |= SCONTAINER s.Outer.Type |= sym.SCONTAINER
} }
} }
@ -244,7 +245,7 @@ func (ctxt *Link) pclntab() {
} }
nfunc = 0 nfunc = 0
var last *Symbol var last *sym.Symbol
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
last = s last = s
if !emitPcln(s) { if !emitPcln(s) {
@ -262,14 +263,14 @@ func (ctxt *Link) pclntab() {
if len(pcln.InlTree) > 0 { if len(pcln.InlTree) > 0 {
if len(pcln.Pcdata) <= objabi.PCDATA_InlTreeIndex { if len(pcln.Pcdata) <= objabi.PCDATA_InlTreeIndex {
// Create inlining pcdata table. // Create inlining pcdata table.
pcdata := make([]Pcdata, objabi.PCDATA_InlTreeIndex+1) pcdata := make([]sym.Pcdata, objabi.PCDATA_InlTreeIndex+1)
copy(pcdata, pcln.Pcdata) copy(pcdata, pcln.Pcdata)
pcln.Pcdata = pcdata pcln.Pcdata = pcdata
} }
if len(pcln.Funcdataoff) <= objabi.FUNCDATA_InlTree { if len(pcln.Funcdataoff) <= objabi.FUNCDATA_InlTree {
// Create inline tree funcdata. // Create inline tree funcdata.
funcdata := make([]*Symbol, objabi.FUNCDATA_InlTree+1) funcdata := make([]*sym.Symbol, objabi.FUNCDATA_InlTree+1)
funcdataoff := make([]int64, objabi.FUNCDATA_InlTree+1) funcdataoff := make([]int64, objabi.FUNCDATA_InlTree+1)
copy(funcdata, pcln.Funcdata) copy(funcdata, pcln.Funcdata)
copy(funcdataoff, pcln.Funcdataoff) copy(funcdataoff, pcln.Funcdataoff)
@ -334,8 +335,8 @@ func (ctxt *Link) pclntab() {
if len(pcln.InlTree) > 0 { if len(pcln.InlTree) > 0 {
inlTreeSym := ctxt.Syms.Lookup("inltree."+s.Name, 0) inlTreeSym := ctxt.Syms.Lookup("inltree."+s.Name, 0)
inlTreeSym.Type = SRODATA inlTreeSym.Type = sym.SRODATA
inlTreeSym.Attr |= AttrReachable | AttrDuplicateOK inlTreeSym.Attr |= sym.AttrReachable | sym.AttrDuplicateOK
for i, call := range pcln.InlTree { for i, call := range pcln.InlTree {
// Usually, call.File is already numbered since the file // Usually, call.File is already numbered since the file
@ -443,9 +444,9 @@ const (
// function for a pc. See src/runtime/symtab.go:findfunc for details. // function for a pc. See src/runtime/symtab.go:findfunc for details.
func (ctxt *Link) findfunctab() { func (ctxt *Link) findfunctab() {
t := ctxt.Syms.Lookup("runtime.findfunctab", 0) t := ctxt.Syms.Lookup("runtime.findfunctab", 0)
t.Type = SRODATA t.Type = sym.SRODATA
t.Attr |= AttrReachable t.Attr |= sym.AttrReachable
t.Attr |= AttrLocal t.Attr |= sym.AttrLocal
// find min and max address // find min and max address
min := ctxt.Textp[0].Value min := ctxt.Textp[0].Value
@ -468,7 +469,7 @@ func (ctxt *Link) findfunctab() {
continue continue
} }
p := s.Value p := s.Value
var e *Symbol var e *sym.Symbol
i++ i++
if i < len(ctxt.Textp) { if i < len(ctxt.Textp) {
e = ctxt.Textp[i] e = ctxt.Textp[i]

View file

@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"debug/pe" "debug/pe"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
@ -231,7 +232,7 @@ var dosstub = []uint8{
} }
type Imp struct { type Imp struct {
s *Symbol s *sym.Symbol
off uint64 off uint64
next *Imp next *Imp
argsize int argsize int
@ -246,12 +247,12 @@ type Dll struct {
} }
var ( var (
rsrcsym *Symbol rsrcsym *sym.Symbol
PESECTHEADR int32 PESECTHEADR int32
PEFILEHEADR int32 PEFILEHEADR int32
pe64 int pe64 int
dr *Dll dr *Dll
dexport [1024]*Symbol dexport [1024]*sym.Symbol
nexport int nexport int
) )
@ -308,7 +309,7 @@ func (sect *peSection) checkOffset(off int64) {
// checkSegment verifies COFF section sect matches address // checkSegment verifies COFF section sect matches address
// and file offset provided in segment seg. // and file offset provided in segment seg.
func (sect *peSection) checkSegment(seg *Segment) { func (sect *peSection) checkSegment(seg *sym.Segment) {
if seg.Vaddr-PEBASE != uint64(sect.virtualAddress) { if seg.Vaddr-PEBASE != uint64(sect.virtualAddress) {
Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-PEBASE))) Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-PEBASE)))
errorexit() errorexit()
@ -481,7 +482,7 @@ func (f *peFile) emitRelocations(ctxt *Link) {
// relocsect relocates symbols from first in section sect, and returns // relocsect relocates symbols from first in section sect, and returns
// the total number of relocations emitted. // the total number of relocations emitted.
relocsect := func(sect *Section, syms []*Symbol, base uint64) int { relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) int {
// If main section has no bits, nothing to relocate. // If main section has no bits, nothing to relocate.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return 0 return 0
@ -574,7 +575,7 @@ dwarfLoop:
// writeSymbol appends symbol s to file f symbol table. // writeSymbol appends symbol s to file f symbol table.
// It also sets s.Dynid to written symbol number. // It also sets s.Dynid to written symbol number.
func (f *peFile) writeSymbol(out *OutBuf, s *Symbol, value int64, sectidx int, typ uint16, class uint8) { func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx int, typ uint16, class uint8) {
if len(s.Name) > 8 { if len(s.Name) > 8 {
out.Write32(0) out.Write32(0)
out.Write32(uint32(f.stringTable.add(s.Name))) out.Write32(uint32(f.stringTable.add(s.Name)))
@ -594,7 +595,7 @@ func (f *peFile) writeSymbol(out *OutBuf, s *Symbol, value int64, sectidx int, t
// mapToPESection searches peFile f for s symbol's location. // mapToPESection searches peFile f for s symbol's location.
// It returns PE section index, and offset within that section. // It returns PE section index, and offset within that section.
func (f *peFile) mapToPESection(s *Symbol) (pesectidx int, offset int64, err error) { func (f *peFile) mapToPESection(s *sym.Symbol) (pesectidx int, offset int64, err error) {
if s.Sect == nil { if s.Sect == nil {
return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name) return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name)
} }
@ -608,10 +609,10 @@ func (f *peFile) mapToPESection(s *Symbol) (pesectidx int, offset int64, err err
if Linkmode != LinkExternal { if Linkmode != LinkExternal {
return f.dataSect.index, int64(v), nil return f.dataSect.index, int64(v), nil
} }
if s.Type == SDATA { if s.Type == sym.SDATA {
return f.dataSect.index, int64(v), nil return f.dataSect.index, int64(v), nil
} }
// Note: although address of runtime.edata (type SDATA) is at the start of .bss section // Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section
// it still belongs to the .data section, not the .bss section. // it still belongs to the .data section, not the .bss section.
if v < Segdata.Filelen { if v < Segdata.Filelen {
return f.dataSect.index, int64(v), nil return f.dataSect.index, int64(v), nil
@ -622,7 +623,7 @@ func (f *peFile) mapToPESection(s *Symbol) (pesectidx int, offset int64, err err
// writeSymbols writes all COFF symbol table records. // writeSymbols writes all COFF symbol table records.
func (f *peFile) writeSymbols(ctxt *Link) { func (f *peFile) writeSymbols(ctxt *Link) {
put := func(ctxt *Link, s *Symbol, name string, type_ SymbolType, addr int64, gotype *Symbol) { put := func(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) {
if s == nil { if s == nil {
return return
} }
@ -638,7 +639,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
// Only windows/386 requires underscore prefix on external symbols. // Only windows/386 requires underscore prefix on external symbols.
if ctxt.Arch.Family == sys.I386 && if ctxt.Arch.Family == sys.I386 &&
Linkmode == LinkExternal && Linkmode == LinkExternal &&
(s.Type == SHOSTOBJ || s.Attr.CgoExport()) { (s.Type == sym.SHOSTOBJ || s.Attr.CgoExport()) {
s.Name = "_" + s.Name s.Name = "_" + s.Name
} }
@ -659,7 +660,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
} }
} }
class := IMAGE_SYM_CLASS_EXTERNAL class := IMAGE_SYM_CLASS_EXTERNAL
if s.Version != 0 || (s.Type&SHIDDEN != 0) || s.Attr.Local() { if s.Version != 0 || (s.Type&sym.SHIDDEN != 0) || s.Attr.Local() {
class = IMAGE_SYM_CLASS_STATIC class = IMAGE_SYM_CLASS_STATIC
} }
f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class)) f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class))
@ -897,8 +898,8 @@ func Peinit(ctxt *Link) {
if Linkmode == LinkInternal { if Linkmode == LinkInternal {
// some mingw libs depend on this symbol, for example, FindPESectionByName // some mingw libs depend on this symbol, for example, FindPESectionByName
ctxt.xdefine("__image_base__", SDATA, PEBASE) ctxt.xdefine("__image_base__", sym.SDATA, PEBASE)
ctxt.xdefine("_image_base__", SDATA, PEBASE) ctxt.xdefine("_image_base__", sym.SDATA, PEBASE)
} }
HEADR = PEFILEHEADR HEADR = PEFILEHEADR
@ -947,7 +948,7 @@ func initdynimport(ctxt *Link) *Dll {
dr = nil dr = nil
var m *Imp var m *Imp
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if !s.Attr.Reachable() || s.Type != SDYNIMPORT { if !s.Attr.Reachable() || s.Type != sym.SDYNIMPORT {
continue continue
} }
for d = dr; d != nil; d = d.next { for d = dr; d != nil; d = d.next {
@ -989,7 +990,7 @@ func initdynimport(ctxt *Link) *Dll {
// Add real symbol name // Add real symbol name
for d := dr; d != nil; d = d.next { for d := dr; d != nil; d = d.next {
for m = d.ms; m != nil; m = m.next { for m = d.ms; m != nil; m = m.next {
m.s.Type = SDATA m.s.Type = sym.SDATA
m.s.Grow(int64(ctxt.Arch.PtrSize)) m.s.Grow(int64(ctxt.Arch.PtrSize))
dynName := m.s.Extname dynName := m.s.Extname
// only windows/386 requires stdcall decoration // only windows/386 requires stdcall decoration
@ -997,8 +998,8 @@ func initdynimport(ctxt *Link) *Dll {
dynName += fmt.Sprintf("@%d", m.argsize) dynName += fmt.Sprintf("@%d", m.argsize)
} }
dynSym := ctxt.Syms.Lookup(dynName, 0) dynSym := ctxt.Syms.Lookup(dynName, 0)
dynSym.Attr |= AttrReachable dynSym.Attr |= sym.AttrReachable
dynSym.Type = SHOSTOBJ dynSym.Type = sym.SHOSTOBJ
r := m.s.AddRel() r := m.s.AddRel()
r.Sym = dynSym r.Sym = dynSym
r.Off = 0 r.Off = 0
@ -1008,11 +1009,11 @@ func initdynimport(ctxt *Link) *Dll {
} }
} else { } else {
dynamic := ctxt.Syms.Lookup(".windynamic", 0) dynamic := ctxt.Syms.Lookup(".windynamic", 0)
dynamic.Attr |= AttrReachable dynamic.Attr |= sym.AttrReachable
dynamic.Type = SWINDOWS dynamic.Type = sym.SWINDOWS
for d := dr; d != nil; d = d.next { for d := dr; d != nil; d = d.next {
for m = d.ms; m != nil; m = m.next { for m = d.ms; m != nil; m = m.next {
m.s.Type = SWINDOWS | SSUB m.s.Type = sym.SWINDOWS | sym.SSUB
m.s.Sub = dynamic.Sub m.s.Sub = dynamic.Sub
dynamic.Sub = m.s dynamic.Sub = m.s
m.s.Value = dynamic.Size m.s.Value = dynamic.Size
@ -1143,7 +1144,7 @@ func addimports(ctxt *Link, datsect *peSection) {
out.SeekSet(endoff) out.SeekSet(endoff)
} }
type byExtname []*Symbol type byExtname []*sym.Symbol
func (s byExtname) Len() int { return len(s) } func (s byExtname) Len() int { return len(s) }
func (s byExtname) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s byExtname) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
@ -1237,14 +1238,14 @@ func (ctxt *Link) dope() {
/* relocation table */ /* relocation table */
rel := ctxt.Syms.Lookup(".rel", 0) rel := ctxt.Syms.Lookup(".rel", 0)
rel.Attr |= AttrReachable rel.Attr |= sym.AttrReachable
rel.Type = SELFROSECT rel.Type = sym.SELFROSECT
initdynimport(ctxt) initdynimport(ctxt)
initdynexport(ctxt) initdynexport(ctxt)
} }
func setpersrc(ctxt *Link, sym *Symbol) { func setpersrc(ctxt *Link, sym *sym.Symbol) {
if rsrcsym != nil { if rsrcsym != nil {
Errorf(sym, "too many .rsrc sections") Errorf(sym, "too many .rsrc sections")
} }
@ -1263,7 +1264,7 @@ func addpersrc(ctxt *Link) {
// relocation // relocation
var p []byte var p []byte
var r *Reloc var r *sym.Reloc
var val uint32 var val uint32
for ri := 0; ri < len(rsrcsym.R); ri++ { for ri := 0; ri < len(rsrcsym.R); ri++ {
r = &rsrcsym.R[ri] r = &rsrcsym.R[ri]

View file

@ -34,19 +34,13 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"log" "log"
) )
func linknew(arch *sys.Arch) *Link { func linknew(arch *sys.Arch) *Link {
ctxt := &Link{ ctxt := &Link{
Syms: &Symbols{ Syms: sym.NewSymbols(),
hash: []map[string]*Symbol{
// preallocate about 2mb for hash of
// non static symbols
make(map[string]*Symbol, 100000),
},
Allsym: make([]*Symbol, 0, 100000),
},
Out: &OutBuf{arch: arch}, Out: &OutBuf{arch: arch},
Arch: arch, Arch: arch,
LibraryByPkg: make(map[string]*Library), LibraryByPkg: make(map[string]*Library),

View file

@ -33,6 +33,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/sym"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strings" "strings"
@ -76,7 +77,7 @@ var numelfsym int = 1 // 0 is reserved
var elfbind int var elfbind int
func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *Symbol) { func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go_ *sym.Symbol) {
var typ int var typ int
switch t { switch t {
@ -109,7 +110,7 @@ func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *S
} }
var elfshnum int var elfshnum int
if xo.Type == SDYNIMPORT || xo.Type == SHOSTOBJ { if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ {
elfshnum = SHN_UNDEF elfshnum = SHN_UNDEF
} else { } else {
if xo.Sect == nil { if xo.Sect == nil {
@ -120,14 +121,14 @@ func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *S
Errorf(x, "missing ELF section in putelfsym") Errorf(x, "missing ELF section in putelfsym")
return return
} }
elfshnum = xo.Sect.Elfsect.shnum elfshnum = xo.Sect.Elfsect.(*ElfShdr).shnum
} }
// One pass for each binding: STB_LOCAL, STB_GLOBAL, // One pass for each binding: STB_LOCAL, STB_GLOBAL,
// maybe one day STB_WEAK. // maybe one day STB_WEAK.
bind := STB_GLOBAL bind := STB_GLOBAL
if x.Version != 0 || (x.Type&SHIDDEN != 0) || x.Attr.Local() { if x.Version != 0 || (x.Type&sym.SHIDDEN != 0) || x.Attr.Local() {
bind = STB_LOCAL bind = STB_LOCAL
} }
@ -144,7 +145,7 @@ func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *S
addr -= int64(xo.Sect.Vaddr) addr -= int64(xo.Sect.Vaddr)
} }
other := STV_DEFAULT other := STV_DEFAULT
if x.Type&SHIDDEN != 0 { if x.Type&sym.SHIDDEN != 0 {
other = STV_HIDDEN other = STV_HIDDEN
} }
if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { if ctxt.Arch.Family == sys.PPC64 && typ == STT_FUNC && x.Attr.Shared() && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
@ -165,13 +166,13 @@ func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *S
s = strings.Replace(s, "·", ".", -1) s = strings.Replace(s, "·", ".", -1)
} }
if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == STEXT { if ctxt.DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == sym.STEXT {
// When dynamically linking, we want references to functions defined // When dynamically linking, we want references to functions defined
// in this module to always be to the function object, not to the // in this module to always be to the function object, not to the
// PLT. We force this by writing an additional local symbol for every // PLT. We force this by writing an additional local symbol for every
// global function symbol and making all relocations against the // global function symbol and making all relocations against the
// global symbol refer to this local symbol instead (see // global symbol refer to this local symbol instead (see
// (*Symbol).ElfsymForReloc). This is approximately equivalent to the // (*sym.Symbol).ElfsymForReloc). This is approximately equivalent to the
// ELF linker -Bsymbolic-functions option, but that is buggy on // ELF linker -Bsymbolic-functions option, but that is buggy on
// several platforms. // several platforms.
putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other) putelfsyment(ctxt.Out, putelfstr("local."+s), addr, size, STB_LOCAL<<4|typ&0xf, elfshnum, other)
@ -187,7 +188,7 @@ func putelfsym(ctxt *Link, x *Symbol, s string, t SymbolType, addr int64, go_ *S
numelfsym++ numelfsym++
} }
func putelfsectionsym(out *OutBuf, s *Symbol, shndx int) { func putelfsectionsym(out *OutBuf, s *sym.Symbol, shndx int) {
putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0) putelfsyment(out, 0, 0, 0, STB_LOCAL<<4|STT_SECTION, shndx, 0)
s.Elfsym = int32(numelfsym) s.Elfsym = int32(numelfsym)
numelfsym++ numelfsym++
@ -214,7 +215,7 @@ func Asmelfsym(ctxt *Link) {
genasmsym(ctxt, putelfsym) genasmsym(ctxt, putelfsym)
} }
func putplan9sym(ctxt *Link, x *Symbol, s string, typ SymbolType, addr int64, go_ *Symbol) { func putplan9sym(ctxt *Link, x *sym.Symbol, s string, typ SymbolType, addr int64, go_ *sym.Symbol) {
t := int(typ) t := int(typ)
switch typ { switch typ {
case TextSym, DataSym, BSSSym: case TextSym, DataSym, BSSSym:
@ -247,7 +248,7 @@ func Asmplan9sym(ctxt *Link) {
genasmsym(ctxt, putplan9sym) genasmsym(ctxt, putplan9sym)
} }
var symt *Symbol var symt *sym.Symbol
type byPkg []*Library type byPkg []*Library
@ -268,8 +269,8 @@ func (libs byPkg) Swap(a, b int) {
func textsectionmap(ctxt *Link) uint32 { func textsectionmap(ctxt *Link) uint32 {
t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
t.Type = SRODATA t.Type = sym.SRODATA
t.Attr |= AttrReachable t.Attr |= sym.AttrReachable
nsections := int64(0) nsections := int64(0)
for _, sect := range Segtext.Sections { for _, sect := range Segtext.Sections {
@ -324,98 +325,98 @@ func (ctxt *Link) symtab() {
// Define these so that they'll get put into the symbol table. // Define these so that they'll get put into the symbol table.
// data.c:/^address will provide the actual values. // data.c:/^address will provide the actual values.
ctxt.xdefine("runtime.text", STEXT, 0) ctxt.xdefine("runtime.text", sym.STEXT, 0)
ctxt.xdefine("runtime.etext", STEXT, 0) ctxt.xdefine("runtime.etext", sym.STEXT, 0)
ctxt.xdefine("runtime.itablink", SRODATA, 0) ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.eitablink", SRODATA, 0) ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.rodata", SRODATA, 0) ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.erodata", SRODATA, 0) ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.types", SRODATA, 0) ctxt.xdefine("runtime.types", sym.SRODATA, 0)
ctxt.xdefine("runtime.etypes", SRODATA, 0) ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
ctxt.xdefine("runtime.noptrdata", SNOPTRDATA, 0) ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.enoptrdata", SNOPTRDATA, 0) ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.data", SDATA, 0) ctxt.xdefine("runtime.data", sym.SDATA, 0)
ctxt.xdefine("runtime.edata", SDATA, 0) ctxt.xdefine("runtime.edata", sym.SDATA, 0)
ctxt.xdefine("runtime.bss", SBSS, 0) ctxt.xdefine("runtime.bss", sym.SBSS, 0)
ctxt.xdefine("runtime.ebss", SBSS, 0) ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
ctxt.xdefine("runtime.noptrbss", SNOPTRBSS, 0) ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.enoptrbss", SNOPTRBSS, 0) ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.end", SBSS, 0) ctxt.xdefine("runtime.end", sym.SBSS, 0)
ctxt.xdefine("runtime.epclntab", SRODATA, 0) ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
ctxt.xdefine("runtime.esymtab", SRODATA, 0) ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
// garbage collection symbols // garbage collection symbols
s := ctxt.Syms.Lookup("runtime.gcdata", 0) s := ctxt.Syms.Lookup("runtime.gcdata", 0)
s.Type = SRODATA s.Type = sym.SRODATA
s.Size = 0 s.Size = 0
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
ctxt.xdefine("runtime.egcdata", SRODATA, 0) ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0)
s = ctxt.Syms.Lookup("runtime.gcbss", 0) s = ctxt.Syms.Lookup("runtime.gcbss", 0)
s.Type = SRODATA s.Type = sym.SRODATA
s.Size = 0 s.Size = 0
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
ctxt.xdefine("runtime.egcbss", SRODATA, 0) ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
// pseudo-symbols to mark locations of type, string, and go string data. // pseudo-symbols to mark locations of type, string, and go string data.
var symtype *Symbol var symtype *sym.Symbol
var symtyperel *Symbol var symtyperel *sym.Symbol
if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) { if UseRelro() && (Buildmode == BuildmodeCArchive || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
s = ctxt.Syms.Lookup("type.*", 0) s = ctxt.Syms.Lookup("type.*", 0)
s.Type = STYPE s.Type = sym.STYPE
s.Size = 0 s.Size = 0
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
symtype = s symtype = s
s = ctxt.Syms.Lookup("typerel.*", 0) s = ctxt.Syms.Lookup("typerel.*", 0)
s.Type = STYPERELRO s.Type = sym.STYPERELRO
s.Size = 0 s.Size = 0
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
symtyperel = s symtyperel = s
} else if !ctxt.DynlinkingGo() { } else if !ctxt.DynlinkingGo() {
s = ctxt.Syms.Lookup("type.*", 0) s = ctxt.Syms.Lookup("type.*", 0)
s.Type = STYPE s.Type = sym.STYPE
s.Size = 0 s.Size = 0
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
symtype = s symtype = s
symtyperel = s symtyperel = s
} }
groupSym := func(name string, t SymKind) *Symbol { groupSym := func(name string, t sym.SymKind) *sym.Symbol {
s := ctxt.Syms.Lookup(name, 0) s := ctxt.Syms.Lookup(name, 0)
s.Type = t s.Type = t
s.Size = 0 s.Size = 0
s.Attr |= AttrLocal | AttrReachable s.Attr |= sym.AttrLocal | sym.AttrReachable
return s return s
} }
var ( var (
symgostring = groupSym("go.string.*", SGOSTRING) symgostring = groupSym("go.string.*", sym.SGOSTRING)
symgofunc = groupSym("go.func.*", SGOFUNC) symgofunc = groupSym("go.func.*", sym.SGOFUNC)
symgcbits = groupSym("runtime.gcbits.*", SGCBITS) symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
) )
var symgofuncrel *Symbol var symgofuncrel *sym.Symbol
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
if UseRelro() { if UseRelro() {
symgofuncrel = groupSym("go.funcrel.*", SGOFUNCRELRO) symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
} else { } else {
symgofuncrel = symgofunc symgofuncrel = symgofunc
} }
} }
symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
symitablink.Type = SITABLINK symitablink.Type = sym.SITABLINK
symt = ctxt.Syms.Lookup("runtime.symtab", 0) symt = ctxt.Syms.Lookup("runtime.symtab", 0)
symt.Attr |= AttrLocal symt.Attr |= sym.AttrLocal
symt.Type = SSYMTAB symt.Type = sym.SSYMTAB
symt.Size = 0 symt.Size = 0
symt.Attr |= AttrReachable symt.Attr |= sym.AttrReachable
nitablinks := 0 nitablinks := 0
@ -424,53 +425,53 @@ func (ctxt *Link) symtab() {
// just defined above will be first. // just defined above will be first.
// hide the specific symbols. // hide the specific symbols.
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
if !s.Attr.Reachable() || s.Attr.Special() || s.Type != SRODATA { if !s.Attr.Reachable() || s.Attr.Special() || s.Type != sym.SRODATA {
continue continue
} }
switch { switch {
case strings.HasPrefix(s.Name, "type."): case strings.HasPrefix(s.Name, "type."):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
} }
if UseRelro() { if UseRelro() {
s.Type = STYPERELRO s.Type = sym.STYPERELRO
s.Outer = symtyperel s.Outer = symtyperel
} else { } else {
s.Type = STYPE s.Type = sym.STYPE
s.Outer = symtype s.Outer = symtype
} }
case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro(): case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro():
// Keep go.importpath symbols in the same section as types and // Keep go.importpath symbols in the same section as types and
// names, as they can be referred to by a section offset. // names, as they can be referred to by a section offset.
s.Type = STYPERELRO s.Type = sym.STYPERELRO
case strings.HasPrefix(s.Name, "go.itablink."): case strings.HasPrefix(s.Name, "go.itablink."):
nitablinks++ nitablinks++
s.Type = SITABLINK s.Type = sym.SITABLINK
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symitablink s.Outer = symitablink
case strings.HasPrefix(s.Name, "go.string."): case strings.HasPrefix(s.Name, "go.string."):
s.Type = SGOSTRING s.Type = sym.SGOSTRING
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgostring s.Outer = symgostring
case strings.HasPrefix(s.Name, "runtime.gcbits."): case strings.HasPrefix(s.Name, "runtime.gcbits."):
s.Type = SGCBITS s.Type = sym.SGCBITS
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgcbits s.Outer = symgcbits
case strings.HasSuffix(s.Name, "·f"): case strings.HasSuffix(s.Name, "·f"):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
} }
if UseRelro() { if UseRelro() {
s.Type = SGOFUNCRELRO s.Type = sym.SGOFUNCRELRO
s.Outer = symgofuncrel s.Outer = symgofuncrel
} else { } else {
s.Type = SGOFUNC s.Type = sym.SGOFUNC
s.Outer = symgofunc s.Outer = symgofunc
} }
@ -478,8 +479,8 @@ func (ctxt *Link) symtab() {
strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals."),
strings.HasPrefix(s.Name, "gclocals·"), strings.HasPrefix(s.Name, "gclocals·"),
strings.HasPrefix(s.Name, "inltree."): strings.HasPrefix(s.Name, "inltree."):
s.Type = SGOFUNC s.Type = sym.SGOFUNC
s.Attr |= AttrNotInSymbolTable s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgofunc s.Outer = symgofunc
s.Align = 4 s.Align = 4
liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
@ -488,8 +489,8 @@ func (ctxt *Link) symtab() {
if Buildmode == BuildmodeShared { if Buildmode == BuildmodeShared {
abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
abihashgostr.Attr |= AttrReachable abihashgostr.Attr |= sym.AttrReachable
abihashgostr.Type = SRODATA abihashgostr.Type = sym.SRODATA
hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
abihashgostr.AddAddr(ctxt.Arch, hashsym) abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
@ -497,13 +498,13 @@ func (ctxt *Link) symtab() {
if Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil { if Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
for _, l := range ctxt.Library { for _, l := range ctxt.Library {
s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
s.Attr |= AttrReachable s.Attr |= sym.AttrReachable
s.Type = SRODATA s.Type = sym.SRODATA
s.Size = int64(len(l.hash)) s.Size = int64(len(l.hash))
s.P = []byte(l.hash) s.P = []byte(l.hash)
str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
str.Attr |= AttrReachable str.Attr |= sym.AttrReachable
str.Type = SRODATA str.Type = sym.SRODATA
str.AddAddr(ctxt.Arch, s) str.AddAddr(ctxt.Arch, s)
str.AddUint(ctxt.Arch, uint64(len(l.hash))) str.AddUint(ctxt.Arch, uint64(len(l.hash)))
} }
@ -567,8 +568,8 @@ func (ctxt *Link) symtab() {
moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
// The ptab slice // The ptab slice
if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
ptab.Attr |= AttrLocal ptab.Attr |= sym.AttrLocal
ptab.Type = SRODATA ptab.Type = sym.SRODATA
nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
moduledata.AddAddr(ctxt.Arch, ptab) moduledata.AddAddr(ctxt.Arch, ptab)
@ -583,9 +584,9 @@ func (ctxt *Link) symtab() {
addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath) addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath)
pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
pkghashes.Attr |= AttrReachable pkghashes.Attr |= sym.AttrReachable
pkghashes.Attr |= AttrLocal pkghashes.Attr |= sym.AttrLocal
pkghashes.Type = SRODATA pkghashes.Type = sym.SRODATA
for i, l := range ctxt.Library { for i, l := range ctxt.Library {
// pkghashes[i].name // pkghashes[i].name
@ -617,9 +618,9 @@ func (ctxt *Link) symtab() {
addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename)
modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0)
modulehashes.Attr |= AttrReachable modulehashes.Attr |= sym.AttrReachable
modulehashes.Attr |= AttrLocal modulehashes.Attr |= sym.AttrLocal
modulehashes.Type = SRODATA modulehashes.Type = sym.SRODATA
for i, shlib := range ctxt.Shlibs { for i, shlib := range ctxt.Shlibs {
// modulehashes[i].modulename // modulehashes[i].modulename
@ -631,7 +632,7 @@ func (ctxt *Link) symtab() {
// modulehashes[i].runtimehash // modulehashes[i].runtimehash
abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
abihash.Attr |= AttrReachable abihash.Attr |= sym.AttrReachable
modulehashes.AddAddr(ctxt.Arch, abihash) modulehashes.AddAddr(ctxt.Arch, abihash)
} }
@ -649,8 +650,8 @@ func (ctxt *Link) symtab() {
moduledata.Grow(moduledata.Size) moduledata.Grow(moduledata.Size)
lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
if lastmoduledatap.Type != SDYNIMPORT { if lastmoduledatap.Type != sym.SDYNIMPORT {
lastmoduledatap.Type = SNOPTRDATA lastmoduledatap.Type = sym.SNOPTRDATA
lastmoduledatap.Size = 0 // overwrite existing value lastmoduledatap.Size = 0 // overwrite existing value
lastmoduledatap.AddAddr(ctxt.Arch, moduledata) lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
} }

View file

@ -6,6 +6,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/link/internal/sym"
"sort" "sort"
) )
@ -13,7 +14,7 @@ type byTypeStr []typelinkSortKey
type typelinkSortKey struct { type typelinkSortKey struct {
TypeStr string TypeStr string
Type *Symbol Type *sym.Symbol
} }
func (s byTypeStr) Less(i, j int) bool { return s[i].TypeStr < s[j].TypeStr } func (s byTypeStr) Less(i, j int) bool { return s[i].TypeStr < s[j].TypeStr }
@ -33,11 +34,11 @@ func (ctxt *Link) typelink() {
sort.Sort(typelinks) sort.Sort(typelinks)
tl := ctxt.Syms.Lookup("runtime.typelink", 0) tl := ctxt.Syms.Lookup("runtime.typelink", 0)
tl.Type = STYPELINK tl.Type = sym.STYPELINK
tl.Attr |= AttrReachable | AttrLocal tl.Attr |= sym.AttrReachable | sym.AttrLocal
tl.Size = int64(4 * len(typelinks)) tl.Size = int64(4 * len(typelinks))
tl.P = make([]byte, tl.Size) tl.P = make([]byte, tl.Size)
tl.R = make([]Reloc, len(typelinks)) tl.R = make([]sym.Reloc, len(typelinks))
for i, s := range typelinks { for i, s := range typelinks {
r := &tl.R[i] r := &tl.R[i]
r.Sym = s.Type r.Sym = s.Type

View file

@ -6,6 +6,7 @@ package ld
import ( import (
"bytes" "bytes"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"os" "os"
@ -102,7 +103,7 @@ func Exitf(format string, a ...interface{}) {
// //
// Logging an error means that on exit cmd/link will delete any // Logging an error means that on exit cmd/link will delete any
// output file and return a non-zero error code. // output file and return a non-zero error code.
func Errorf(s *Symbol, format string, args ...interface{}) { func Errorf(s *sym.Symbol, format string, args ...interface{}) {
if s != nil { if s != nil {
format = s.Name + ": " + format format = s.Name + ": " + format
} }

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"fmt" "fmt"
"log" "log"
) )
@ -42,12 +43,12 @@ func gentext(ctxt *ld.Link) {
return return
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
log.Fatalf("adddynrel not implemented") log.Fatalf("adddynrel not implemented")
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write32(uint32(sectoff)) ctxt.Out.Write32(uint32(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -76,11 +77,11 @@ func elfsetupplt(ctxt *ld.Link) {
return return
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
return false return false
} }
func applyrel(arch *sys.Arch, r *ld.Reloc, s *ld.Symbol, val *int64, t int64) { func applyrel(arch *sys.Arch, r *sym.Reloc, s *sym.Symbol, val *int64, t int64) {
o := arch.ByteOrder.Uint32(s.P[r.Off:]) o := arch.ByteOrder.Uint32(s.P[r.Off:])
switch r.Type { switch r.Type {
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS: case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
@ -92,7 +93,7 @@ func applyrel(arch *sys.Arch, r *ld.Reloc, s *ld.Symbol, val *int64, t int64) {
} }
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
switch r.Type { switch r.Type {
default: default:
@ -108,7 +109,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
rs = rs.Outer rs = rs.Outer
} }
if rs.Type != ld.SHOSTOBJ && rs.Type != ld.SDYNIMPORT && rs.Sect == nil { if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name) ld.Errorf(s, "missing section for %s", rs.Name)
} }
r.Xsym = rs r.Xsym = rs
@ -161,7 +162,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
return -1 return -1
} }

View file

@ -34,18 +34,19 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"fmt" "fmt"
"log" "log"
) )
func gentext(ctxt *ld.Link) {} func gentext(ctxt *ld.Link) {}
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
log.Fatalf("adddynrel not implemented") log.Fatalf("adddynrel not implemented")
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
// mips64 ELF relocation (endian neutral) // mips64 ELF relocation (endian neutral)
// offset uint64 // offset uint64
// sym uint32 // sym uint32
@ -93,11 +94,11 @@ func elfsetupplt(ctxt *ld.Link) {
return return
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
return false return false
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
switch r.Type { switch r.Type {
default: default:
@ -114,7 +115,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
rs = rs.Outer rs = rs.Outer
} }
if rs.Type != ld.SHOSTOBJ && rs.Type != ld.SDYNIMPORT && rs.Sect == nil { if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name) ld.Errorf(s, "missing section for %s", rs.Name)
} }
r.Xsym = rs r.Xsym = rs
@ -168,7 +169,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
return -1 return -1
} }

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"log" "log"
@ -88,11 +89,11 @@ func genplt(ctxt *ld.Link) {
// //
// This assumes "case 1" from the ABI, where the caller needs // This assumes "case 1" from the ABI, where the caller needs
// us to save and restore the TOC pointer. // us to save and restore the TOC pointer.
var stubs []*ld.Symbol var stubs []*sym.Symbol
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
for i := range s.R { for i := range s.R {
r := &s.R[i] r := &s.R[i]
if r.Type != 256+ld.R_PPC64_REL24 || r.Sym.Type != ld.SDYNIMPORT { if r.Type != 256+ld.R_PPC64_REL24 || r.Sym.Type != sym.SDYNIMPORT {
continue continue
} }
@ -105,7 +106,7 @@ func genplt(ctxt *ld.Link) {
stub := ctxt.Syms.Lookup(n, 0) stub := ctxt.Syms.Lookup(n, 0)
if s.Attr.Reachable() { if s.Attr.Reachable() {
stub.Attr |= ld.AttrReachable stub.Attr |= sym.AttrReachable
} }
if stub.Size == 0 { if stub.Size == 0 {
// Need outer to resolve .TOC. // Need outer to resolve .TOC.
@ -132,14 +133,14 @@ func genplt(ctxt *ld.Link) {
func genaddmoduledata(ctxt *ld.Link) { func genaddmoduledata(ctxt *ld.Link) {
addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT && ld.Buildmode != ld.BuildmodePlugin { if addmoduledata.Type == sym.STEXT && ld.Buildmode != ld.BuildmodePlugin {
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
o := func(op uint32) { o := func(op uint32) {
initfunc.AddUint32(ctxt.Arch, op) initfunc.AddUint32(ctxt.Arch, op)
} }
@ -148,7 +149,7 @@ func genaddmoduledata(ctxt *ld.Link) {
rel.Off = int32(initfunc.Size) rel.Off = int32(initfunc.Size)
rel.Siz = 8 rel.Siz = 8
rel.Sym = ctxt.Syms.Lookup(".TOC.", 0) rel.Sym = ctxt.Syms.Lookup(".TOC.", 0)
rel.Sym.Attr |= ld.AttrReachable rel.Sym.Attr |= sym.AttrReachable
rel.Type = objabi.R_ADDRPOWER_PCREL rel.Type = objabi.R_ADDRPOWER_PCREL
o(0x3c4c0000) o(0x3c4c0000)
// addi r2, r2, .TOC.-func@l // addi r2, r2, .TOC.-func@l
@ -166,8 +167,8 @@ func genaddmoduledata(ctxt *ld.Link) {
} else { } else {
rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0) rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
} }
rel.Sym.Attr |= ld.AttrReachable rel.Sym.Attr |= sym.AttrReachable
rel.Sym.Attr |= ld.AttrLocal rel.Sym.Attr |= sym.AttrLocal
rel.Type = objabi.R_ADDRPOWER_GOT rel.Type = objabi.R_ADDRPOWER_GOT
o(0x3c620000) o(0x3c620000)
// ld r3, local.moduledata@got@l(r3) // ld r3, local.moduledata@got@l(r3)
@ -195,9 +196,9 @@ func genaddmoduledata(ctxt *ld.Link) {
} }
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
@ -213,7 +214,7 @@ func gentext(ctxt *ld.Link) {
// Construct a call stub in stub that calls symbol targ via its PLT // Construct a call stub in stub that calls symbol targ via its PLT
// entry. // entry.
func gencallstub(ctxt *ld.Link, abicase int, stub *ld.Symbol, targ *ld.Symbol) { func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol) {
if abicase != 1 { if abicase != 1 {
// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC // If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
// relocations, we'll need to implement cases 2 and 3. // relocations, we'll need to implement cases 2 and 3.
@ -222,7 +223,7 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *ld.Symbol, targ *ld.Symbol) {
plt := ctxt.Syms.Lookup(".plt", 0) plt := ctxt.Syms.Lookup(".plt", 0)
stub.Type = ld.STEXT stub.Type = sym.STEXT
// Save TOC pointer in TOC save slot // Save TOC pointer in TOC save slot
stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1) stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1)
@ -238,7 +239,7 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *ld.Symbol, targ *ld.Symbol) {
r.Off += int32(r.Siz) r.Off += int32(r.Siz)
} }
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_HA r.Variant = sym.RV_POWER_HA
stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha
r = stub.AddRel() r = stub.AddRel()
r.Off = int32(stub.Size) r.Off = int32(stub.Size)
@ -249,7 +250,7 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *ld.Symbol, targ *ld.Symbol) {
r.Off += int32(r.Siz) r.Off += int32(r.Siz)
} }
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_LO r.Variant = sym.RV_POWER_LO
stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12) stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12)
// Jump to the loaded pointer // Jump to the loaded pointer
@ -257,13 +258,13 @@ func gencallstub(ctxt *ld.Link, abicase int, stub *ld.Symbol, targ *ld.Symbol) {
stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
switch r.Type { switch r.Type {
default: default:
if r.Type >= 256 { if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
return false return false
} }
@ -278,7 +279,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// to use r12 to compute r2.) // to use r12 to compute r2.)
r.Add += int64(r.Sym.Localentry) * 4 r.Add += int64(r.Sym.Localentry) * 4
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
// Should have been handled in elfsetupplt // Should have been handled in elfsetupplt
ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import") ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
} }
@ -289,7 +290,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Add += 4 r.Add += 4
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import") ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
} }
@ -297,7 +298,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_PPC64_ADDR64: case 256 + ld.R_PPC64_ADDR64:
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
// These happen in .toc sections // These happen in .toc sections
ld.Adddynsym(ctxt, targ) ld.Adddynsym(ctxt, targ)
@ -312,55 +313,55 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_PPC64_TOC16: case 256 + ld.R_PPC64_TOC16:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_LO | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
return true return true
case 256 + ld.R_PPC64_TOC16_LO: case 256 + ld.R_PPC64_TOC16_LO:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_LO r.Variant = sym.RV_POWER_LO
return true return true
case 256 + ld.R_PPC64_TOC16_HA: case 256 + ld.R_PPC64_TOC16_HA:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
return true return true
case 256 + ld.R_PPC64_TOC16_HI: case 256 + ld.R_PPC64_TOC16_HI:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
return true return true
case 256 + ld.R_PPC64_TOC16_DS: case 256 + ld.R_PPC64_TOC16_DS:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_DS | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
return true return true
case 256 + ld.R_PPC64_TOC16_LO_DS: case 256 + ld.R_PPC64_TOC16_LO_DS:
r.Type = objabi.R_POWER_TOC r.Type = objabi.R_POWER_TOC
r.Variant = ld.RV_POWER_DS r.Variant = sym.RV_POWER_DS
return true return true
case 256 + ld.R_PPC64_REL16_LO: case 256 + ld.R_PPC64_REL16_LO:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_POWER_LO r.Variant = sym.RV_POWER_LO
r.Add += 2 // Compensate for relocation size of 2 r.Add += 2 // Compensate for relocation size of 2
return true return true
case 256 + ld.R_PPC64_REL16_HI: case 256 + ld.R_PPC64_REL16_HI:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
r.Add += 2 r.Add += 2
return true return true
case 256 + ld.R_PPC64_REL16_HA: case 256 + ld.R_PPC64_REL16_HA:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
r.Add += 2 r.Add += 2
return true return true
} }
// Handle references to ELF symbols from our own object files. // Handle references to ELF symbols from our own object files.
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
return true return true
} }
@ -369,7 +370,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write64(uint64(sectoff)) ctxt.Out.Write64(uint64(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -448,13 +449,13 @@ func elfsetupplt(ctxt *ld.Link) {
} }
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
return false return false
} }
// Return the value of .TOC. for symbol s // Return the value of .TOC. for symbol s
func symtoc(ctxt *ld.Link, s *ld.Symbol) int64 { func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
var toc *ld.Symbol var toc *sym.Symbol
if s.Outer != nil { if s.Outer != nil {
toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version)) toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
@ -470,7 +471,7 @@ func symtoc(ctxt *ld.Link, s *ld.Symbol) int64 {
return toc.Value return toc.Value
} }
func archrelocaddr(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
var o1, o2 uint32 var o1, o2 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian { if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = uint32(*val >> 32) o1 = uint32(*val >> 32)
@ -518,7 +519,7 @@ func archrelocaddr(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
} }
// resolve direct jump relocation r in s, and add trampoline if necessary // resolve direct jump relocation r in s, and add trampoline if necessary
func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) { func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
// Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it.
// For internal linking, trampolines are always created for long calls. // For internal linking, trampolines are always created for long calls.
@ -536,7 +537,7 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
// If branch offset is too far then create a trampoline. // If branch offset is too far then create a trampoline.
if (ld.Linkmode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ld.Linkmode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) { if (ld.Linkmode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ld.Linkmode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
var tramp *ld.Symbol var tramp *sym.Symbol
for i := 0; ; i++ { for i := 0; ; i++ {
// Using r.Add as part of the name is significant in functions like duffzero where the call // Using r.Add as part of the name is significant in functions like duffzero where the call
@ -579,11 +580,11 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
r.Done = false r.Done = false
} }
default: default:
ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
} }
} }
func gentramp(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) { func gentramp(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
// Used for default build mode for an executable // Used for default build mode for an executable
// Address of the call target is generated using // Address of the call target is generated using
// relocation and doesn't depend on r2 (TOC). // relocation and doesn't depend on r2 (TOC).
@ -619,7 +620,7 @@ func gentramp(arch *sys.Arch, tramp, target *ld.Symbol, offset int64) {
arch.ByteOrder.PutUint32(tramp.P[12:], o4) arch.ByteOrder.PutUint32(tramp.P[12:], o4)
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
switch r.Type { switch r.Type {
default: default:
@ -646,7 +647,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
rs = rs.Outer rs = rs.Outer
} }
if rs.Type != ld.SHOSTOBJ && rs.Type != ld.SDYNIMPORT && rs.Sect == nil { if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name) ld.Errorf(s, "missing section for %s", rs.Name)
} }
r.Xsym = rs r.Xsym = rs
@ -704,17 +705,17 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
switch r.Variant & ld.RV_TYPE_MASK { switch r.Variant & sym.RV_TYPE_MASK {
default: default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant) ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
fallthrough fallthrough
case ld.RV_NONE: case sym.RV_NONE:
return t return t
case ld.RV_POWER_LO: case sym.RV_POWER_LO:
if r.Variant&ld.RV_CHECK_OVERFLOW != 0 { if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned // Whether to check for signed or unsigned
// overflow depends on the instruction // overflow depends on the instruction
var o1 uint32 var o1 uint32
@ -740,15 +741,15 @@ func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
return int64(int16(t)) return int64(int16(t))
case ld.RV_POWER_HA: case sym.RV_POWER_HA:
t += 0x8000 t += 0x8000
fallthrough fallthrough
// Fallthrough // Fallthrough
case ld.RV_POWER_HI: case sym.RV_POWER_HI:
t >>= 16 t >>= 16
if r.Variant&ld.RV_CHECK_OVERFLOW != 0 { if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned // Whether to check for signed or unsigned
// overflow depends on the instruction // overflow depends on the instruction
var o1 uint32 var o1 uint32
@ -774,7 +775,7 @@ func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
return int64(int16(t)) return int64(int16(t))
case ld.RV_POWER_DS: case sym.RV_POWER_DS:
var o1 uint32 var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian { if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = uint32(ld.Be16(s.P[r.Off:])) o1 = uint32(ld.Be16(s.P[r.Off:]))
@ -784,7 +785,7 @@ func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
if t&3 != 0 { if t&3 != 0 {
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
} }
if (r.Variant&ld.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
goto overflow goto overflow
} }
return int64(o1)&0x3 | int64(int16(t)) return int64(o1)&0x3 | int64(int16(t))
@ -795,7 +796,7 @@ overflow:
return t return t
} }
func addpltsym(ctxt *ld.Link, s *ld.Symbol) { func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Plt >= 0 { if s.Plt >= 0 {
return return
} }
@ -841,7 +842,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
} }
// Generate the glink resolver stub if necessary and return the .glink section // Generate the glink resolver stub if necessary and return the .glink section
func ensureglinkresolver(ctxt *ld.Link) *ld.Symbol { func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol {
glink := ctxt.Syms.Lookup(".glink", 0) glink := ctxt.Syms.Lookup(".glink", 0)
if glink.Size != 0 { if glink.Size != 0 {
return glink return glink

View file

@ -34,6 +34,7 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"debug/elf" "debug/elf"
"fmt" "fmt"
) )
@ -53,16 +54,16 @@ func gentext(ctxt *ld.Link) {
return return
} }
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT && ld.Buildmode != ld.BuildmodePlugin { if addmoduledata.Type == sym.STEXT && ld.Buildmode != ld.BuildmodePlugin {
// we're linking a module containing the runtime -> no need for // we're linking a module containing the runtime -> no need for
// an init function // an init function
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
// larl %r2, <local.moduledata> // larl %r2, <local.moduledata>
initfunc.AddUint8(0xc0) initfunc.AddUint8(0xc0)
@ -72,7 +73,7 @@ func gentext(ctxt *ld.Link) {
lmd.Siz = 4 lmd.Siz = 4
lmd.Sym = ctxt.Moduledata lmd.Sym = ctxt.Moduledata
lmd.Type = objabi.R_PCREL lmd.Type = objabi.R_PCREL
lmd.Variant = ld.RV_390_DBL lmd.Variant = sym.RV_390_DBL
lmd.Add = 2 + int64(lmd.Siz) lmd.Add = 2 + int64(lmd.Siz)
initfunc.AddUint32(ctxt.Arch, 0) initfunc.AddUint32(ctxt.Arch, 0)
@ -84,7 +85,7 @@ func gentext(ctxt *ld.Link) {
rel.Siz = 4 rel.Siz = 4
rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0) rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
rel.Type = objabi.R_CALL rel.Type = objabi.R_CALL
rel.Variant = ld.RV_390_DBL rel.Variant = sym.RV_390_DBL
rel.Add = 2 + int64(rel.Siz) rel.Add = 2 + int64(rel.Siz)
initfunc.AddUint32(ctxt.Arch, 0) initfunc.AddUint32(ctxt.Arch, 0)
@ -95,13 +96,13 @@ func gentext(ctxt *ld.Link) {
} }
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
switch r.Type { switch r.Type {
@ -121,7 +122,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
256 + ld.R_390_16, 256 + ld.R_390_16,
256 + ld.R_390_32, 256 + ld.R_390_32,
256 + ld.R_390_64: 256 + ld.R_390_64:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
} }
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
@ -130,10 +131,10 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_390_PC16, case 256 + ld.R_390_PC16,
256 + ld.R_390_PC32, 256 + ld.R_390_PC32,
256 + ld.R_390_PC64: 256 + ld.R_390_PC64:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name)
} }
if targ.Type == 0 || targ.Type == ld.SXREF { if targ.Type == 0 || targ.Type == sym.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name) ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
} }
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
@ -149,9 +150,9 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_390_PLT16DBL, case 256 + ld.R_390_PLT16DBL,
256 + ld.R_390_PLT32DBL: 256 + ld.R_390_PLT32DBL:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_390_DBL r.Variant = sym.RV_390_DBL
r.Add += int64(r.Siz) r.Add += int64(r.Siz)
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt) r.Add += int64(targ.Plt)
@ -162,7 +163,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
256 + ld.R_390_PLT64: 256 + ld.R_390_PLT64:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Add += int64(r.Siz) r.Add += int64(r.Siz)
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt) r.Add += int64(targ.Plt)
@ -186,7 +187,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
case 256 + ld.R_390_GOTOFF: case 256 + ld.R_390_GOTOFF:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
} }
r.Type = objabi.R_GOTOFF r.Type = objabi.R_GOTOFF
@ -201,16 +202,16 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_390_PC16DBL, case 256 + ld.R_390_PC16DBL,
256 + ld.R_390_PC32DBL: 256 + ld.R_390_PC32DBL:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_390_DBL r.Variant = sym.RV_390_DBL
r.Add += int64(r.Siz) r.Add += int64(r.Siz)
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name)
} }
return true return true
case 256 + ld.R_390_GOTPCDBL: case 256 + ld.R_390_GOTPCDBL:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_390_DBL r.Variant = sym.RV_390_DBL
r.Sym = ctxt.Syms.Lookup(".got", 0) r.Sym = ctxt.Syms.Lookup(".got", 0)
r.Add += int64(r.Siz) r.Add += int64(r.Siz)
return true return true
@ -219,21 +220,21 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
addgotsym(ctxt, targ) addgotsym(ctxt, targ)
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = ld.RV_390_DBL r.Variant = sym.RV_390_DBL
r.Sym = ctxt.Syms.Lookup(".got", 0) r.Sym = ctxt.Syms.Lookup(".got", 0)
r.Add += int64(targ.Got) r.Add += int64(targ.Got)
r.Add += int64(r.Siz) r.Add += int64(r.Siz)
return true return true
} }
// Handle references to ELF symbols from our own object files. // Handle references to ELF symbols from our own object files.
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
return true return true
} }
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write64(uint64(sectoff)) ctxt.Out.Write64(uint64(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -275,14 +276,14 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
} }
case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL: case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
elfrel := ld.R_390_NONE elfrel := ld.R_390_NONE
isdbl := r.Variant&ld.RV_TYPE_MASK == ld.RV_390_DBL isdbl := r.Variant&sym.RV_TYPE_MASK == sym.RV_390_DBL
// TODO(mundaym): all DBL style relocations should be // TODO(mundaym): all DBL style relocations should be
// signalled using the variant - see issue 14218. // signalled using the variant - see issue 14218.
switch r.Type { switch r.Type {
case objabi.R_PCRELDBL, objabi.R_CALL: case objabi.R_PCRELDBL, objabi.R_CALL:
isdbl = true isdbl = true
} }
if r.Xsym.Type == ld.SDYNIMPORT && (r.Xsym.ElfType == elf.STT_FUNC || r.Type == objabi.R_CALL) { if r.Xsym.Type == sym.SDYNIMPORT && (r.Xsym.ElfType == elf.STT_FUNC || r.Type == objabi.R_CALL) {
if isdbl { if isdbl {
switch r.Siz { switch r.Siz {
case 2: case 2:
@ -377,11 +378,11 @@ func elfsetupplt(ctxt *ld.Link) {
} }
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
return false return false
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
return false return false
} }
@ -398,16 +399,16 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
switch r.Variant & ld.RV_TYPE_MASK { switch r.Variant & sym.RV_TYPE_MASK {
default: default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant) ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
return t return t
case ld.RV_NONE: case sym.RV_NONE:
return t return t
case ld.RV_390_DBL: case sym.RV_390_DBL:
if (t & 1) != 0 { if (t & 1) != 0 {
ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value) ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
} }
@ -415,7 +416,7 @@ func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
} }
} }
func addpltsym(ctxt *ld.Link, s *ld.Symbol) { func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Plt >= 0 { if s.Plt >= 0 {
return return
} }
@ -478,7 +479,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
} }
} }
func addgotsym(ctxt *ld.Link, s *ld.Symbol) { func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Got >= 0 { if s.Got >= 0 {
return return
} }

View file

@ -0,0 +1,83 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sym
// Attribute is a set of common symbol attributes.
type Attribute int16
const (
// AttrDuplicateOK marks a symbol that can be present in multiple object
// files.
AttrDuplicateOK Attribute = 1 << iota
// AttrExternal marks function symbols loaded from host object files.
AttrExternal
// AttrNoSplit marks functions that cannot split the stack; the linker
// cares because it checks that there are no call chains of nosplit
// functions that require more than StackLimit bytes (see
// lib.go:dostkcheck)
AttrNoSplit
// AttrReachable marks symbols that are transitively referenced from the
// entry points. Unreachable symbols are not written to the output.
AttrReachable
// AttrCgoExportDynamic and AttrCgoExportStatic mark symbols referenced
// by directives written by cgo (in response to //export directives in
// the source).
AttrCgoExportDynamic
AttrCgoExportStatic
// AttrSpecial marks symbols that do not have their address (i.e. Value)
// computed by the usual mechanism of data.go:dodata() &
// data.go:address().
AttrSpecial
// AttrStackCheck is used by dostkcheck to only check each NoSplit
// function's stack usage once.
AttrStackCheck
// AttrNotInSymbolTable marks symbols that are not written to the symbol table.
AttrNotInSymbolTable
// AttrOnList marks symbols that are on some list (such as the list of
// all text symbols, or one of the lists of data symbols) and is
// consulted to avoid bugs where a symbol is put on a list twice.
AttrOnList
// AttrLocal marks symbols that are only visible within the module
// (executable or shared library) being linked. Only relevant when
// dynamically linking Go code.
AttrLocal
// AttrReflectMethod marks certain methods from the reflect package that
// can be used to call arbitrary methods. If no symbol with this bit set
// is marked as reachable, more dead code elimination can be done.
AttrReflectMethod
// AttrMakeTypelink Amarks types that should be added to the typelink
// table. See typelinks.go:typelinks().
AttrMakeTypelink
// AttrShared marks symbols compiled with the -shared option.
AttrShared
// 14 attributes defined so far.
)
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
func (a Attribute) External() bool { return a&AttrExternal != 0 }
func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 }
func (a Attribute) Reachable() bool { return a&AttrReachable != 0 }
func (a Attribute) CgoExportDynamic() bool { return a&AttrCgoExportDynamic != 0 }
func (a Attribute) CgoExportStatic() bool { return a&AttrCgoExportStatic != 0 }
func (a Attribute) Special() bool { return a&AttrSpecial != 0 }
func (a Attribute) StackCheck() bool { return a&AttrStackCheck != 0 }
func (a Attribute) NotInSymbolTable() bool { return a&AttrNotInSymbolTable != 0 }
func (a Attribute) OnList() bool { return a&AttrOnList != 0 }
func (a Attribute) Local() bool { return a&AttrLocal != 0 }
func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 }
func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 }
func (a Attribute) Shared() bool { return a&AttrShared != 0 }
func (a Attribute) CgoExport() bool {
return a.CgoExportDynamic() || a.CgoExportStatic()
}
func (a *Attribute) Set(flag Attribute, value bool) {
if value {
*a |= flag
} else {
*a &^= flag
}
}

View file

@ -0,0 +1,97 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sym
import (
"cmd/internal/objabi"
"cmd/internal/sys"
"debug/elf"
)
// Reloc is a relocation.
//
// The typical Reloc rewrites part of a symbol at offset Off to address Sym.
// A Reloc is stored in a slice on the Symbol it rewrites.
//
// Relocations are generated by the compiler as the type
// cmd/internal/obj.Reloc, which is encoded into the object file wire
// format and decoded by the linker into this type. A separate type is
// used to hold linker-specific state about the relocation.
//
// Some relocations are created by cmd/link.
type Reloc struct {
Off int32 // offset to rewrite
Siz uint8 // number of bytes to rewrite, 1, 2, or 4
Done bool // set to true when relocation is complete
Variant RelocVariant // variation on Type
Type objabi.RelocType // the relocation type
Add int64 // addend
Xadd int64 // addend passed to external linker
Sym *Symbol // symbol the relocation addresses
Xsym *Symbol // symbol passed to external linker
}
// RelocVariant is a linker-internal variation on a relocation.
type RelocVariant uint8
const (
RV_NONE RelocVariant = iota
RV_POWER_LO
RV_POWER_HI
RV_POWER_HA
RV_POWER_DS
// RV_390_DBL is a s390x-specific relocation variant that indicates that
// the value to be placed into the relocatable field should first be
// divided by 2.
RV_390_DBL
RV_CHECK_OVERFLOW RelocVariant = 1 << 7
RV_TYPE_MASK RelocVariant = RV_CHECK_OVERFLOW - 1
)
func RelocName(arch *sys.Arch, r objabi.RelocType) string {
// We didn't have some relocation types at Go1.4.
// Uncomment code when we include those in bootstrap code.
switch {
case r >= 512: // Mach-O
// nr := (r - 512)>>1
// switch ctxt.Arch.Family {
// case sys.AMD64:
// return macho.RelocTypeX86_64(nr).String()
// case sys.ARM:
// return macho.RelocTypeARM(nr).String()
// case sys.ARM64:
// return macho.RelocTypeARM64(nr).String()
// case sys.I386:
// return macho.RelocTypeGeneric(nr).String()
// default:
// panic("unreachable")
// }
case r >= 256: // ELF
nr := r - 256
switch arch.Family {
case sys.AMD64:
return elf.R_X86_64(nr).String()
case sys.ARM:
return elf.R_ARM(nr).String()
case sys.ARM64:
return elf.R_AARCH64(nr).String()
case sys.I386:
return elf.R_386(nr).String()
case sys.MIPS, sys.MIPS64:
// return elf.R_MIPS(nr).String()
case sys.PPC64:
// return elf.R_PPC64(nr).String()
case sys.S390X:
// return elf.R_390(nr).String()
default:
panic("unreachable")
}
}
return r.String()
}

View file

@ -0,0 +1,58 @@
// Inferno utils/8l/asm.c
// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/8l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package sym
// Terrible but standard terminology.
// A segment describes a block of file to load into memory.
// A section further describes the pieces of that block for
// use in debuggers and such.
type Segment struct {
Rwx uint8 // permission as usual unix bits (5 = r-x etc)
Vaddr uint64 // virtual address
Length uint64 // length in memory
Fileoff uint64 // file offset
Filelen uint64 // length on disk
Sections []*Section
}
type Section struct {
Rwx uint8
Extnum int16
Align int32
Name string
Vaddr uint64
Length uint64
Seg *Segment
Elfsect interface{} // an *ld.ElfShdr
Reloff uint64
Rellen uint64
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package ld package sym
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
@ -105,19 +105,19 @@ func (s *Symbol) AddUint8(v uint8) int64 {
} }
func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 { func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 {
return s.addUintXX(arch, uint64(v), 2) return s.AddUintXX(arch, uint64(v), 2)
} }
func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 { func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 {
return s.addUintXX(arch, uint64(v), 4) return s.AddUintXX(arch, uint64(v), 4)
} }
func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 { func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 {
return s.addUintXX(arch, v, 8) return s.AddUintXX(arch, v, 8)
} }
func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 { func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 {
return s.addUintXX(arch, v, arch.PtrSize) return s.AddUintXX(arch, v, arch.PtrSize)
} }
func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 {
@ -234,7 +234,7 @@ func (s *Symbol) AddRel() *Reloc {
return &s.R[len(s.R)-1] return &s.R[len(s.R)-1]
} }
func (s *Symbol) addUintXX(arch *sys.Arch, v uint64, wid int) int64 { func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 {
off := s.Size off := s.Size
s.setUintXX(arch, off, v, int64(wid)) s.setUintXX(arch, off, v, int64(wid))
return off return off
@ -263,3 +263,37 @@ func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64
return off + wid return off + wid
} }
type FuncInfo struct {
Args int32
Locals int32
Autom []Auto
Pcsp Pcdata
Pcfile Pcdata
Pcline Pcdata
Pcinline Pcdata
Pcdata []Pcdata
Funcdata []*Symbol
Funcdataoff []int64
File []*Symbol
InlTree []InlinedCall
}
// InlinedCall is a node in a local inlining tree (FuncInfo.InlTree).
type InlinedCall struct {
Parent int32 // index of parent in InlTree
File *Symbol // file of the inlined call
Line int32 // line number of the inlined call
Func *Symbol // function that was inlined
}
type Pcdata struct {
P []byte
}
type Auto struct {
Asym *Symbol
Gotype *Symbol
Aoffset int32
Name int16
}

View file

@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
package ld package sym
type Symbols struct { type Symbols struct {
symbolBatch []Symbol symbolBatch []Symbol
@ -39,7 +39,18 @@ type Symbols struct {
Allsym []*Symbol Allsym []*Symbol
} }
func (syms *Symbols) newsym(name string, v int) *Symbol { func NewSymbols() *Symbols {
return &Symbols{
hash: []map[string]*Symbol{
// preallocate about 2mb for hash of
// non static symbols
make(map[string]*Symbol, 100000),
},
Allsym: make([]*Symbol, 0, 100000),
}
}
func (syms *Symbols) Newsym(name string, v int) *Symbol {
batch := syms.symbolBatch batch := syms.symbolBatch
if len(batch) == 0 { if len(batch) == 0 {
batch = make([]Symbol, 1000) batch = make([]Symbol, 1000)
@ -65,7 +76,7 @@ func (syms *Symbols) Lookup(name string, v int) *Symbol {
if s != nil { if s != nil {
return s return s
} }
s = syms.newsym(name, v) s = syms.Newsym(name, v)
s.Extname = s.Name s.Extname = s.Name
m[name] = s m[name] = s
return s return s

View file

@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
package ld package sym
// A SymKind describes the kind of memory represented by a symbol. // A SymKind describes the kind of memory represented by a symbol.
type SymKind int16 type SymKind int16
@ -111,9 +111,9 @@ const (
SCONTAINER = SymKind(1 << 10) // has a sub-symbol SCONTAINER = SymKind(1 << 10) // has a sub-symbol
) )
// abiSymKindToSymKind maps values read from object files (which are // AbiSymKindToSymKind maps values read from object files (which are
// of type cmd/internal/objabi.SymKind) to values of type SymKind. // of type cmd/internal/objabi.SymKind) to values of type SymKind.
var abiSymKindToSymKind = [...]SymKind{ var AbiSymKindToSymKind = [...]SymKind{
Sxxx, Sxxx,
STEXT, STEXT,
SRODATA, SRODATA,
@ -127,10 +127,10 @@ var abiSymKindToSymKind = [...]SymKind{
SDWARFLOC, SDWARFLOC,
} }
// readOnly are the symbol kinds that form read-only sections. In some // ReadOnly are the symbol kinds that form read-only sections. In some
// cases, if they will require relocations, they are transformed into // cases, if they will require relocations, they are transformed into
// rel-ro sections using relROMap. // rel-ro sections using relROMap.
var readOnly = []SymKind{ var ReadOnly = []SymKind{
STYPE, STYPE,
SSTRING, SSTRING,
SGOSTRING, SGOSTRING,
@ -140,9 +140,9 @@ var readOnly = []SymKind{
SFUNCTAB, SFUNCTAB,
} }
// relROMap describes the transformation of read-only symbols to rel-ro // RelROMap describes the transformation of read-only symbols to rel-ro
// symbols. // symbols.
var relROMap = map[SymKind]SymKind{ var RelROMap = map[SymKind]SymKind{
STYPE: STYPERELRO, STYPE: STYPERELRO,
SSTRING: SSTRINGRELRO, SSTRING: SSTRINGRELRO,
SGOSTRING: SGOSTRINGRELRO, SGOSTRING: SGOSTRINGRELRO,

View file

@ -1,6 +1,6 @@
// Code generated by "stringer -type=SymKind"; DO NOT EDIT. // Code generated by "stringer -type=SymKind"; DO NOT EDIT.
package ld package sym
import "fmt" import "fmt"

View file

@ -34,12 +34,13 @@ import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/ld" "cmd/link/internal/ld"
"cmd/link/internal/sym"
"log" "log"
) )
// Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in. // Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in.
func addcall(ctxt *ld.Link, s *ld.Symbol, t *ld.Symbol) { func addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) {
s.Attr |= ld.AttrReachable s.Attr |= sym.AttrReachable
i := s.Size i := s.Size
s.Size += 4 s.Size += 4
s.Grow(s.Size) s.Grow(s.Size)
@ -67,7 +68,7 @@ func gentext(ctxt *ld.Link) {
} }
// Generate little thunks that load the PC of the next instruction into a register. // Generate little thunks that load the PC of the next instruction into a register.
thunks := make([]*ld.Symbol, 0, 7+len(ctxt.Textp)) thunks := make([]*sym.Symbol, 0, 7+len(ctxt.Textp))
for _, r := range [...]struct { for _, r := range [...]struct {
name string name string
num uint8 num uint8
@ -82,9 +83,9 @@ func gentext(ctxt *ld.Link) {
{"di", 7}, {"di", 7},
} { } {
thunkfunc := ctxt.Syms.Lookup("__x86.get_pc_thunk."+r.name, 0) thunkfunc := ctxt.Syms.Lookup("__x86.get_pc_thunk."+r.name, 0)
thunkfunc.Type = ld.STEXT thunkfunc.Type = sym.STEXT
thunkfunc.Attr |= ld.AttrLocal thunkfunc.Attr |= sym.AttrLocal
thunkfunc.Attr |= ld.AttrReachable //TODO: remove? thunkfunc.Attr |= sym.AttrReachable //TODO: remove?
o := func(op ...uint8) { o := func(op ...uint8) {
for _, op1 := range op { for _, op1 := range op {
thunkfunc.AddUint8(op1) thunkfunc.AddUint8(op1)
@ -101,18 +102,18 @@ func gentext(ctxt *ld.Link) {
ctxt.Textp = append(thunks, ctxt.Textp...) // keep Textp in dependency order ctxt.Textp = append(thunks, ctxt.Textp...) // keep Textp in dependency order
addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0) addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
if addmoduledata.Type == ld.STEXT && ld.Buildmode != ld.BuildmodePlugin { if addmoduledata.Type == sym.STEXT && ld.Buildmode != ld.BuildmodePlugin {
// we're linking a module containing the runtime -> no need for // we're linking a module containing the runtime -> no need for
// an init function // an init function
return return
} }
addmoduledata.Attr |= ld.AttrReachable addmoduledata.Attr |= sym.AttrReachable
initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
initfunc.Type = ld.STEXT initfunc.Type = sym.STEXT
initfunc.Attr |= ld.AttrLocal initfunc.Attr |= sym.AttrLocal
initfunc.Attr |= ld.AttrReachable initfunc.Attr |= sym.AttrReachable
o := func(op ...uint8) { o := func(op ...uint8) {
for _, op1 := range op { for _, op1 := range op {
initfunc.AddUint8(op1) initfunc.AddUint8(op1)
@ -159,28 +160,28 @@ func gentext(ctxt *ld.Link) {
} }
ctxt.Textp = append(ctxt.Textp, initfunc) ctxt.Textp = append(ctxt.Textp, initfunc)
initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable initarray_entry.Attr |= sym.AttrReachable
initarray_entry.Attr |= ld.AttrLocal initarray_entry.Attr |= sym.AttrLocal
initarray_entry.Type = ld.SINITARR initarray_entry.Type = sym.SINITARR
initarray_entry.AddAddr(ctxt.Arch, initfunc) initarray_entry.AddAddr(ctxt.Arch, initfunc)
} }
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
switch r.Type { switch r.Type {
default: default:
if r.Type >= 256 { if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, ld.RelocName(ctxt.Arch, r.Type)) ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
return false return false
} }
// Handle relocations found in ELF object files. // Handle relocations found in ELF object files.
case 256 + ld.R_386_PC32: case 256 + ld.R_386_PC32:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_386_PC32 relocation for dynamic symbol %s", targ.Name)
} }
if targ.Type == 0 || targ.Type == ld.SXREF { if targ.Type == 0 || targ.Type == sym.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name) ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
} }
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
@ -190,7 +191,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 256 + ld.R_386_PLT32: case 256 + ld.R_386_PLT32:
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Add += 4 r.Add += 4
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt) r.Add += int64(targ.Plt)
@ -199,7 +200,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_386_GOT32, 256 + ld.R_386_GOT32X: case 256 + ld.R_386_GOT32, 256 + ld.R_386_GOT32X:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
// have symbol // have symbol
if r.Off >= 2 && s.P[r.Off-2] == 0x8b { if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
// turn MOVL of GOT entry into LEAL of symbol address, relative to GOT. // turn MOVL of GOT entry into LEAL of symbol address, relative to GOT.
@ -240,7 +241,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 256 + ld.R_386_32: case 256 + ld.R_386_32:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected R_386_32 relocation for dynamic symbol %s", targ.Name)
} }
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
@ -248,13 +249,13 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0: case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 0:
r.Type = objabi.R_ADDR r.Type = objabi.R_ADDR
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name) ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
} }
return true return true
case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1: case 512 + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1:
if targ.Type == ld.SDYNIMPORT { if targ.Type == sym.SDYNIMPORT {
addpltsym(ctxt, targ) addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add = int64(targ.Plt) r.Add = int64(targ.Plt)
@ -266,7 +267,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case 512 + ld.MACHO_FAKE_GOTPCREL: case 512 + ld.MACHO_FAKE_GOTPCREL:
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
// have symbol // have symbol
// turn MOVL of GOT entry into LEAL of symbol itself // turn MOVL of GOT entry into LEAL of symbol itself
if r.Off < 2 || s.P[r.Off-2] != 0x8b { if r.Off < 2 || s.P[r.Off-2] != 0x8b {
@ -287,7 +288,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
} }
// Handle references to ELF symbols from our own object files. // Handle references to ELF symbols from our own object files.
if targ.Type != ld.SDYNIMPORT { if targ.Type != sym.SDYNIMPORT {
return true return true
} }
switch r.Type { switch r.Type {
@ -299,7 +300,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return true return true
case objabi.R_ADDR: case objabi.R_ADDR:
if s.Type != ld.SDATA { if s.Type != sym.SDATA {
break break
} }
if ld.Iself { if ld.Iself {
@ -326,7 +327,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
ld.Adddynsym(ctxt, targ) ld.Adddynsym(ctxt, targ)
got := ctxt.Syms.Lookup(".got", 0) got := ctxt.Syms.Lookup(".got", 0)
s.Type = got.Type | ld.SSUB s.Type = got.Type | sym.SSUB
s.Outer = got s.Outer = got
s.Sub = got.Sub s.Sub = got.Sub
got.Sub = s got.Sub = s
@ -341,7 +342,7 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
return false return false
} }
func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool { func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
ctxt.Out.Write32(uint32(sectoff)) ctxt.Out.Write32(uint32(sectoff))
elfsym := r.Xsym.ElfsymForReloc() elfsym := r.Xsym.ElfsymForReloc()
@ -366,7 +367,7 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
} }
case objabi.R_CALL: case objabi.R_CALL:
if r.Siz == 4 { if r.Siz == 4 {
if r.Xsym.Type == ld.SDYNIMPORT { if r.Xsym.Type == sym.SDYNIMPORT {
ctxt.Out.Write32(ld.R_386_PLT32 | uint32(elfsym)<<8) ctxt.Out.Write32(ld.R_386_PLT32 | uint32(elfsym)<<8)
} else { } else {
ctxt.Out.Write32(ld.R_386_PC32 | uint32(elfsym)<<8) ctxt.Out.Write32(ld.R_386_PC32 | uint32(elfsym)<<8)
@ -399,14 +400,14 @@ func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) bool {
return true return true
} }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
if rs.Type == ld.SHOSTOBJ { if rs.Type == sym.SHOSTOBJ {
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -415,7 +416,7 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
} else { } else {
v = uint32(rs.Sect.Extnum) v = uint32(rs.Sect.Extnum)
if v == 0 { if v == 0 {
ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
return false return false
} }
} }
@ -449,13 +450,13 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sect
return true return true
} }
func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff int64) bool { func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
if rs.Dynid < 0 { if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, ld.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type) ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
return false return false
} }
@ -482,7 +483,7 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *ld.Symbol, r *ld.Reloc, sectoff
return true return true
} }
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool {
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
return false return false
} }
@ -498,7 +499,7 @@ func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) bool {
return false return false
} }
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant") log.Fatalf("unexpected relocation variant")
return t return t
} }
@ -530,7 +531,7 @@ func elfsetupplt(ctxt *ld.Link) {
} }
} }
func addpltsym(ctxt *ld.Link, s *ld.Symbol) { func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Plt >= 0 { if s.Plt >= 0 {
return return
} }
@ -590,7 +591,7 @@ func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
} }
} }
func addgotsym(ctxt *ld.Link, s *ld.Symbol) { func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
if s.Got >= 0 { if s.Got >= 0 {
return return
} }