[PATCH] D91426: [PowerPC] Fix issue where binary uses a .got but is missing a .TOC.

Stefan Pintilie via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 4 04:41:28 PST 2021


stefanp added a comment.

In D91426#2535050 <https://reviews.llvm.org/D91426#2535050>, @MaskRay wrote:

> Sorry, I missed your early comments.
>
> Which test can demonstrate the bug? My idea is that instead of creating `setupPPCDelayedInit`, we should let `in.got->hasGotOffRel` to convey that .got is needed.
> See Relocations.cpp:1397

Thank you for looking at this again!
I think I understand what you are looking for.

Let me start with the example test case. Pretty much any test that requires a GOT will work as long as we use PC Relative and don't have a TOC.
Take `globalvar.c`:

   int glob_int=0;
  int function() {
    return glob_int;
  }

If we compile it for Power 10:

  clang -O3 -mcpu=pwr10 -c globalvar.c -fPIC
  ld.lld --shared globalvar.o -o globalvar.so

We can then dump out some information on the GOT for `globalvar.so`.

  $ llvm-readelf -r globalvar.so
  Relocation section '.rela.dyn' at offset 0x2a0 contains 1 entries:
      Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
  0000000000020380  0000000200000014 R_PPC64_GLOB_DAT       0000000000030388 glob_int + 0
  $ llvm-readelf -x .got globalvar.so
  Hex dump of section '.got':
  0x00020380 80830200 00000000                   ........

The problem with the output is that the `glob_int` is placed right at the top of the `.got` section. The TOC base is missing and according to the ABI we require it in all cases that require a `.got`.
This becomes a problem when we link `globalvar.so` later on with something that expects that TOC base to exist.

Now with respect to the suggestion you made. The `in.got->hasGotOffRel` is not set in the example from above.
The reason is that:

  R_PPC64_GOT_PCREL34	glob_int

And `R_PPC64_GOT_PCREL34` is turned into `R_GOT_PC` which is not part of: `oneof<R_GOTONLY_PC, R_GOTREL, R_PPC64_TOCBASE, R_PPC64_RELAX_TOC>(expr)`. 
This is why I added `setupPPCDelayedInit` that would run when we actively tried to add something to the GOT. We do not want to try to add a header to the GOT if the `R_GOT_PC` ends up being relaxed away and the rest of the GOT is empty.

In the past this wasn't really a problem because `.TOC.` would be defined any time we needed a GOT because we would always access the GOT with the TOC pointer. But now with PC Relative that is not the case.

I'm not sure how to proceed in this case. I have no way of knowing whether or not a GOT entry will be required when I create the `GotSection` object and I need a header in all situations where the GOT has something in it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91426/new/

https://reviews.llvm.org/D91426



More information about the llvm-commits mailing list