Page MenuHomePhabricator

[PPC64] Sort .toc sections accessed with small code model relocs close to the .got
ClosedPublic

Authored by sfertile on Jan 18 2019, 9:54 AM.

Details

Summary

Small code model global variable access on PPC64 has a very limited range of addressing. The instructions the relocations are used on add an offset in the range [-0x8000, 0x7FFC] to the toc pointer which points to .got +0x8000, giving an addressable range of [.got, .got + 0xFFFC]. While user code can be recompiled with medium and large code models when the binary grows too large for small code model, there are small code model relocations in the crt files and libgcc.a which are typically shipped with the distros, and the ABI dictates that linkers must allow linking of relocatable object files using different code models.

To minimze the chance of relocation overflow, any file that contains a small code model relocation should have its .toc section placed closer to the .got then any .toc from a file without small code model relocations.

Diff Detail

Repository
rLLD LLVM Linker

Event Timeline

sfertile created this revision.Jan 18 2019, 9:54 AM

I am not PPC expert, but approach itself seems probably OK to me. At least I do not have good ideas on how to do what you want much simpler/better atm.
Maybe other reviewers will have something.

My comments/suggestions are below.

Also, do you know how this problem is solved by the GNU linkers?

ELF/Arch/PPC64.cpp
112

This does not seem to be clang-formatted.
Also, since you only have 3 entries here, probably it will be better to use if instead of switch.

ELF/InputFiles.h
138

then -> than

ELF/Writer.cpp
1256

I would return early.

if (Script->HasSectionsCommand)
  return;
test/ELF/Inputs/ppc64-sort-small-cm-relocs-Input2.s
24 ↗(On Diff #182537)

Seems Lfunc_end0 is not used. And I think you do not need .size set...
Also seems there are a lot of instructions that are not needed for the test. I think you could remove stw, blr, .p2align, .abiversion,
probably others.

That applies to all input files. They are a bit bulky now and it feels can be reduced significantly probably.

One more minor issue: we do not use uppercase in file names I think. Your input files contain *-Input*.

test/ELF/ppc64-sort-small-cm-relocs.s
7

Do you really need so many inputs? You have 6. Feels to be a bit excessive amount.

34

This can be written in a single line:

# RUN: echo "SECTIONS {  .text : { *(.text*) } } " > %t.script
39

Can it be just an empty script?

79

Since you're testing the order of files here, I think you can omit addresses, entsize, alignment:

# CHECK:  .got
# CHECK:   <internal>:(.got)
# CHECK:  .toc
# CHECK:     {{.*}}/ppc64-sort-small-cm-relocs.s.tmp4.o:(.toc)
...

Also, please use CHECK-NEXT too.

MaskRay added inline comments.Jan 20 2019, 11:01 PM
ELF/Arch/PPC64.cpp
112

Using a switch for 3 entries looks good to me. I guess this is an incomplete list (but enough to make some not-so-small applications able to link against libgcc.a). If it is indeed incomplete, this code deserves a comment.

I've checked some powerpc64le target which failed to link due to
libgcc/libgcc2.c:1444: relocation R_PPC64_ADDR16_DS out of range: 37088 is not in [-32768, 32767]
The relocation out-of-range issues goes away with this patch.

"Power Architecture 64-bit ELF V2 ABI Specification" published on July 16, 2015 does not give examples what relocation types may be used in small/medium/large code models... The x86-64 ABI gives a few regarding PIC/non-PIC * small/medium/large code model..

I am not PPC expert, but approach itself seems probably OK to me. At least I do not have good ideas on how to do what you want much simpler/better atm.
Maybe other reviewers will have something.

My comments/suggestions are below.

Also, do you know how this problem is solved by the GNU linkers?

Both ld.bfd and gold have the similar "small_toc_reloc" notation and binutils-gdb/gold/power.cc does similar TOC sorting (ld.bfd has a much more complicated rule).
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;hb=dff021e14a9c72380311c15a90c1a646b179b987;f=gold/powerpc.cc#l8376

ELF/Arch/PPC64.cpp
112

There are indeed a few other relocation types that need to be added. They can be added in another patch, though.

gold
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;hb=dff021e14a9c72380311c15a90c1a646b179b987;f=gold/powerpc.cc#l7291

ld.bfd
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;hb=dff021e14a9c72380311c15a90c1a646b179b987;f=bfd/elf64-ppc.c#l4395
and line 4535

c
	  if (r_type == R_PPC64_GOT_TLSLD16
	      || r_type == R_PPC64_GOT_TLSGD16
	      || r_type == R_PPC64_GOT_TPREL16_DS
	      || r_type == R_PPC64_GOT_DTPREL16_DS
	      || r_type == R_PPC64_GOT16
	      || r_type == R_PPC64_GOT16_DS)
	    {
	      htab->do_multi_toc = 1;
	      ppc64_elf_tdata (abfd)->has_small_toc_reloc = 1;
	    }

! In D56920#1364896, @MaskRay wrote:
Both ld.bfd and gold have the similar "small_toc_reloc" notation and binutils-gdb/gold/power.cc does similar TOC sorting (ld.bfd has a much more complicated rule).
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;hb=dff021e14a9c72380311c15a90c1a646b179b987;f=gold/powerpc.cc#l8376

Thanks for the info!

ELF/Writer.cpp
1254

You should probably check for Config->EMachine == EM_PPC64 here too as
.toc can be (in theory) a name of a regular section for other targets and would be simpler to do nothing at all in that case.

sfertile updated this revision to Diff 182845.Jan 21 2019, 9:03 PM

Addressed review comments and cut down the test.

sfertile marked 9 inline comments as done.Jan 21 2019, 9:30 PM
sfertile added inline comments.
ELF/Arch/PPC64.cpp
112

Thanks for looking into this, glad to hear it fixes the libgcc related relocation overflows.
I intend to add the tls related relocations as follow on patches, 1 for the GOT related ones, then a separate patch for R_PPC_TPREL16 and R_PPC64_TPREL16_DS (which I seemed to have missed when adding tls support)

test/ELF/ppc64-sort-small-cm-relocs.s
7

I've cut it down to 2 inputs with small code model relocations and 2 without (mainly to show the sorting is meant to be stable).

39

Thank you, I didn't realize an empty script was valid.

MaskRay added inline comments.Jan 21 2019, 10:08 PM
ELF/InputFiles.h
143

Placing PPC64SmallCodeModelRelocs here increases sizeof(InputFile) from 184 to 192. If you place it below bool JustSymbols = false;, the size does not change (due to padding).

I think this is OK. Let's see what Rui think about it.
(few more nits are below)

ELF/Arch/PPC64.cpp
111

This would be 2 lines instead of 7 if you would use if.

return Type == R_PPC64_GOT16 || Type == R_PPC64_TOC16 ||
       Type == R_PPC64_TOC16_DS;

It is common to use if in LLD for relocations, see: https://github.com/llvm-mirror/lld/blob/master/ELF/Arch/X86_64.cpp#L166

test/ELF/ppc64-sort-small-cm-relocs.s
19

This relies on a test suite temporary file naming rules it seems. I am not sure if it can bring any inconsistencies or troubles, I would just use
something like

*4.o(.toc*)

It should also be more consistent with our other tests I think.

66

Could you remove excessive indentations in the tests, please?

sfertile updated this revision to Diff 182927.Jan 22 2019, 8:28 AM
sfertile marked 2 inline comments as done.

Addressed second round of review comments.

sfertile marked 4 inline comments as done.Jan 22 2019, 8:30 AM
ruiu accepted this revision.Jan 22 2019, 6:00 PM

LGTM

ELF/Writer.cpp
1254

Can you add a comment describing what this code does? It doesn't have to be a complete explanation because you already added it to InputFiles.h, but something like this would help readers of the code:

.toc is allocated just after .got and is accessed using GOT-relative relocations. The addressable range is [.got, .got + 0xFFFC] if an object file is compiled with the small code model. To reduce the risk of relocation overflow, .toc contents are sorted so that sections having smaller relocation offsets are at beginning of .toc.
This revision is now accepted and ready to land.Jan 22 2019, 6:00 PM
This revision was automatically updated to reflect the committed changes.