// lay down trampolines after each function
for ; ntramps < len(ctxt.tramps); ntramps++ {
tramp := ctxt.tramps[ntramps]
+ if ctxt.HeadType == objabi.Haix && strings.HasPrefix(tramp.Name, "runtime.text.") {
+ // Already set in assignAddress
+ continue
+ }
sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true)
}
}
} else {
va = uint64(Rnd(int64(va), int64(Funcalign)))
}
- s.Value = 0
- for sub := s; sub != nil; sub = sub.Sub {
- sub.Value += int64(va)
- }
funcsize := uint64(MINFUNC) // spacing required for findfunctab
if s.Size > MINFUNC {
// Only break at outermost syms.
- if ctxt.Arch.InFamily(sys.PPC64) && s.Outer == nil && ctxt.IsELF && ctxt.LinkMode == LinkExternal && va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(s, isTramp) > 0x1c00000 {
+ if ctxt.Arch.InFamily(sys.PPC64) && s.Outer == nil && ctxt.LinkMode == LinkExternal && va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(s, isTramp) > 0x1c00000 {
// Set the length for the previous text section
sect.Length = va - sect.Vaddr
s.Sect = sect
// Create a symbol for the start of the secondary text sections
- ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0).Sect = sect
+ ntext := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
+ ntext.Sect = sect
+ if ctxt.HeadType == objabi.Haix {
+ // runtime.text.X must be a real symbol on AIX.
+ // Assign its address directly in order to be the
+ // first symbol of this new section.
+ ntext.Type = sym.STEXT
+ ntext.Size = int64(MINFUNC)
+ ntext.Attr |= sym.AttrReachable
+ ntext.Attr |= sym.AttrOnList
+ ctxt.tramps = append(ctxt.tramps, ntext)
+
+ ntext.Value = int64(va)
+ va += uint64(ntext.Size)
+
+ if s.Align != 0 {
+ va = uint64(Rnd(int64(va), int64(s.Align)))
+ } else {
+ va = uint64(Rnd(int64(va), int64(Funcalign)))
+ }
+ }
n++
}
+
+ s.Value = 0
+ for sub := s; sub != nil; sub = sub.Sub {
+ sub.Value += int64(va)
+ }
+
va += funcsize
return sect, n, va
break
}
symname := fmt.Sprintf("runtime.text.%d", n)
- ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
+ if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
+ // Addresses are already set on AIX with external linker
+ // because these symbols are part of their sections.
+ ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
+ }
n++
}
syms := []xcoffSym{}
// Check if a new file is detected.
- if x.File == "" { // Undefined global symbol
+ if strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
+ // Trampoline don't have a FILE so there are considered
+ // in the current file.
+ // Same goes for runtime.text.X symbols.
+ } else if x.File == "" { // Undefined global symbol
// If this happens, the algorithme must be redone.
if currSymSrcFile.name != "" {
Exitf("undefined global symbol found inside another file")
return
case TextSym:
- if x.FuncInfo != nil {
+ if x.FuncInfo != nil || strings.Contains(x.Name, "-tramp") || strings.HasPrefix(x.Name, "runtime.text.") {
// Function within a file
syms = xfile.writeSymbolFunc(ctxt, x)
} else {
ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n")
} else {
ctxt.AddTramp(tramp)
- gentramp(ctxt.Arch, ctxt.LinkMode, tramp, r.Sym, r.Add)
+ gentramp(ctxt, tramp, r.Sym, r.Add)
}
}
r.Sym = tramp
}
}
-func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, offset int64) {
- // Used for default build mode for an executable
- // Address of the call target is generated using
- // relocation and doesn't depend on r2 (TOC).
+func gentramp(ctxt *ld.Link, tramp, target *sym.Symbol, offset int64) {
tramp.Size = 16 // 4 instructions
tramp.P = make([]byte, tramp.Size)
t := ld.Symaddr(target) + offset
- o1 := uint32(0x3fe00000) // lis r31,targetaddr hi
- o2 := uint32(0x3bff0000) // addi r31,targetaddr lo
- // With external linking, the target address must be
- // relocated using LO and HA
- if linkmode == ld.LinkExternal {
+ var o1, o2 uint32
+
+ if ctxt.HeadType == objabi.Haix {
+ // On AIX, the address is retrieved with a TOC symbol.
+ // For internal linking, the "Linux" way might still be used.
+ // However, all text symbols are accessed with a TOC symbol as
+ // text relocations aren't supposed to be possible.
+ // So, keep using the external linking way to be more AIX friendly.
+ o1 = uint32(0x3fe20000) // lis r2, toctargetaddr hi
+ o2 = uint32(0xebff0000) // ld r31, toctargetaddr lo
+
+ toctramp := ctxt.Syms.Lookup("TOC."+tramp.Name, 0)
+ toctramp.Type = sym.SXCOFFTOC
+ toctramp.Attr |= sym.AttrReachable
+ toctramp.AddAddr(ctxt.Arch, target)
+
tr := tramp.AddRel()
tr.Off = 0
- tr.Type = objabi.R_ADDRPOWER
+ tr.Type = objabi.R_ADDRPOWER_TOCREL_DS
tr.Siz = 8 // generates 2 relocations: HA + LO
- tr.Sym = target
+ tr.Sym = toctramp
tr.Add = offset
} else {
- // adjustment needed if lo has sign bit set
- // when using addi to compute address
- val := uint32((t & 0xffff0000) >> 16)
- if t&0x8000 != 0 {
- val += 1
+ // Used for default build mode for an executable
+ // Address of the call target is generated using
+ // relocation and doesn't depend on r2 (TOC).
+ o1 = uint32(0x3fe00000) // lis r31,targetaddr hi
+ o2 = uint32(0x3bff0000) // addi r31,targetaddr lo
+
+ // With external linking, the target address must be
+ // relocated using LO and HA
+ if ctxt.LinkMode == ld.LinkExternal {
+ tr := tramp.AddRel()
+ tr.Off = 0
+ tr.Type = objabi.R_ADDRPOWER
+ tr.Siz = 8 // generates 2 relocations: HA + LO
+ tr.Sym = target
+ tr.Add = offset
+
+ } else {
+ // adjustment needed if lo has sign bit set
+ // when using addi to compute address
+ val := uint32((t & 0xffff0000) >> 16)
+ if t&0x8000 != 0 {
+ val += 1
+ }
+ o1 |= val // hi part of addr
+ o2 |= uint32(t & 0xffff) // lo part of addr
}
- o1 |= val // hi part of addr
- o2 |= uint32(t & 0xffff) // lo part of addr
}
+
o3 := uint32(0x7fe903a6) // mtctr r31
o4 := uint32(0x4e800420) // bctr
- arch.ByteOrder.PutUint32(tramp.P, o1)
- arch.ByteOrder.PutUint32(tramp.P[4:], o2)
- arch.ByteOrder.PutUint32(tramp.P[8:], o3)
- arch.ByteOrder.PutUint32(tramp.P[12:], o4)
+ ctxt.Arch.ByteOrder.PutUint32(tramp.P, o1)
+ ctxt.Arch.ByteOrder.PutUint32(tramp.P[4:], o2)
+ ctxt.Arch.ByteOrder.PutUint32(tramp.P[8:], o3)
+ ctxt.Arch.ByteOrder.PutUint32(tramp.P[12:], o4)
}
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {