mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link: create Target in order to make relocsym threadsafe
In its current form, relocsym requires the Link context -- largely in a readonly state. Rather than passing around such heavy-weight object to the function, this CL separates out the link target. From here, the number of touchpoints (and thread unsafe portions) of relocing symbols can be mentally reasoned about. (NB: My personal intent is to make this more universal -- passing only the necessary variables/state to reloc functions. This is a taste to see if we like this form.) Change-Id: Id9177d03267fedf0bb572a9d61bc07b64309c3b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/220837 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
99eb14a7f4
commit
e9056a6a73
5 changed files with 168 additions and 72 deletions
|
|
@ -127,7 +127,7 @@ func trampoline(ctxt *Link, s *sym.Symbol) {
|
||||||
//
|
//
|
||||||
// This is a performance-critical function for the linker; be careful
|
// This is a performance-critical function for the linker; be careful
|
||||||
// to avoid introducing unnecessary allocations in the main loop.
|
// to avoid introducing unnecessary allocations in the main loop.
|
||||||
func relocsym(ctxt *Link, s *sym.Symbol) {
|
func relocsym(ctxt *Link, target *Target, s *sym.Symbol) {
|
||||||
if len(s.R) == 0 {
|
if len(s.R) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -158,8 +158,8 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
if r.Sym != nil && ((r.Sym.Type == sym.Sxxx && !r.Sym.Attr.VisibilityHidden()) || r.Sym.Type == sym.SXREF) {
|
if r.Sym != nil && ((r.Sym.Type == sym.Sxxx && !r.Sym.Attr.VisibilityHidden()) || r.Sym.Type == sym.SXREF) {
|
||||||
// When putting the runtime but not main into a shared library
|
// When putting the runtime but not main into a shared library
|
||||||
// these symbols are undefined and that's OK.
|
// these symbols are undefined and that's OK.
|
||||||
if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin {
|
if target.IsShared() || target.IsPlugin() {
|
||||||
if r.Sym.Name == "main.main" || (ctxt.BuildMode != BuildModePlugin && r.Sym.Name == "main..inittask") {
|
if r.Sym.Name == "main.main" || (!target.IsPlugin() && r.Sym.Name == "main..inittask") {
|
||||||
r.Sym.Type = sym.SDYNIMPORT
|
r.Sym.Type = sym.SDYNIMPORT
|
||||||
} else if strings.HasPrefix(r.Sym.Name, "go.info.") {
|
} else if strings.HasPrefix(r.Sym.Name, "go.info.") {
|
||||||
// Skip go.info symbols. They are only needed to communicate
|
// Skip go.info symbols. They are only needed to communicate
|
||||||
|
|
@ -181,21 +181,21 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
|
|
||||||
// We need to be able to reference dynimport symbols when linking against
|
// We need to be able to reference dynimport symbols when linking against
|
||||||
// shared libraries, and Solaris, Darwin and AIX need it always
|
// shared libraries, and Solaris, Darwin and AIX need it always
|
||||||
if ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Haix && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
|
if !target.IsSolaris() && !target.IsDarwin() && !target.IsAIX() && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !target.IsDynlinkingGo() && !r.Sym.Attr.SubSymbol() {
|
||||||
if !(ctxt.Arch.Family == sys.PPC64 && ctxt.LinkMode == LinkExternal && r.Sym.Name == ".TOC.") {
|
if !(target.IsPPC64() && target.IsExternal() && r.Sym.Name == ".TOC.") {
|
||||||
Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(target.Arch, r.Type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r.Sym != nil && r.Sym.Type != sym.STLSBSS && r.Type != objabi.R_WEAKADDROFF && !r.Sym.Attr.Reachable() {
|
if r.Sym != nil && r.Sym.Type != sym.STLSBSS && r.Type != objabi.R_WEAKADDROFF && !r.Sym.Attr.Reachable() {
|
||||||
Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
|
Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.LinkMode == LinkExternal {
|
if target.IsExternal() {
|
||||||
r.InitExt()
|
r.InitExt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mundaym): remove this special case - see issue 14218.
|
// TODO(mundaym): remove this special case - see issue 14218.
|
||||||
if ctxt.Arch.Family == sys.S390X {
|
if target.IsS390X() {
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case objabi.R_PCRELDBL:
|
case objabi.R_PCRELDBL:
|
||||||
r.InitExt()
|
r.InitExt()
|
||||||
|
|
@ -216,19 +216,19 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
case 1:
|
case 1:
|
||||||
o = int64(s.P[off])
|
o = int64(s.P[off])
|
||||||
case 2:
|
case 2:
|
||||||
o = int64(ctxt.Arch.ByteOrder.Uint16(s.P[off:]))
|
o = int64(target.Arch.ByteOrder.Uint16(s.P[off:]))
|
||||||
case 4:
|
case 4:
|
||||||
o = int64(ctxt.Arch.ByteOrder.Uint32(s.P[off:]))
|
o = int64(target.Arch.ByteOrder.Uint32(s.P[off:]))
|
||||||
case 8:
|
case 8:
|
||||||
o = int64(ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
|
o = int64(target.Arch.ByteOrder.Uint64(s.P[off:]))
|
||||||
}
|
}
|
||||||
if offset, ok := thearch.Archreloc(ctxt, r, s, o); ok {
|
if offset, ok := thearch.Archreloc(ctxt, r, s, o); ok {
|
||||||
o = offset
|
o = offset
|
||||||
} else {
|
} else {
|
||||||
Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(ctxt.Arch, r.Type))
|
Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(target.Arch, r.Type))
|
||||||
}
|
}
|
||||||
case objabi.R_TLS_LE:
|
case objabi.R_TLS_LE:
|
||||||
if ctxt.LinkMode == LinkExternal && ctxt.IsELF {
|
if target.IsExternal() && target.IsElf() {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
if r.Sym == nil {
|
if r.Sym == nil {
|
||||||
r.Sym = ctxt.Tlsg
|
r.Sym = ctxt.Tlsg
|
||||||
|
|
@ -236,13 +236,13 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
o = 0
|
o = 0
|
||||||
if ctxt.Arch.Family != sys.AMD64 {
|
if !target.IsAMD64() {
|
||||||
o = r.Add
|
o = r.Add
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.IsELF && ctxt.Arch.Family == sys.ARM {
|
if target.IsElf() && target.IsARM() {
|
||||||
// On ELF ARM, the thread pointer is 8 bytes before
|
// On ELF ARM, the thread pointer is 8 bytes before
|
||||||
// the start of the thread-local data block, so add 8
|
// the start of the thread-local data block, so add 8
|
||||||
// to the actual TLS offset (r->sym->value).
|
// to the actual TLS offset (r->sym->value).
|
||||||
|
|
@ -251,15 +251,15 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// related to the fact that our own TLS storage happens
|
// related to the fact that our own TLS storage happens
|
||||||
// to take up 8 bytes.
|
// to take up 8 bytes.
|
||||||
o = 8 + r.Sym.Value
|
o = 8 + r.Sym.Value
|
||||||
} else if ctxt.IsELF || ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hdarwin {
|
} else if target.IsElf() || target.IsPlan9() || target.IsDarwin() {
|
||||||
o = int64(ctxt.Tlsoffset) + r.Add
|
o = int64(ctxt.Tlsoffset) + r.Add
|
||||||
} else if ctxt.HeadType == objabi.Hwindows {
|
} else if target.IsWindows() {
|
||||||
o = r.Add
|
o = r.Add
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("unexpected R_TLS_LE relocation for %v", ctxt.HeadType)
|
log.Fatalf("unexpected R_TLS_LE relocation for %v", target.HeadType)
|
||||||
}
|
}
|
||||||
case objabi.R_TLS_IE:
|
case objabi.R_TLS_IE:
|
||||||
if ctxt.LinkMode == LinkExternal && ctxt.IsELF {
|
if target.IsExternal() && target.IsElf() {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
if r.Sym == nil {
|
if r.Sym == nil {
|
||||||
r.Sym = ctxt.Tlsg
|
r.Sym = ctxt.Tlsg
|
||||||
|
|
@ -267,16 +267,16 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
o = 0
|
o = 0
|
||||||
if ctxt.Arch.Family != sys.AMD64 {
|
if !target.IsAMD64() {
|
||||||
o = r.Add
|
o = r.Add
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if ctxt.BuildMode == BuildModePIE && ctxt.IsELF {
|
if target.IsPIE() && target.IsElf() {
|
||||||
// We are linking the final executable, so we
|
// We are linking the final executable, so we
|
||||||
// can optimize any TLS IE relocation to LE.
|
// can optimize any TLS IE relocation to LE.
|
||||||
if thearch.TLSIEtoLE == nil {
|
if thearch.TLSIEtoLE == nil {
|
||||||
log.Fatalf("internal linking of TLS IE not supported on %v", ctxt.Arch.Family)
|
log.Fatalf("internal linking of TLS IE not supported on %v", target.Arch.Family)
|
||||||
}
|
}
|
||||||
thearch.TLSIEtoLE(s, int(off), int(r.Siz))
|
thearch.TLSIEtoLE(s, int(off), int(r.Siz))
|
||||||
o = int64(ctxt.Tlsoffset)
|
o = int64(ctxt.Tlsoffset)
|
||||||
|
|
@ -287,7 +287,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", s.Name)
|
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", s.Name)
|
||||||
}
|
}
|
||||||
case objabi.R_ADDR:
|
case objabi.R_ADDR:
|
||||||
if ctxt.LinkMode == LinkExternal && r.Sym.Type != sym.SCONST {
|
if target.IsExternal() && r.Sym.Type != sym.SCONST {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
|
|
||||||
// set up addend for eventual relocation via outer symbol.
|
// set up addend for eventual relocation via outer symbol.
|
||||||
|
|
@ -305,20 +305,20 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
r.Xsym = rs
|
r.Xsym = rs
|
||||||
|
|
||||||
o = r.Xadd
|
o = r.Xadd
|
||||||
if ctxt.IsELF {
|
if target.IsElf() {
|
||||||
if ctxt.Arch.Family == sys.AMD64 {
|
if target.IsAMD64() {
|
||||||
o = 0
|
o = 0
|
||||||
}
|
}
|
||||||
} else if ctxt.HeadType == objabi.Hdarwin {
|
} else if target.IsDarwin() {
|
||||||
if rs.Type != sym.SHOSTOBJ {
|
if rs.Type != sym.SHOSTOBJ {
|
||||||
o += Symaddr(rs)
|
o += Symaddr(rs)
|
||||||
}
|
}
|
||||||
} else if ctxt.HeadType == objabi.Hwindows {
|
} else if target.IsWindows() {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
} else if ctxt.HeadType == objabi.Haix {
|
} else if target.IsAIX() {
|
||||||
o = Symaddr(r.Sym) + r.Add
|
o = Symaddr(r.Sym) + r.Add
|
||||||
} else {
|
} else {
|
||||||
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.HeadType)
|
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
@ -328,7 +328,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// as section addresses can change once loaded.
|
// as section addresses can change once loaded.
|
||||||
// The "default" symbol address is still needed by the loader so
|
// The "default" symbol address is still needed by the loader so
|
||||||
// the current relocation can't be skipped.
|
// the current relocation can't be skipped.
|
||||||
if ctxt.HeadType == objabi.Haix && r.Sym.Type != sym.SDYNIMPORT {
|
if target.IsAIX() && r.Sym.Type != sym.SDYNIMPORT {
|
||||||
// It's not possible to make a loader relocation in a
|
// It's not possible to make a loader relocation in a
|
||||||
// symbol which is not inside .data section.
|
// symbol which is not inside .data section.
|
||||||
// FIXME: It should be forbidden to have R_ADDR from a
|
// FIXME: It should be forbidden to have R_ADDR from a
|
||||||
|
|
@ -346,7 +346,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// fail at runtime. See https://golang.org/issue/7980.
|
// fail at runtime. See https://golang.org/issue/7980.
|
||||||
// Instead of special casing only amd64, we treat this as an error on all
|
// Instead of special casing only amd64, we treat this as an error on all
|
||||||
// 64-bit architectures so as to be future-proof.
|
// 64-bit architectures so as to be future-proof.
|
||||||
if int32(o) < 0 && ctxt.Arch.PtrSize > 4 && siz == 4 {
|
if int32(o) < 0 && target.Arch.PtrSize > 4 && siz == 4 {
|
||||||
Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", r.Sym.Name, uint64(o), Symaddr(r.Sym), r.Add)
|
Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", r.Sym.Name, uint64(o), Symaddr(r.Sym), r.Add)
|
||||||
errorexit()
|
errorexit()
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +355,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
|
Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.LinkMode == LinkExternal {
|
if target.IsExternal() {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
|
|
||||||
// On most platforms, the external linker needs to adjust DWARF references
|
// On most platforms, the external linker needs to adjust DWARF references
|
||||||
|
|
@ -363,7 +363,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// DWARF linking, and it understands how to follow section offsets.
|
// DWARF linking, and it understands how to follow section offsets.
|
||||||
// Leaving in the relocation records confuses it (see
|
// Leaving in the relocation records confuses it (see
|
||||||
// https://golang.org/issue/22068) so drop them for Darwin.
|
// https://golang.org/issue/22068) so drop them for Darwin.
|
||||||
if ctxt.HeadType == objabi.Hdarwin {
|
if target.IsDarwin() {
|
||||||
r.Done = true
|
r.Done = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,7 +372,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
// IMAGE_REL_I386_DIR32, IMAGE_REL_AMD64_ADDR64 and IMAGE_REL_AMD64_ADDR32.
|
// IMAGE_REL_I386_DIR32, IMAGE_REL_AMD64_ADDR64 and IMAGE_REL_AMD64_ADDR32.
|
||||||
// Do not replace R_DWARFSECREF with R_ADDR for windows -
|
// Do not replace R_DWARFSECREF with R_ADDR for windows -
|
||||||
// let PE code emit correct relocations.
|
// let PE code emit correct relocations.
|
||||||
if ctxt.HeadType != objabi.Hwindows {
|
if !target.IsWindows() {
|
||||||
r.Type = objabi.R_ADDR
|
r.Type = objabi.R_ADDR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,7 +380,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
|
r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
|
||||||
|
|
||||||
o = r.Xadd
|
o = r.Xadd
|
||||||
if ctxt.IsELF && ctxt.Arch.Family == sys.AMD64 {
|
if target.IsElf() && target.IsAMD64() {
|
||||||
o = 0
|
o = 0
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -407,7 +407,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
|
|
||||||
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
|
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
|
||||||
case objabi.R_GOTPCREL:
|
case objabi.R_GOTPCREL:
|
||||||
if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin && r.Sym != nil && r.Sym.Type != sym.SCONST {
|
if target.IsDynlinkingGo() && target.IsDarwin() && r.Sym != nil && r.Sym.Type != sym.SCONST {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xadd = r.Add
|
r.Xadd = r.Add
|
||||||
r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
|
r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
|
||||||
|
|
@ -419,18 +419,18 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case objabi.R_CALL, objabi.R_PCREL:
|
case objabi.R_CALL, objabi.R_PCREL:
|
||||||
if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
|
if target.IsExternal() && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
|
||||||
// pass through to the external linker.
|
// pass through to the external linker.
|
||||||
r.Done = false
|
r.Done = false
|
||||||
r.Xadd = 0
|
r.Xadd = 0
|
||||||
if ctxt.IsELF {
|
if target.IsElf() {
|
||||||
r.Xadd -= int64(r.Siz)
|
r.Xadd -= int64(r.Siz)
|
||||||
}
|
}
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
o = 0
|
o = 0
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
|
if target.IsExternal() && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
|
||||||
r.Done = false
|
r.Done = false
|
||||||
|
|
||||||
// set up addend for eventual relocation via outer symbol.
|
// set up addend for eventual relocation via outer symbol.
|
||||||
|
|
@ -449,14 +449,14 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
r.Xsym = rs
|
r.Xsym = rs
|
||||||
|
|
||||||
o = r.Xadd
|
o = r.Xadd
|
||||||
if ctxt.IsELF {
|
if target.IsElf() {
|
||||||
if ctxt.Arch.Family == sys.AMD64 {
|
if target.IsAMD64() {
|
||||||
o = 0
|
o = 0
|
||||||
}
|
}
|
||||||
} else if ctxt.HeadType == objabi.Hdarwin {
|
} else if target.IsDarwin() {
|
||||||
if r.Type == objabi.R_CALL {
|
if r.Type == objabi.R_CALL {
|
||||||
if ctxt.LinkMode == LinkExternal && rs.Type == sym.SDYNIMPORT {
|
if target.IsExternal() && rs.Type == sym.SDYNIMPORT {
|
||||||
switch ctxt.Arch.Family {
|
switch target.Arch.Family {
|
||||||
case sys.AMD64:
|
case sys.AMD64:
|
||||||
// AMD64 dynamic relocations are relative to the end of the relocation.
|
// AMD64 dynamic relocations are relative to the end of the relocation.
|
||||||
o += int64(r.Siz)
|
o += int64(r.Siz)
|
||||||
|
|
@ -471,18 +471,18 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
}
|
}
|
||||||
o -= int64(r.Off) // relative to section offset, not symbol
|
o -= int64(r.Off) // relative to section offset, not symbol
|
||||||
}
|
}
|
||||||
} else if ctxt.Arch.Family == sys.ARM {
|
} else if target.IsARM() {
|
||||||
// see ../arm/asm.go:/machoreloc1
|
// see ../arm/asm.go:/machoreloc1
|
||||||
o += Symaddr(rs) - s.Value - int64(r.Off)
|
o += Symaddr(rs) - s.Value - int64(r.Off)
|
||||||
} else {
|
} else {
|
||||||
o += int64(r.Siz)
|
o += int64(r.Siz)
|
||||||
}
|
}
|
||||||
} else if ctxt.HeadType == objabi.Hwindows && ctxt.Arch.Family == sys.AMD64 { // only amd64 needs PCREL
|
} else if target.IsWindows() && target.IsAMD64() { // only amd64 needs PCREL
|
||||||
// PE/COFF's PC32 relocation uses the address after the relocated
|
// PE/COFF's PC32 relocation uses the address after the relocated
|
||||||
// bytes as the base. Compensate by skewing the addend.
|
// bytes as the base. Compensate by skewing the addend.
|
||||||
o += int64(r.Siz)
|
o += int64(r.Siz)
|
||||||
} else {
|
} else {
|
||||||
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.HeadType)
|
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
@ -498,10 +498,10 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
o = r.Sym.Size + r.Add
|
o = r.Sym.Size + r.Add
|
||||||
|
|
||||||
case objabi.R_XCOFFREF:
|
case objabi.R_XCOFFREF:
|
||||||
if ctxt.HeadType != objabi.Haix {
|
if !target.IsAIX() {
|
||||||
Errorf(s, "find XCOFF R_REF on non-XCOFF files")
|
Errorf(s, "find XCOFF R_REF on non-XCOFF files")
|
||||||
}
|
}
|
||||||
if ctxt.LinkMode != LinkExternal {
|
if !target.IsExternal() {
|
||||||
Errorf(s, "find XCOFF R_REF with internal linking")
|
Errorf(s, "find XCOFF R_REF with internal linking")
|
||||||
}
|
}
|
||||||
r.Xsym = r.Sym
|
r.Xsym = r.Sym
|
||||||
|
|
@ -517,7 +517,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
o = r.Add
|
o = r.Add
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.Arch.Family == sys.PPC64 || ctxt.Arch.Family == sys.S390X {
|
if target.IsPPC64() || target.IsS390X() {
|
||||||
r.InitExt()
|
r.InitExt()
|
||||||
if r.Variant != sym.RV_NONE {
|
if r.Variant != sym.RV_NONE {
|
||||||
o = thearch.Archrelocvariant(ctxt, r, s, o)
|
o = thearch.Archrelocvariant(ctxt, r, s, o)
|
||||||
|
|
@ -535,7 +535,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
if r.Xsym != nil {
|
if r.Xsym != nil {
|
||||||
xnam = r.Xsym.Name
|
xnam = r.Xsym.Name
|
||||||
}
|
}
|
||||||
fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x (xsym: %s +%#x) [type %d (%s)/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, addr, r.Add, xnam, r.Xadd, r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Variant, o)
|
fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x (xsym: %s +%#x) [type %d (%s)/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, addr, r.Add, xnam, r.Xadd, r.Type, sym.RelocName(target.Arch, r.Type), r.Variant, o)
|
||||||
}
|
}
|
||||||
switch siz {
|
switch siz {
|
||||||
default:
|
default:
|
||||||
|
|
@ -550,7 +550,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
Errorf(s, "relocation address for %s is too big: %#x", r.Sym.Name, o)
|
Errorf(s, "relocation address for %s is too big: %#x", r.Sym.Name, o)
|
||||||
}
|
}
|
||||||
i16 := int16(o)
|
i16 := int16(o)
|
||||||
ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))
|
target.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))
|
||||||
case 4:
|
case 4:
|
||||||
if r.Type == objabi.R_PCREL || r.Type == objabi.R_CALL {
|
if r.Type == objabi.R_PCREL || r.Type == objabi.R_CALL {
|
||||||
if o != int64(int32(o)) {
|
if o != int64(int32(o)) {
|
||||||
|
|
@ -563,22 +563,22 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fl := int32(o)
|
fl := int32(o)
|
||||||
ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
|
target.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
|
||||||
case 8:
|
case 8:
|
||||||
ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
|
target.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctxt *Link) reloc() {
|
func (ctxt *Link) reloc() {
|
||||||
for _, s := range ctxt.Textp {
|
for _, s := range ctxt.Textp {
|
||||||
relocsym(ctxt, s)
|
relocsym(ctxt, &ctxt.Target, s)
|
||||||
}
|
}
|
||||||
for _, s := range datap {
|
for _, s := range datap {
|
||||||
relocsym(ctxt, s)
|
relocsym(ctxt, &ctxt.Target, s)
|
||||||
}
|
}
|
||||||
for _, s := range dwarfp {
|
for _, s := range dwarfp {
|
||||||
relocsym(ctxt, s)
|
relocsym(ctxt, &ctxt.Target, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2443,6 +2443,8 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
|
||||||
binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
|
binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
|
||||||
buf.Write(sizeBytes[:])
|
buf.Write(sizeBytes[:])
|
||||||
|
|
||||||
|
var relocbuf []byte // temporary buffer for applying relocations
|
||||||
|
|
||||||
// Using zlib.BestSpeed achieves very nearly the same
|
// Using zlib.BestSpeed achieves very nearly the same
|
||||||
// compression levels of zlib.DefaultCompression, but takes
|
// compression levels of zlib.DefaultCompression, but takes
|
||||||
// substantially less time. This is important because DWARF
|
// substantially less time. This is important because DWARF
|
||||||
|
|
@ -2457,11 +2459,11 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
|
||||||
oldP := s.P
|
oldP := s.P
|
||||||
wasReadOnly := s.Attr.ReadOnly()
|
wasReadOnly := s.Attr.ReadOnly()
|
||||||
if len(s.R) != 0 && wasReadOnly {
|
if len(s.R) != 0 && wasReadOnly {
|
||||||
ctxt.relocbuf = append(ctxt.relocbuf[:0], s.P...)
|
relocbuf = append(relocbuf[:0], s.P...)
|
||||||
s.P = ctxt.relocbuf
|
s.P = relocbuf
|
||||||
s.Attr.Set(sym.AttrReadOnly, false)
|
s.Attr.Set(sym.AttrReadOnly, false)
|
||||||
}
|
}
|
||||||
relocsym(ctxt, s)
|
relocsym(ctxt, &ctxt.Target, s)
|
||||||
if _, err := z.Write(s.P); err != nil {
|
if _, err := z.Write(s.P); err != nil {
|
||||||
log.Fatalf("compression failed: %s", err)
|
log.Fatalf("compression failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1752,7 +1752,6 @@ func dwarfcompress(ctxt *Link) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dwarfp = newDwarfp
|
dwarfp = newDwarfp
|
||||||
ctxt.relocbuf = nil // no longer needed, don't hold it live
|
|
||||||
|
|
||||||
// Re-compute the locations of the compressed DWARF symbols
|
// Re-compute the locations of the compressed DWARF symbols
|
||||||
// and sections, since the layout of these within the file is
|
// and sections, since the layout of these within the file is
|
||||||
|
|
|
||||||
|
|
@ -51,23 +51,16 @@ type Shlib struct {
|
||||||
// Link holds the context for writing object code from a compiler
|
// Link holds the context for writing object code from a compiler
|
||||||
// or for reading that input into the linker.
|
// or for reading that input into the linker.
|
||||||
type Link struct {
|
type Link struct {
|
||||||
|
Target
|
||||||
Out *OutBuf
|
Out *OutBuf
|
||||||
|
|
||||||
Syms *sym.Symbols
|
Syms *sym.Symbols
|
||||||
|
|
||||||
Arch *sys.Arch
|
|
||||||
Debugvlog int
|
Debugvlog int
|
||||||
Bso *bufio.Writer
|
Bso *bufio.Writer
|
||||||
|
|
||||||
Loaded bool // set after all inputs have been loaded as symbols
|
Loaded bool // set after all inputs have been loaded as symbols
|
||||||
|
|
||||||
IsELF bool
|
|
||||||
HeadType objabi.HeadType
|
|
||||||
|
|
||||||
linkShared bool // link against installed Go shared libraries
|
|
||||||
LinkMode LinkMode
|
|
||||||
BuildMode BuildMode
|
|
||||||
canUsePlugins bool // initialized when Loaded is set to true
|
|
||||||
compressDWARF bool
|
compressDWARF bool
|
||||||
|
|
||||||
Tlsg *sym.Symbol
|
Tlsg *sym.Symbol
|
||||||
|
|
@ -98,8 +91,6 @@ type Link struct {
|
||||||
compUnits []*sym.CompilationUnit // DWARF compilation units
|
compUnits []*sym.CompilationUnit // DWARF compilation units
|
||||||
runtimeCU *sym.CompilationUnit // One of the runtime CUs, the last one seen.
|
runtimeCU *sym.CompilationUnit // One of the runtime CUs, the last one seen.
|
||||||
|
|
||||||
relocbuf []byte // temporary buffer for applying relocations
|
|
||||||
|
|
||||||
loader *loader.Loader
|
loader *loader.Loader
|
||||||
cgodata []cgodata // cgo directives to load, three strings are args for loadcgo
|
cgodata []cgodata // cgo directives to load, three strings are args for loadcgo
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ import (
|
||||||
|
|
||||||
func linknew(arch *sys.Arch) *Link {
|
func linknew(arch *sys.Arch) *Link {
|
||||||
ctxt := &Link{
|
ctxt := &Link{
|
||||||
|
Target: Target{Arch: arch},
|
||||||
Syms: sym.NewSymbols(),
|
Syms: sym.NewSymbols(),
|
||||||
Out: &OutBuf{arch: arch},
|
Out: &OutBuf{arch: arch},
|
||||||
Arch: arch,
|
|
||||||
LibraryByPkg: make(map[string]*sym.Library),
|
LibraryByPkg: make(map[string]*sym.Library),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
104
src/cmd/link/internal/ld/target.go
Normal file
104
src/cmd/link/internal/ld/target.go
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
// Copyright 2020 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 ld
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/internal/objabi"
|
||||||
|
"cmd/internal/sys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Target holds the configuration we're building for.
|
||||||
|
type Target struct {
|
||||||
|
Arch *sys.Arch
|
||||||
|
|
||||||
|
HeadType objabi.HeadType
|
||||||
|
|
||||||
|
LinkMode LinkMode
|
||||||
|
BuildMode BuildMode
|
||||||
|
|
||||||
|
linkShared bool
|
||||||
|
canUsePlugins bool
|
||||||
|
IsELF bool
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Target type functions
|
||||||
|
//
|
||||||
|
|
||||||
|
func (t *Target) IsShared() bool {
|
||||||
|
return t.BuildMode == BuildModeShared
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsPlugin() bool {
|
||||||
|
return t.BuildMode == BuildModePlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsExternal() bool {
|
||||||
|
return t.LinkMode == LinkExternal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsPIE() bool {
|
||||||
|
return t.BuildMode == BuildModePIE
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsSharedGoLink() bool {
|
||||||
|
return t.linkShared
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) CanUsePlugins() bool {
|
||||||
|
return t.canUsePlugins
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsElf() bool {
|
||||||
|
return t.IsELF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsDynlinkingGo() bool {
|
||||||
|
return t.IsShared() || t.IsSharedGoLink() || t.IsPlugin() || t.CanUsePlugins()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Processor functions
|
||||||
|
//
|
||||||
|
|
||||||
|
func (t *Target) IsARM() bool {
|
||||||
|
return t.Arch.Family == sys.ARM
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsAMD64() bool {
|
||||||
|
return t.Arch.Family == sys.AMD64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsPPC64() bool {
|
||||||
|
return t.Arch.Family == sys.PPC64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsS390X() bool {
|
||||||
|
return t.Arch.Family == sys.S390X
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// OS Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
func (t *Target) IsDarwin() bool {
|
||||||
|
return t.HeadType == objabi.Hdarwin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsWindows() bool {
|
||||||
|
return t.HeadType == objabi.Hwindows
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsPlan9() bool {
|
||||||
|
return t.HeadType == objabi.Hplan9
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsAIX() bool {
|
||||||
|
return t.HeadType == objabi.Haix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Target) IsSolaris() bool {
|
||||||
|
return t.HeadType == objabi.Hsolaris
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue