]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: load external ELF PPC64 objects which set st_other=1
authorPaul E. Murphy <murp@ibm.com>
Tue, 17 Jan 2023 17:33:28 +0000 (11:33 -0600)
committerPaul Murphy <murp@ibm.com>
Fri, 28 Apr 2023 21:26:08 +0000 (21:26 +0000)
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>

src/cmd/link/internal/loadelf/ldelf.go
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/ppc64/asm.go

index c1bfec059d91ba6e4b2ee61eb364dd285a4fc651..77247b47f4c43e6598f9d1052a1a303d1b8ee636 100644 (file)
@@ -639,11 +639,15 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
                        case 0:
                                // No local entry. R2 is preserved.
                        case 1:
-                               // These require R2 be saved and restored by the caller. This isn't supported today.
-                               return errorf("%s: unable to handle local entry type 1", sb.Name())
+                               // This is kind of a hack, but pass the hint about this symbol's
+                               // 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:
                                return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
                        default:
+                               // Convert the word sized offset into bytes.
                                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_GOT32X)<<16,
                PPC64 | uint32(elf.R_PPC64_REL24)<<16,
+               PPC64 | uint32(elf.R_PPC64_REL24_NOTOC)<<16,
                PPC64 | uint32(elf.R_PPC_REL32)<<16,
                S390X | uint32(elf.R_390_32)<<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_PREL64)<<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_RELATIVE)<<16,
                S390X | uint32(elf.R_390_GOTOFF)<<16,
index 455ef587d1c2934e5022bfc6642ceb5953f403df..4bccce047b00909a90e97aabdc96b6312e58a670 100644 (file)
@@ -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.
+//
+// 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 {
        return l.localentry[i]
 }
index c716c2a5e023695b399d9835075e0eafb8516e1e..121fbf8fa50f5e1b73b945df94cb1934264ff8b0 100644 (file)
@@ -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.
                                        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)
                                        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
                // point.  (If we don't do this, the callee will try
                // 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 {
                        // Should have been handled in elfsetupplt