mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: load external ELF PPC64 objects which set st_other=1
This indicates the symbol does not use or preserve the TOC pointer in R2. Likewise, it does not have a distinct local entry point. This happens when gcc compiles an object with -mcpu=power10. Recycle the SymLocalentry field of a text symbol to pass through this hint as the bogus value 1 (A valid offset must be a multiple of 4 bytes), and update the usage to check and generate errors further into the linking process. This matches the behavior of st_other as used by ELFv2. Change-Id: Ic89ce17b57f400ab44213b21a3730a98c7cdf842 Reviewed-on: https://go-review.googlesource.com/c/go/+/490295 Run-TryBot: Paul Murphy <murp@ibm.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
265d19ed52
commit
3c46d8f511
3 changed files with 23 additions and 4 deletions
|
|
@ -639,11 +639,15 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
|
||||||
case 0:
|
case 0:
|
||||||
// No local entry. R2 is preserved.
|
// No local entry. R2 is preserved.
|
||||||
case 1:
|
case 1:
|
||||||
// These require R2 be saved and restored by the caller. This isn't supported today.
|
// This is kind of a hack, but pass the hint about this symbol's
|
||||||
return errorf("%s: unable to handle local entry type 1", sb.Name())
|
// usage of R2 (R2 is a caller-save register not a TOC pointer, and
|
||||||
|
// this function does not have a distinct local entry) by setting
|
||||||
|
// its SymLocalentry to 1.
|
||||||
|
l.SetSymLocalentry(s, 1)
|
||||||
case 7:
|
case 7:
|
||||||
return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
|
return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
|
||||||
default:
|
default:
|
||||||
|
// Convert the word sized offset into bytes.
|
||||||
l.SetSymLocalentry(s, 4<<uint(flag-2))
|
l.SetSymLocalentry(s, 4<<uint(flag-2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1061,6 +1065,7 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
|
||||||
I386 | uint32(elf.R_386_GOTPC)<<16,
|
I386 | uint32(elf.R_386_GOTPC)<<16,
|
||||||
I386 | uint32(elf.R_386_GOT32X)<<16,
|
I386 | uint32(elf.R_386_GOT32X)<<16,
|
||||||
PPC64 | uint32(elf.R_PPC64_REL24)<<16,
|
PPC64 | uint32(elf.R_PPC64_REL24)<<16,
|
||||||
|
PPC64 | uint32(elf.R_PPC64_REL24_NOTOC)<<16,
|
||||||
PPC64 | uint32(elf.R_PPC_REL32)<<16,
|
PPC64 | uint32(elf.R_PPC_REL32)<<16,
|
||||||
S390X | uint32(elf.R_390_32)<<16,
|
S390X | uint32(elf.R_390_32)<<16,
|
||||||
S390X | uint32(elf.R_390_PC32)<<16,
|
S390X | uint32(elf.R_390_PC32)<<16,
|
||||||
|
|
@ -1077,6 +1082,9 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
|
||||||
ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
|
ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
|
||||||
ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
|
ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
|
||||||
PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
|
PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
|
||||||
|
PPC64 | uint32(elf.R_PPC64_PCREL34)<<16,
|
||||||
|
PPC64 | uint32(elf.R_PPC64_GOT_PCREL34)<<16,
|
||||||
|
PPC64 | uint32(elf.R_PPC64_PLT_PCREL34_NOTOC)<<16,
|
||||||
S390X | uint32(elf.R_390_GLOB_DAT)<<16,
|
S390X | uint32(elf.R_390_GLOB_DAT)<<16,
|
||||||
S390X | uint32(elf.R_390_RELATIVE)<<16,
|
S390X | uint32(elf.R_390_RELATIVE)<<16,
|
||||||
S390X | uint32(elf.R_390_GOTOFF)<<16,
|
S390X | uint32(elf.R_390_GOTOFF)<<16,
|
||||||
|
|
|
||||||
|
|
@ -1582,6 +1582,9 @@ func (l *Loader) SetSymPkg(i Sym, pkg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SymLocalentry returns an offset in bytes of the "local entry" of a symbol.
|
// SymLocalentry returns an offset in bytes of the "local entry" of a symbol.
|
||||||
|
//
|
||||||
|
// On PPC64, a value of 1 indicates the symbol does not use or preserve a TOC
|
||||||
|
// pointer in R2, nor does it have a distinct local entry.
|
||||||
func (l *Loader) SymLocalentry(i Sym) uint8 {
|
func (l *Loader) SymLocalentry(i Sym) uint8 {
|
||||||
return l.localentry[i]
|
return l.localentry[i]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,11 @@ func genstubs(ctxt *ld.Link, ldr *loader.Loader) {
|
||||||
|
|
||||||
// Turn this reloc into an R_CALLPOWER, and convert the TOC restore into a nop.
|
// Turn this reloc into an R_CALLPOWER, and convert the TOC restore into a nop.
|
||||||
su.SetRelocType(i, objabi.R_CALLPOWER)
|
su.SetRelocType(i, objabi.R_CALLPOWER)
|
||||||
su.SetRelocAdd(i, r.Add()+int64(ldr.SymLocalentry(r.Sym())))
|
localEoffset := int64(ldr.SymLocalentry(r.Sym()))
|
||||||
|
if localEoffset == 1 {
|
||||||
|
ldr.Errorf(s, "Unsupported NOTOC call to %s", ldr.SymName(r.Sym()))
|
||||||
|
}
|
||||||
|
su.SetRelocAdd(i, r.Add()+localEoffset)
|
||||||
r.SetSiz(4)
|
r.SetSiz(4)
|
||||||
rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_TOCRESTORE)
|
rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_TOCRESTORE)
|
||||||
}
|
}
|
||||||
|
|
@ -435,7 +439,11 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo
|
||||||
// callee. Hence, we need to go to the local entry
|
// callee. Hence, we need to go to the local entry
|
||||||
// point. (If we don't do this, the callee will try
|
// point. (If we don't do this, the callee will try
|
||||||
// to use r12 to compute r2.)
|
// to use r12 to compute r2.)
|
||||||
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymLocalentry(targ)))
|
localEoffset := int64(ldr.SymLocalentry(targ))
|
||||||
|
if localEoffset == 1 {
|
||||||
|
ldr.Errorf(s, "Unsupported NOTOC call to %s", targ)
|
||||||
|
}
|
||||||
|
su.SetRelocAdd(rIdx, r.Add()+localEoffset)
|
||||||
|
|
||||||
if targType == sym.SDYNIMPORT {
|
if targType == sym.SDYNIMPORT {
|
||||||
// Should have been handled in elfsetupplt
|
// Should have been handled in elfsetupplt
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue