reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
syms = append(syms, reloc.Sym)
empty = false
+ // LLVM doesn't support base address entries. Strip them out so LLDB and dsymutil don't get confused.
+ if ctxt.HeadType == objabi.Hdarwin {
+ removeLocationListBaseAddress(ctxt, fn, reloc.Sym)
+ }
// One location list entry per function, but many relocations to it. Don't duplicate.
break
}
return syms
}
+func removeLocationListBaseAddress(ctxt *Link, info, list *sym.Symbol) {
+ // The list symbol contains multiple lists, but they're all for the
+ // same function, and it's not empty.
+ fn := list.R[0].Sym
+
+ // Discard the relocations for the base address entries.
+ list.R = list.R[:0]
+
+ // Add relocations for each location entry's start and end addresses,
+ // so that the base address entries aren't necessary.
+ // We could remove them entirely, but that's more work for a relatively
+ // small size win. If dsymutil runs it'll throw them away anyway.
+
+ // relocate adds a CU-relative relocation to fn+addr at offset.
+ relocate := func(addr uint64, offset int) {
+ list.R = append(list.R, sym.Reloc{
+ Off: int32(offset),
+ Siz: uint8(ctxt.Arch.PtrSize),
+ Type: objabi.R_ADDRCUOFF,
+ Add: int64(addr),
+ Sym: fn,
+ })
+ }
+
+ for i := 0; i < len(list.P); {
+ first := readPtr(ctxt, list.P[i:])
+ second := readPtr(ctxt, list.P[i+ctxt.Arch.PtrSize:])
+
+ if first == 0 ||
+ first == ^uint64(0) ||
+ (ctxt.Arch.PtrSize == 4 && first == uint64(^uint32(0))) {
+ // Base address selection entry or end of list. Ignore.
+ i += ctxt.Arch.PtrSize * 2
+ continue
+ }
+
+ relocate(first, i)
+ relocate(second, i+ctxt.Arch.PtrSize)
+
+ // Skip past the actual location.
+ i += ctxt.Arch.PtrSize * 2
+ i += 2 + int(ctxt.Arch.ByteOrder.Uint16(list.P[i:]))
+ }
+
+ // Rewrite the DIE's relocations to point to the first location entry,
+ // not the now-useless base address selection entry.
+ for i := range info.R {
+ r := &info.R[i]
+ if r.Sym != list {
+ continue
+ }
+ r.Add += int64(2 * ctxt.Arch.PtrSize)
+ }
+}
+
+// Read a pointer-sized uint from the beginning of buf.
+func readPtr(ctxt *Link, buf []byte) uint64 {
+ switch ctxt.Arch.PtrSize {
+ case 4:
+ return uint64(ctxt.Arch.ByteOrder.Uint32(buf))
+ case 8:
+ return ctxt.Arch.ByteOrder.Uint64(buf)
+ default:
+ panic("unexpected pointer size")
+ }
+}
+
/*
* Elf.
*/