switch r.Type {
default:
return false
- case objabi.R_ADDR:
+ case objabi.R_ADDR, objabi.R_DWARFSECREF:
v = ld.XCOFF_R_POS
if r.Siz == 4 {
v |= 0x1F << 8
emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
case objabi.R_XCOFFREF:
emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
-
}
return true
}
// Return the value of .TOC. for symbol s
-func symtoc(syms *ld.ArchSyms, s *sym.Symbol) int64 {
- v := s.Version
- if s.Outer != nil {
- v = s.Outer.Version
+func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
+ v := ldr.SymVersion(s)
+ if out := ldr.OuterSym(s); out != 0 {
+ v = ldr.SymVersion(out)
}
- toc := syms.DotTOC[v]
- if toc == nil {
- ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
+ toc := syms.DotTOC2[v]
+ if toc == 0 {
+ ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
return 0
}
- return toc.Value
+ return ldr.SymValue(toc)
}
// archreloctoc relocates a TOC relative symbol.
// 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(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 {
+ rs := ldr.ResolveABIAlias(r.Sym())
if target.IsLinux() {
- ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
+ ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
}
var o1, o2 uint32
o1 = uint32(val >> 32)
o2 = uint32(val)
+ if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
+ ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
+ }
var t int64
useAddi := false
- const prefix = "TOC."
- var tarSym *sym.Symbol
- if strings.HasPrefix(r.Sym.Name, prefix) {
- tarSym = r.Sym.R[0].Sym
- } else {
- ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
- }
+ relocs := ldr.Relocs(rs)
+ tarSym := ldr.ResolveABIAlias(relocs.At2(0).Sym())
- if target.IsInternal() && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
- t = ld.Symaddr(tarSym) + r.Add - syms.TOC.Value
+ if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
+ t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC2)
// change ld to addi in the second instruction
o2 = (o2 & 0x03FF0000) | 0xE<<26
useAddi = true
} else {
- t = ld.Symaddr(r.Sym) + r.Add - syms.TOC.Value
+ t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC2)
}
if t != int64(int32(t)) {
- ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t)
+ ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
}
if t&0x8000 != 0 {
o1 |= uint32((t >> 16) & 0xFFFF)
- switch r.Type {
+ switch r.Type() {
case objabi.R_ADDRPOWER_TOCREL_DS:
if useAddi {
o2 |= uint32(t) & 0xFFFF
} else {
if t&3 != 0 {
- ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+ ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
}
o2 |= uint32(t) & 0xFFFC
}
// archrelocaddr relocates a symbol address.
// This code is for AIX only.
-func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
+func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 {
+ rs := ldr.ResolveABIAlias(r.Sym())
if target.IsAIX() {
- ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
+ ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
}
var o1, o2 uint32
if target.IsBigEndian() {
// instruction (it is an error in this case if the low 2 bits of the address
// are non-zero).
- t := ld.Symaddr(r.Sym) + r.Add
+ t := ldr.SymAddr(rs) + r.Add()
if t < 0 || t >= 1<<31 {
- ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
+ ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
}
if t&0x8000 != 0 {
t += 0x10000
}
- switch r.Type {
+ switch r.Type() {
case objabi.R_ADDRPOWER:
o1 |= (uint32(t) >> 16) & 0xffff
o2 |= uint32(t) & 0xffff
case objabi.R_ADDRPOWER_DS:
o1 |= (uint32(t) >> 16) & 0xffff
if t&3 != 0 {
- ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+ ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
}
o2 |= uint32(t) & 0xfffc
default:
tramp.SetData(P)
}
-func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (relocatedOffset int64, needExtReloc bool, ok bool) {
+ needExternal := false
+ rs := ldr.ResolveABIAlias(r.Sym())
if target.IsExternal() {
// On AIX, relocations (except TLS ones) must be also done to the
// value with the current addresses.
- switch r.Type {
+ switch r.Type() {
default:
if target.IsAIX() {
- return val, false
+ return val, needExternal, false
}
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
- r.Done = false
// check Outer is nil, Type is TLSBSS?
- r.Xadd = r.Add
- r.Xsym = r.Sym
- return val, true
+ needExternal = true
+ rr.Xadd = r.Add()
+ rr.Xsym = rs
+ return val, needExternal, true
case objabi.R_ADDRPOWER,
objabi.R_ADDRPOWER_DS,
objabi.R_ADDRPOWER_TOCREL,
objabi.R_ADDRPOWER_TOCREL_DS,
objabi.R_ADDRPOWER_GOT,
objabi.R_ADDRPOWER_PCREL:
- r.Done = false
+ needExternal = true
// set up addend for eventual relocation via outer symbol.
- rs := ld.ApplyOuterToXAdd(r)
- if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
- ld.Errorf(s, "missing section for %s", rs.Name)
+ rs, off := ld.FoldSubSymbolOffset(ldr, rs)
+ rr.Xadd = r.Add() + off
+ rst := ldr.SymType(rs)
+ if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
+ ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
}
- r.Xsym = rs
+ rr.Xsym = rs
if !target.IsAIX() {
- return val, true
+ return val, needExternal, true
}
case objabi.R_CALLPOWER:
- r.Done = false
- r.Xsym = r.Sym
- r.Xadd = r.Add
+ needExternal = true
+ rr.Xsym = rs
+ rr.Xadd = r.Add()
if !target.IsAIX() {
- return val, true
+ return val, needExternal, true
}
}
}
- switch r.Type {
- case objabi.R_CONST:
- return r.Add, true
- case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
+ switch r.Type() {
case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
- return archreloctoc(target, syms, r, s, val), true
+ return archreloctoc(ldr, target, syms, r, s, val), needExternal, true
case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
- return archrelocaddr(target, syms, r, s, val), true
+ return archrelocaddr(ldr, target, syms, r, s, val), needExternal, true
case objabi.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
- t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
+ t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
if t&3 != 0 {
- ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
+ ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
}
// If branch offset is too far then create a trampoline.
if int64(int32(t<<6)>>6) != t {
- ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
+ ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
}
- return val | int64(uint32(t)&^0xfc000003), true
+ return val | int64(uint32(t)&^0xfc000003), needExternal, true
case objabi.R_POWER_TOC: // S + A - .TOC.
- return ld.Symaddr(r.Sym) + r.Add - symtoc(syms, s), true
+ return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), needExternal, true
case objabi.R_POWER_TLS_LE:
// The thread pointer points 0x7000 bytes after the start of the
// thread local storage area as documented in section "3.7.2 TLS
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
// Specification".
- v := r.Sym.Value - 0x7000
+ v := ldr.SymValue(rs) - 0x7000
if target.IsAIX() {
// On AIX, the thread pointer points 0x7800 bytes after
// the TLS.
v -= 0x800
}
if int64(int16(v)) != v {
- ld.Errorf(s, "TLS offset out of range %d", v)
+ ldr.Errorf(s, "TLS offset out of range %d", v)
}
- return (val &^ 0xffff) | (v & 0xffff), true
+ return (val &^ 0xffff) | (v & 0xffff), needExternal, true
}
- return val, false
+ return val, needExternal, false
}
-func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
- switch r.Variant & sym.RV_TYPE_MASK {
+func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) (relocatedOffset int64) {
+ rs := ldr.ResolveABIAlias(r.Sym())
+ switch rv & sym.RV_TYPE_MASK {
default:
- ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
+ ldr.Errorf(s, "unexpected relocation variant %d", rv)
fallthrough
case sym.RV_NONE:
return t
case sym.RV_POWER_LO:
- if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
+ if rv&sym.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
if target.IsBigEndian() {
- o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
+ o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
} else {
- o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
+ o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
}
switch o1 >> 26 {
case 24, // ori
case sym.RV_POWER_HI:
t >>= 16
- if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
+ if rv&sym.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
if target.IsBigEndian() {
- o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
+ o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
} else {
- o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
+ o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
}
switch o1 >> 26 {
case 25, // oris
case sym.RV_POWER_DS:
var o1 uint32
if target.IsBigEndian() {
- o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
+ o1 = uint32(binary.BigEndian.Uint16(ldr.Data(s)[r.Off():]))
} else {
- o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
+ o1 = uint32(binary.LittleEndian.Uint16(ldr.Data(s)[r.Off():]))
}
if t&3 != 0 {
- ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
+ ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
}
- if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
+ if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
goto overflow
}
return int64(o1)&0x3 | int64(int16(t))
}
overflow:
- ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
+ ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
return t
}