return true
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant")
return t
}
}
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
switch r.Type {
case objabi.R_CALLARM:
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
// The following three arch specific relocations are only for generation of
// Linux/ARM ELF's PLT entry (3 assembler instruction)
case objabi.R_PLT0: // add ip, pc, #0xXX00000
- if ld.Symaddr(ctxt.Syms.Lookup(".got.plt", 0)) < ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) {
+ if ld.Symaddr(syms.GOTPLT) < ld.Symaddr(syms.PLT) {
ld.Errorf(s, ".got.plt should be placed after .plt section.")
}
- return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add)) >> 20)), true
+ return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add)) >> 20)), true
case objabi.R_PLT1: // add ip, ip, #0xYY000
- return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+4)) >> 12)), true
+ return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+4)) >> 12)), true
case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
- return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+8))), true
+ return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+8))), true
case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
// r.Add is the instruction
// low 24-bit encodes the target address
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant")
return t
}
return true
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
switch r.Type {
default:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
case objabi.R_ADDRARM64:
t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
case objabi.R_CALLARM64:
var t int64
if r.Sym.Type == sym.SDYNIMPORT {
- t = (ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) + r.Add) - (s.Value + int64(r.Off))
+ t = (ld.Symaddr(syms.PLT) + r.Add) - (s.Value + int64(r.Off))
} else {
t = (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
}
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant")
return -1
}
case 8:
o = int64(target.Arch.ByteOrder.Uint64(s.P[off:]))
}
- if offset, ok := thearch.Archreloc(ctxt, target, r, s, o); ok {
+ if offset, ok := thearch.Archreloc(target, &ctxt.ArchSyms, r, s, o); ok {
o = offset
} else {
Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(target.Arch, r.Type))
if target.IsPPC64() || target.IsS390X() {
r.InitExt()
if r.Variant != sym.RV_NONE {
- o = thearch.Archrelocvariant(ctxt, target, r, s, o)
+ o = thearch.Archrelocvariant(target, &ctxt.ArchSyms, r, s, o)
}
}
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+type LookupFn func(name string, version int) *sym.Symbol
+
+// ArchSyms holds a number of architecture specific symbols used during
+// relocation. Rather than allowing them universal access to all symbols,
+// we keep a subset for relocation application.
+type ArchSyms struct {
+ TOC *sym.Symbol
+ DotTOC *sym.Symbol
+ GOT *sym.Symbol
+ PLT *sym.Symbol
+ GOTPLT *sym.Symbol
+}
+
+// setArchSyms sets up the ArchSyms structure, and must be called before
+// relocations are applied.
+func (ctxt *Link) setArchSyms() {
+ ctxt.TOC = ctxt.Syms.Lookup("TOC", 0)
+ ctxt.DotTOC = ctxt.Syms.Lookup(".TOC.", 0)
+ ctxt.GOT = ctxt.Syms.Lookup(".got", 0)
+ ctxt.PLT = ctxt.Syms.Lookup(".plt", 0)
+ ctxt.GOTPLT = ctxt.Syms.Lookup(".got.plt", 0)
+}
+
type Arch struct {
Funcalign int
Maxalign int
// value is the appropriately relocated value (to be written back
// to the same spot in sym.P) and a boolean indicating
// success/failure (a failing value indicates a fatal error).
- Archreloc func(link *Link, target *Target, rel *sym.Reloc, sym *sym.Symbol,
+ Archreloc func(target *Target, syms *ArchSyms, rel *sym.Reloc, sym *sym.Symbol,
offset int64) (relocatedOffset int64, success bool)
// Archrelocvariant is a second arch-specific hook used for
// relocation processing; it handles relocations where r.Type is
// relocation applies, and "off" is the contents of the
// to-be-relocated data item (from sym.P). Return is an updated
// offset value.
- Archrelocvariant func(link *Link, target *Target, rel *sym.Reloc, sym *sym.Symbol,
+ Archrelocvariant func(target *Target, syms *ArchSyms, rel *sym.Reloc, sym *sym.Symbol,
offset int64) (relocatedOffset int64)
Trampoline func(*Link, *sym.Reloc, *sym.Symbol)
type Link struct {
Target
ErrorReporter
+ ArchSyms
Out *OutBuf
Syms *sym.Symbols
bench.Start("address")
order := ctxt.address()
bench.Start("dwarfcompress")
+ ctxt.setArchSyms()
dwarfcompress(ctxt)
bench.Start("layout")
filesize := ctxt.layout(order)
}
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
switch r.Type {
default:
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
t := ld.Symaddr(r.Sym) + r.Add
return applyrel(target.Arch, r, s, val, t), true
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
return -1
}
return false
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
switch r.Type {
default:
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
case objabi.R_ADDRMIPS,
objabi.R_ADDRMIPSU:
t := ld.Symaddr(r.Sym) + r.Add
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
return -1
}
return false
}
-// Return the value of .TOC. for symbol s
-func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
- var toc *sym.Symbol
-
- if s.Outer != nil {
- toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
- } else {
- toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version))
- }
-
- if toc == nil {
- ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
- return 0
- }
-
- return toc.Value
-}
-
// archreloctoc relocates a TOC relative symbol.
// If the symbol pointed by this TOC relative symbol is in .data or .bss, the
// default load instruction can be changed to an addi instruction and the
// symbol address can be used directly.
// This code is for AIX only.
-func archreloctoc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
if target.IsLinux() {
ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
}
}
if target.IsInternal() && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
- t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
+ t = ld.Symaddr(tarSym) + r.Add - syms.TOC.Value
// change ld to addi in the second instruction
o2 = (o2 & 0x03FF0000) | 0xE<<26
useAddi = true
} else {
- t = ld.Symaddr(r.Sym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
+ t = ld.Symaddr(r.Sym) + r.Add - syms.TOC.Value
}
if t != int64(int32(t)) {
// archrelocaddr relocates a symbol address.
// This code is for AIX only.
-func archrelocaddr(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
if target.IsAIX() {
ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
}
ctxt.Arch.ByteOrder.PutUint32(tramp.P[12:], o4)
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
- if ctxt.LinkMode == ld.LinkExternal {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+ if target.IsExternal() {
// On AIX, relocations (except TLS ones) must be also done to the
// value with the current addresses.
switch r.Type {
default:
- if ctxt.HeadType != objabi.Haix {
+ if target.IsAIX() {
return val, false
}
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
}
r.Xsym = rs
- if ctxt.HeadType != objabi.Haix {
+ if !target.IsAIX() {
return val, true
}
case objabi.R_CALLPOWER:
r.Done = false
r.Xsym = r.Sym
r.Xadd = r.Add
- if ctxt.HeadType != objabi.Haix {
+ if !target.IsAIX() {
return val, true
}
}
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
- return archreloctoc(ctxt, &ctxt.Target, r, s, val), true
+ return archreloctoc(target, syms, r, s, val), true
case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
- return archrelocaddr(ctxt, target, r, s, val), true
+ return archrelocaddr(target, syms, r, s, val), true
case objabi.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
}
return val | int64(uint32(t)&^0xfc000003), true
case objabi.R_POWER_TOC: // S + A - .TOC.
- return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true
+ return ld.Symaddr(r.Sym) + r.Add - syms.DotTOC.Value, true
case objabi.R_POWER_TLS_LE:
// The thread pointer points 0x7000 bytes after the start of the
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
// Specification".
v := r.Sym.Value - 0x7000
- if ctxt.HeadType == objabi.Haix {
+ if target.IsAIX() {
// On AIX, the thread pointer points 0x7800 bytes after
// the TLS.
v -= 0x800
return val, false
}
-func archrelocvariant(ctxt *ld.Link, taget *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
switch r.Variant & sym.RV_TYPE_MASK {
default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
- if ctxt.Arch.ByteOrder == binary.BigEndian {
+ if target.IsBigEndian() {
o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
} else {
o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
- if ctxt.Arch.ByteOrder == binary.BigEndian {
+ if target.IsBigEndian() {
o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
} else {
o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
case sym.RV_POWER_DS:
var o1 uint32
- if ctxt.Arch.ByteOrder == binary.BigEndian {
+ if target.IsBigEndian() {
o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
} else {
o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
return false
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
switch r.Type {
case objabi.R_CALLRISCV:
// Nothing to do.
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("archrelocvariant")
return -1
}
return false
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
return val, false
}
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
}
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
switch r.Variant & sym.RV_TYPE_MASK {
default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
return true
}
-func archreloc(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if target.IsExternal() {
return val, false
}
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
}
return val, false
}
-func archrelocvariant(ctxt *ld.Link, target *ld.Target, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant")
return t
}