mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link: support external linking in new reloc implementation
Support external linking for the new reloc pass as well, and enable it on AMD64 and 386. Change-Id: Ia71aec3d7c14e9d661e0748d2e988f29f220d1e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/230308 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jeremy Faller <jeremy@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
9a3bf7d542
commit
095d2a4532
3 changed files with 247 additions and 171 deletions
|
|
@ -120,6 +120,20 @@ func trampoline(ctxt *Link, s loader.Sym) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// foldSubSymbolOffset computes the offset of symbol s to its top-level outer
|
||||||
|
// symbol. Returns the top-level symbol and the offset.
|
||||||
|
// This is used in generating external relocations.
|
||||||
|
func foldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) {
|
||||||
|
outer := ldr.OuterSym(s)
|
||||||
|
off := int64(0)
|
||||||
|
for outer != 0 {
|
||||||
|
off += ldr.SymValue(s) - ldr.SymValue(outer)
|
||||||
|
s = outer
|
||||||
|
outer = ldr.OuterSym(s)
|
||||||
|
}
|
||||||
|
return s, off
|
||||||
|
}
|
||||||
|
|
||||||
// relocsym resolve relocations in "s", updating the symbol's content
|
// relocsym resolve relocations in "s", updating the symbol's content
|
||||||
// in "P".
|
// in "P".
|
||||||
// The main loop walks through the list of relocations attached to "s"
|
// The main loop walks through the list of relocations attached to "s"
|
||||||
|
|
@ -141,6 +155,7 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
if relocs.Count() == 0 {
|
if relocs.Count() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var extRelocs []loader.ExtReloc
|
||||||
for ri := 0; ri < relocs.Count(); ri++ {
|
for ri := 0; ri < relocs.Count(); ri++ {
|
||||||
r := relocs.At2(ri)
|
r := relocs.At2(ri)
|
||||||
off := r.Off()
|
off := r.Off()
|
||||||
|
|
@ -200,9 +215,14 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
|
err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rr loader.ExtReloc
|
||||||
|
needExtReloc := false // will set to true below in case it is needed
|
||||||
if target.IsExternal() {
|
if target.IsExternal() {
|
||||||
panic("external linking not implemented")
|
rr.Sym = rs
|
||||||
//r.InitExt()
|
rr.Type = rt
|
||||||
|
rr.Off = off
|
||||||
|
rr.Siz = uint8(siz)
|
||||||
|
rr.Add = r.Add()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mundaym): remove this special case - see issue 14218.
|
// TODO(mundaym): remove this special case - see issue 14218.
|
||||||
|
|
@ -239,19 +259,19 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
err.Errorf(s, "unknown reloc to %v: %d (%s)", ldr.SymName(rs), rt, sym.RelocName(target.Arch, rt))
|
err.Errorf(s, "unknown reloc to %v: %d (%s)", ldr.SymName(rs), rt, sym.RelocName(target.Arch, rt))
|
||||||
}
|
}
|
||||||
case objabi.R_TLS_LE:
|
case objabi.R_TLS_LE:
|
||||||
//if target.IsExternal() && target.IsElf() {
|
if target.IsExternal() && target.IsElf() {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
// if r.Sym == nil {
|
if rr.Sym == 0 {
|
||||||
// r.Sym = syms.Tlsg
|
rr.Sym = syms.Tlsg2
|
||||||
// }
|
}
|
||||||
// r.Xsym = r.Sym
|
rr.Xsym = rr.Sym
|
||||||
// r.Xadd = r.Add
|
rr.Xadd = rr.Add
|
||||||
// o = 0
|
o = 0
|
||||||
// if !target.IsAMD64() {
|
if !target.IsAMD64() {
|
||||||
// o = r.Add
|
o = rr.Add
|
||||||
// }
|
}
|
||||||
// break
|
break
|
||||||
//}
|
}
|
||||||
|
|
||||||
if target.IsElf() && target.IsARM() {
|
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
|
||||||
|
|
@ -270,19 +290,19 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
log.Fatalf("unexpected R_TLS_LE relocation for %v", target.HeadType)
|
log.Fatalf("unexpected R_TLS_LE relocation for %v", target.HeadType)
|
||||||
}
|
}
|
||||||
case objabi.R_TLS_IE:
|
case objabi.R_TLS_IE:
|
||||||
//if target.IsExternal() && target.IsElf() {
|
if target.IsExternal() && target.IsElf() {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
// if r.Sym == nil {
|
if rr.Sym == 0 {
|
||||||
// r.Sym = syms.Tlsg
|
rr.Sym = syms.Tlsg2
|
||||||
// }
|
}
|
||||||
// r.Xsym = r.Sym
|
rr.Xsym = rr.Sym
|
||||||
// r.Xadd = r.Add
|
rr.Xadd = rr.Add
|
||||||
// o = 0
|
o = 0
|
||||||
// if !target.IsAMD64() {
|
if !target.IsAMD64() {
|
||||||
// o = r.Add
|
o = rr.Add
|
||||||
// }
|
}
|
||||||
// break
|
break
|
||||||
//}
|
}
|
||||||
if target.IsPIE() && target.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.
|
||||||
|
|
@ -295,42 +315,38 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
|
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
|
||||||
}
|
}
|
||||||
case objabi.R_ADDR:
|
case objabi.R_ADDR:
|
||||||
//if target.IsExternal() && r.Sym.Type != sym.SCONST {
|
if target.IsExternal() && rst != sym.SCONST {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
//
|
|
||||||
// // set up addend for eventual relocation via outer symbol.
|
// set up addend for eventual relocation via outer symbol.
|
||||||
// rs := r.Sym
|
rs := rs
|
||||||
//
|
rs, off := foldSubSymbolOffset(ldr, rs)
|
||||||
// r.Xadd = r.Add
|
rr.Xadd = rr.Add + off
|
||||||
// for rs.Outer != nil {
|
rst := ldr.SymType(rs)
|
||||||
// r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
|
if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
|
||||||
// rs = rs.Outer
|
err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
|
||||||
// }
|
}
|
||||||
//
|
rr.Xsym = rs
|
||||||
// if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
|
|
||||||
// Errorf(s, "missing section for relocation target %s", rs.Name)
|
o = rr.Xadd
|
||||||
// }
|
if target.IsElf() {
|
||||||
// r.Xsym = rs
|
if target.IsAMD64() {
|
||||||
//
|
o = 0
|
||||||
// o = r.Xadd
|
}
|
||||||
// if target.IsElf() {
|
} else if target.IsDarwin() {
|
||||||
// if target.IsAMD64() {
|
if ldr.SymType(rs) != sym.SHOSTOBJ {
|
||||||
// o = 0
|
o += ldr.SymValue(rs)
|
||||||
// }
|
}
|
||||||
// } else if target.IsDarwin() {
|
} else if target.IsWindows() {
|
||||||
// if rs.Type != sym.SHOSTOBJ {
|
// nothing to do
|
||||||
// o += Symaddr(rs)
|
} else if target.IsAIX() {
|
||||||
// }
|
o = ldr.SymValue(rr.Sym) + rr.Add
|
||||||
// } else if target.IsWindows() {
|
} else {
|
||||||
// // nothing to do
|
err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
|
||||||
// } else if target.IsAIX() {
|
}
|
||||||
// o = Symaddr(r.Sym) + r.Add
|
|
||||||
// } else {
|
break
|
||||||
// Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
|
|
||||||
// On AIX, a second relocation must be done by the loader,
|
// On AIX, a second relocation must be done by the loader,
|
||||||
// as section addresses can change once loaded.
|
// as section addresses can change once loaded.
|
||||||
|
|
@ -343,6 +359,7 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
// symbol which isn't in .data. However, as .text has the
|
// symbol which isn't in .data. However, as .text has the
|
||||||
// same address once loaded, this is possible.
|
// same address once loaded, this is possible.
|
||||||
if ldr.SymSect(s).Seg == &Segdata {
|
if ldr.SymSect(s).Seg == &Segdata {
|
||||||
|
panic("not implemented")
|
||||||
//Xcoffadddynrel(target, ldr, err, s, &r) // XXX
|
//Xcoffadddynrel(target, ldr, err, s, &r) // XXX
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -363,36 +380,36 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
err.Errorf(s, "missing DWARF section for relocation target %s", ldr.SymName(rs))
|
err.Errorf(s, "missing DWARF section for relocation target %s", ldr.SymName(rs))
|
||||||
}
|
}
|
||||||
|
|
||||||
//if target.IsExternal() {
|
if target.IsExternal() {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
//
|
|
||||||
// // On most platforms, the external linker needs to adjust DWARF references
|
// On most platforms, the external linker needs to adjust DWARF references
|
||||||
// // as it combines DWARF sections. However, on Darwin, dsymutil does the
|
// as it combines DWARF sections. However, on Darwin, dsymutil does the
|
||||||
// // 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 target.IsDarwin() {
|
if target.IsDarwin() {
|
||||||
// r.Done = true
|
needExtReloc = false
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
|
// PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
|
||||||
// // for R_DWARFSECREF relocations, while R_ADDR is replaced with
|
// for R_DWARFSECREF relocations, while R_ADDR is replaced with
|
||||||
// // 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 !target.IsWindows() {
|
if !target.IsWindows() {
|
||||||
// r.Type = objabi.R_ADDR
|
rr.Type = objabi.R_ADDR
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// r.Xsym = r.Sym.Sect.Sym
|
rr.Xsym = loader.Sym(ldr.SymSect(rr.Sym).Sym2)
|
||||||
// r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
|
rr.Xadd = rr.Add + ldr.SymValue(rr.Sym) - int64(ldr.SymSect(rr.Sym).Vaddr)
|
||||||
//
|
|
||||||
// o = r.Xadd
|
o = rr.Xadd
|
||||||
// if target.IsElf() && target.IsAMD64() {
|
if target.IsElf() && target.IsAMD64() {
|
||||||
// o = 0
|
o = 0
|
||||||
// }
|
}
|
||||||
// break
|
break
|
||||||
//}
|
}
|
||||||
o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
|
o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
|
||||||
case objabi.R_WEAKADDROFF, objabi.R_METHODOFF:
|
case objabi.R_WEAKADDROFF, objabi.R_METHODOFF:
|
||||||
if !ldr.AttrReachable(rs) {
|
if !ldr.AttrReachable(rs) {
|
||||||
|
|
@ -415,78 +432,74 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
|
|
||||||
// r.Sym() can be 0 when CALL $(constant) is transformed from absolute PC to relative PC call.
|
// r.Sym() can be 0 when CALL $(constant) is transformed from absolute PC to relative PC call.
|
||||||
case objabi.R_GOTPCREL:
|
case objabi.R_GOTPCREL:
|
||||||
//if target.IsDynlinkingGo() && target.IsDarwin() && r.Sym != nil && r.Sym.Type != sym.SCONST {
|
if target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 && rst != sym.SCONST {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
// r.Xadd = r.Add
|
rr.Xadd = rr.Add
|
||||||
// r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
|
rr.Xadd -= int64(rr.Siz) // relative to address after the relocated chunk
|
||||||
// r.Xsym = r.Sym
|
rr.Xsym = rr.Sym
|
||||||
//
|
|
||||||
// o = r.Xadd
|
o = rr.Xadd
|
||||||
// o += int64(r.Siz)
|
o += int64(rr.Siz)
|
||||||
// break
|
break
|
||||||
//}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case objabi.R_CALL, objabi.R_PCREL:
|
case objabi.R_CALL, objabi.R_PCREL:
|
||||||
//if target.IsExternal() && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
|
if target.IsExternal() && rs != 0 && rst == sym.SUNDEFEXT {
|
||||||
// // pass through to the external linker.
|
// pass through to the external linker.
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
// r.Xadd = 0
|
rr.Xadd = 0
|
||||||
// if target.IsElf() {
|
if target.IsElf() {
|
||||||
// r.Xadd -= int64(r.Siz)
|
rr.Xadd -= int64(rr.Siz)
|
||||||
// }
|
}
|
||||||
// r.Xsym = r.Sym
|
rr.Xsym = rr.Sym
|
||||||
// o = 0
|
o = 0
|
||||||
// break
|
break
|
||||||
//}
|
}
|
||||||
//if target.IsExternal() && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
|
if target.IsExternal() && rs != 0 && rst != sym.SCONST && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
|
||||||
// r.Done = false
|
needExtReloc = true
|
||||||
//
|
|
||||||
// // set up addend for eventual relocation via outer symbol.
|
// set up addend for eventual relocation via outer symbol.
|
||||||
// rs := r.Sym
|
rs := rs
|
||||||
//
|
rs, off := foldSubSymbolOffset(ldr, rs)
|
||||||
// r.Xadd = r.Add
|
rr.Xadd = rr.Add + off
|
||||||
// for rs.Outer != nil {
|
rr.Xadd -= int64(rr.Siz) // relative to address after the relocated chunk
|
||||||
// r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
|
rst := ldr.SymType(rs)
|
||||||
// rs = rs.Outer
|
if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
|
||||||
// }
|
err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
|
||||||
//
|
}
|
||||||
// r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
|
rr.Xsym = rs
|
||||||
// if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
|
|
||||||
// Errorf(s, "missing section for relocation target %s", rs.Name)
|
o = rr.Xadd
|
||||||
// }
|
if target.IsElf() {
|
||||||
// r.Xsym = rs
|
if target.IsAMD64() {
|
||||||
//
|
o = 0
|
||||||
// o = r.Xadd
|
}
|
||||||
// if target.IsElf() {
|
} else if target.IsDarwin() {
|
||||||
// if target.IsAMD64() {
|
if rr.Type == objabi.R_CALL {
|
||||||
// o = 0
|
if target.IsExternal() && rst == sym.SDYNIMPORT {
|
||||||
// }
|
if target.IsAMD64() {
|
||||||
// } else if target.IsDarwin() {
|
// AMD64 dynamic relocations are relative to the end of the relocation.
|
||||||
// if r.Type == objabi.R_CALL {
|
o += int64(rr.Siz)
|
||||||
// if target.IsExternal() && rs.Type == sym.SDYNIMPORT {
|
}
|
||||||
// if target.IsAMD64() {
|
} else {
|
||||||
// // AMD64 dynamic relocations are relative to the end of the relocation.
|
if rst != sym.SHOSTOBJ {
|
||||||
// o += int64(r.Siz)
|
o += int64(uint64(ldr.SymValue(rs)) - ldr.SymSect(rs).Vaddr)
|
||||||
// }
|
}
|
||||||
// } else {
|
o -= int64(rr.Off) // relative to section offset, not symbol
|
||||||
// if rs.Type != sym.SHOSTOBJ {
|
}
|
||||||
// o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
|
} else {
|
||||||
// }
|
o += int64(rr.Siz)
|
||||||
// o -= int64(r.Off) // relative to section offset, not symbol
|
}
|
||||||
// }
|
} else if target.IsWindows() && target.IsAMD64() { // only amd64 needs PCREL
|
||||||
// } else {
|
// PE/COFF's PC32 relocation uses the address after the relocated
|
||||||
// o += int64(r.Siz)
|
// bytes as the base. Compensate by skewing the addend.
|
||||||
// }
|
o += int64(rr.Siz)
|
||||||
// } else if target.IsWindows() && target.IsAMD64() { // only amd64 needs PCREL
|
} else {
|
||||||
// // PE/COFF's PC32 relocation uses the address after the relocated
|
err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
|
||||||
// // bytes as the base. Compensate by skewing the addend.
|
}
|
||||||
// o += int64(r.Siz)
|
|
||||||
// } else {
|
break
|
||||||
// Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
|
|
||||||
o = 0
|
o = 0
|
||||||
if rs != 0 {
|
if rs != 0 {
|
||||||
|
|
@ -504,9 +517,9 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
if !target.IsExternal() {
|
if !target.IsExternal() {
|
||||||
err.Errorf(s, "find XCOFF R_REF with internal linking")
|
err.Errorf(s, "find XCOFF R_REF with internal linking")
|
||||||
}
|
}
|
||||||
//r.Xsym = r.Sym
|
needExtReloc = true
|
||||||
//r.Xadd = r.Add
|
rr.Xsym = rr.Sym
|
||||||
//r.Done = false
|
rr.Xadd = rr.Add
|
||||||
|
|
||||||
// This isn't a real relocation so it must not update
|
// This isn't a real relocation so it must not update
|
||||||
// its offset value.
|
// its offset value.
|
||||||
|
|
@ -548,6 +561,13 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
|
||||||
case 8:
|
case 8:
|
||||||
target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
|
target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if needExtReloc {
|
||||||
|
extRelocs = append(extRelocs, rr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(extRelocs) != 0 {
|
||||||
|
ldr.SetExtRelocs(s, extRelocs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -557,6 +577,9 @@ func (ctxt *Link) reloc() {
|
||||||
ldr := ctxt.loader
|
ldr := ctxt.loader
|
||||||
reporter := &ctxt.ErrorReporter
|
reporter := &ctxt.ErrorReporter
|
||||||
syms := &ctxt.ArchSyms
|
syms := &ctxt.ArchSyms
|
||||||
|
if ctxt.IsExternal() {
|
||||||
|
ldr.InitExtRelocs()
|
||||||
|
}
|
||||||
wg.Add(3)
|
wg.Add(3)
|
||||||
go func() {
|
go func() {
|
||||||
if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
|
if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
|
||||||
|
|
|
||||||
|
|
@ -326,14 +326,14 @@ func Main(arch *sys.Arch, theArch Arch) {
|
||||||
ctxt.loader.InitOutData()
|
ctxt.loader.InitOutData()
|
||||||
thearch.Asmb(ctxt, ctxt.loader)
|
thearch.Asmb(ctxt, ctxt.loader)
|
||||||
|
|
||||||
newreloc := ctxt.IsInternal() && (ctxt.IsAMD64() || ctxt.Is386())
|
newreloc := ctxt.IsAMD64() || ctxt.Is386()
|
||||||
if newreloc {
|
if newreloc {
|
||||||
bench.Start("reloc")
|
bench.Start("reloc")
|
||||||
ctxt.reloc()
|
ctxt.reloc()
|
||||||
bench.Start("loadlibfull")
|
bench.Start("loadlibfull")
|
||||||
// We don't need relocations at this point.
|
// We don't need relocations at this point.
|
||||||
// An exception is Windows, see pe.go:addPEBaseRelocSym
|
// An exception is internal linking on Windows, see pe.go:addPEBaseRelocSym
|
||||||
needReloc := ctxt.IsWindows()
|
needReloc := ctxt.IsWindows() && ctxt.IsInternal()
|
||||||
ctxt.loadlibfull(symGroupType, needReloc) // XXX do it here for now
|
ctxt.loadlibfull(symGroupType, needReloc) // XXX do it here for now
|
||||||
} else {
|
} else {
|
||||||
bench.Start("loadlibfull")
|
bench.Start("loadlibfull")
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,17 @@ type Reloc struct {
|
||||||
Sym Sym // global index of symbol the reloc addresses
|
Sym Sym // global index of symbol the reloc addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtReloc contains the payload for an external relocation.
|
||||||
|
type ExtReloc struct {
|
||||||
|
Off int32 // offset to rewrite
|
||||||
|
Siz uint8 // number of bytes to rewrite: 0, 1, 2, or 4
|
||||||
|
Type objabi.RelocType // the relocation type
|
||||||
|
Sym Sym // global index of symbol the reloc addresses
|
||||||
|
Add int64 // addend
|
||||||
|
Xsym Sym
|
||||||
|
Xadd int64
|
||||||
|
}
|
||||||
|
|
||||||
// Reloc2 holds a "handle" to access a relocation record from an
|
// Reloc2 holds a "handle" to access a relocation record from an
|
||||||
// object file.
|
// object file.
|
||||||
type Reloc2 struct {
|
type Reloc2 struct {
|
||||||
|
|
@ -216,7 +227,8 @@ type Loader struct {
|
||||||
sects []*sym.Section // sections
|
sects []*sym.Section // sections
|
||||||
symSects []uint16 // symbol's section, index to sects array
|
symSects []uint16 // symbol's section, index to sects array
|
||||||
|
|
||||||
outdata [][]byte // symbol's data in the output buffer
|
outdata [][]byte // symbol's data in the output buffer
|
||||||
|
extRelocs [][]ExtReloc // symbol's external relocations
|
||||||
|
|
||||||
itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
|
itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
|
||||||
|
|
||||||
|
|
@ -1108,6 +1120,16 @@ func (l *Loader) InitOutData() {
|
||||||
l.outdata = make([][]byte, l.extStart)
|
l.outdata = make([][]byte, l.extStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetExtRelocs sets the section of the i-th symbol. i is global index.
|
||||||
|
func (l *Loader) SetExtRelocs(i Sym, relocs []ExtReloc) {
|
||||||
|
l.extRelocs[i] = relocs
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitExtRelocs initialize the slice used to store external relocations.
|
||||||
|
func (l *Loader) InitExtRelocs() {
|
||||||
|
l.extRelocs = make([][]ExtReloc, l.NSym())
|
||||||
|
}
|
||||||
|
|
||||||
// SymAlign returns the alignment for a symbol.
|
// SymAlign returns the alignment for a symbol.
|
||||||
func (l *Loader) SymAlign(i Sym) int32 {
|
func (l *Loader) SymAlign(i Sym) int32 {
|
||||||
// If an alignment has been recorded, return that.
|
// If an alignment has been recorded, return that.
|
||||||
|
|
@ -2072,6 +2094,8 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
|
||||||
l.convertRelocations(i, &relocs, s, false)
|
l.convertRelocations(i, &relocs, s, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.convertExtRelocs(s, i)
|
||||||
|
|
||||||
// Copy data
|
// Copy data
|
||||||
s.P = pp.data
|
s.P = pp.data
|
||||||
|
|
||||||
|
|
@ -2632,6 +2656,8 @@ func loadObjFull(l *Loader, r *oReader, needReloc bool) {
|
||||||
l.convertRelocations(gi, &relocs, s, false)
|
l.convertRelocations(gi, &relocs, s, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.convertExtRelocs(s, gi)
|
||||||
|
|
||||||
// Aux symbol info
|
// Aux symbol info
|
||||||
auxs := r.Auxs(i)
|
auxs := r.Auxs(i)
|
||||||
for j := range auxs {
|
for j := range auxs {
|
||||||
|
|
@ -2697,6 +2723,33 @@ func (l *Loader) convertRelocations(symIdx Sym, src *Relocs, dst *sym.Symbol, st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert external relocations to sym.Relocs on symbol dst.
|
||||||
|
func (l *Loader) convertExtRelocs(dst *sym.Symbol, src Sym) {
|
||||||
|
if int(src) >= len(l.extRelocs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
relocs := l.extRelocs[src]
|
||||||
|
if len(relocs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(dst.R) != 0 {
|
||||||
|
panic("bad")
|
||||||
|
}
|
||||||
|
dst.R = make([]sym.Reloc, len(relocs))
|
||||||
|
for i := range dst.R {
|
||||||
|
sr := &relocs[i]
|
||||||
|
r := &dst.R[i]
|
||||||
|
r.InitExt()
|
||||||
|
r.Off = sr.Off
|
||||||
|
r.Siz = sr.Siz
|
||||||
|
r.Type = sr.Type
|
||||||
|
r.Sym = l.Syms[sr.Sym]
|
||||||
|
r.Add = sr.Add
|
||||||
|
r.Xsym = l.Syms[sr.Xsym]
|
||||||
|
r.Xadd = sr.Xadd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// relocId is essentially a <S,R> tuple identifying the Rth
|
// relocId is essentially a <S,R> tuple identifying the Rth
|
||||||
// relocation of symbol S.
|
// relocation of symbol S.
|
||||||
type relocId struct {
|
type relocId struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue