This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Add -z rel and -z rela
ClosedPublic

Authored by MaskRay on May 24 2020, 1:25 PM.

Details

Summary

LLD supports both REL and RELA for static relocations, but emits either
of REL and RELA for dynamic relocations. The relocation entry format is
specified by each psABI.

musl ld.so supports both REL and RELA. For such ld.so implementations,
REL (.rel.dyn .rel.plt) has size benefits even if the psABI chooses RELA:
sizeof(Elf64_Rel)=16 < sizeof(Elf64_Rela)=24.

  • COPY, GLOB_DAT and J[U]MP_SLOT always have 0 addend. A ld.so implementation does not need to read the implicit addend. REL is strictly better.
  • A RELATIVE has a non-zero addend. Such relocations can be packed compactly with the RELR relocation entry format, which is out of scope of this patch.
  • For other dynamic relocation types (e.g. symbolic relocation R_X86_64_64), a ld.so implementation needs to read the implicit addend. REL may have minor performance impact, because reading implicit addends forces random access reads instead of being able to blast out a bunch of writes while chasing the relocation array.

This patch adds -z rel and -z rela to change the relocation entry format
for dynamic relocations. I have tested that a -z rel produced x86-64
executable works with musl ld.so

-z rela may be useful for debugging purposes on processors whose psABIs
specify REL as the canonical format: addends can be easily read by a tool.

Diff Detail

Event Timeline

MaskRay created this revision.May 24 2020, 1:25 PM

Generally looks fine I think. Few comments from me.

lld/ELF/Driver.cpp
852

It would be more consistent with the rest code to use StringRef comparsion instead of strcmp.
E.g:

static GnuStackKind getZGnuStack(opt::InputArgList &args) {
  for (auto *arg : args.filtered_reverse(OPT_z)) {
    if (StringRef("execstack") == arg->getValue())
      return GnuStackKind::Exec;
...
lld/test/ELF/i386-zrela.s
1 ↗(On Diff #265940)

Perhaps, the name of the test should be i386-zrel-zrela.s since you test both?
(this and all other comments also applies for x86-64-zrel.s)

30 ↗(On Diff #265940)

I think you need to have just -z rela too.

43 ↗(On Diff #265940)

Does it worth to show what happens for R_386_RELATIVE?

MaskRay updated this revision to Diff 266043.May 25 2020, 9:39 AM
MaskRay marked 5 inline comments as done.
MaskRay edited the summary of this revision. (Show Details)

Address comments

lld/test/ELF/i386-zrela.s
30 ↗(On Diff #265940)

This is to show that the last of rel and rela wins.

43 ↗(On Diff #265940)

Worthy. Added

grimar accepted this revision.May 26 2020, 1:20 AM

LGTM with a last comment addressed.
Probably hold this a bit to give other people chance to look too.

lld/test/ELF/i386-zrela.s
30 ↗(On Diff #265940)

Yes, I understood that. I mean you have "-z rel -z rela" case, what is fine, but do not have a case when "-z rela" is just alone.
(what is actually a more real use case)

This revision is now accepted and ready to land.May 26 2020, 1:20 AM

LGTM with a last comment addressed.
Probably hold this a bit to give other people chance to look too.

This may be a display problem. In the latest revision https://reviews.llvm.org/D80496?id=266043 , the files are i386-zrel-zrela.s and x86-64-zrel-zrela.s , but Phabricator seems to display the old names (probably to associate with the old comments).

I'll definitely wait a bit longer to get more input. FWIW I also asked binutils and glibc https://sourceware.org/pipermail/binutils/2020-May/111244.html (it may be difficult for them due to how they organize code...)
asked FreeBSD, mentioned it in a kernel thread, etc...

LGTM with a last comment addressed.
Probably hold this a bit to give other people chance to look too.

This may be a display problem. In the latest revision https://reviews.llvm.org/D80496?id=266043 , the files are i386-zrel-zrela.s and x86-64-zrel-zrela.s , but Phabricator seems to display the old names (probably to associate with the old comments).

I see the new names using the following raw link "https://reviews.llvm.org/D80496". The "https://reviews.llvm.org/D80496?id=266043" refers to the previous diff I believe.

My /opt/google/chrome/chrome

[10] .rela.dyn         RELA            0000000000013030 013030 edc498 18   A  5   0  8

.rela.dyn has 649225 R_X86_64_RELATIVE and 1632 R_X86_64_{64,GLOB_DAT,JUMP_SLOT}.

This feature barely passes my bar for an option. I'd like to hear more from @arichardson how changing REL/RELA can help debugging.

mcgrathr accepted this revision.May 28 2020, 11:32 AM

LGTM. It might be worth mentioning in the doc/comment that REL format cannot pack the full range of addend values for all reloc types, but this only affects reloc types that lld doesn't support emitting as dynamic relocs since they are only used for TEXTRELs.

MaskRay updated this revision to Diff 267062.May 28 2020, 3:29 PM

Update comment

LGTM. It might be worth mentioning in the doc/comment that REL format cannot pack the full range of addend values for all reloc types, but this only affects reloc types that lld doesn't support emitting as dynamic relocs since they are only used for TEXTRELs.

My understanding is that text relocations describes dynamic relocations in non-SHF_WRITE sections. I do not say text relocations because we disallow such dynamic relocations from SHF_WRITE sections as well.

LGTM. It might be worth mentioning in the doc/comment that REL format cannot pack the full range of addend values for all reloc types, but this only affects reloc types that lld doesn't support emitting as dynamic relocs since they are only used for TEXTRELs.

My understanding is that text relocations describes dynamic relocations in non-SHF_WRITE sections. I do not say text relocations because we disallow such dynamic relocations from SHF_WRITE sections as well.

That's right. My point is that the existing documentation describes it as an unknown mystery while RELA even exists. The reason that RELA exists for dynamic relocations is because of the non-full-width reloc types. Since lld doesn't support any such cases, the original rationale for RELA for dynamic relocations never applies in lld. If lld did support those, then -z rel logic would need to check for and diagnose cases where REL format cannot represent the addend for a particular reloc. Since lld doesn't support TEXTRELs, those never come up and -z rel can always work.

This revision was automatically updated to reflect the committed changes.