This is an archive of the discontinued LLVM Phabricator instance.

[ELF][PPC64] Don't report "relocation refers to a discarded section" for .toc
ClosedPublic

Authored by MaskRay on Jun 11 2019, 10:42 PM.

Details

Summary

clang (as of 2019-06-12) / gcc (as of 8.2.1) PPC64 may emit a .rela.toc
which references an embedded switch table in a discarded .rodata/.text
section. The .toc and the .rela.toc are incorrectly not placed in the
comdat.

Technically a relocation from outside the group is not allowed by the ELF spec:

A symbol table entry with STB_LOCAL binding that is defined relative
to one of a group's sections, and that is contained in a symbol table
section that is not part of the group, must be discarded if the group
members are discarded. References to this symbol table entry from
outside the group are not allowed.

Don't report errors to work around the bug.

This should fix the ppc64le-lld-multistage-test bot while linking llvm-tblgen:

ld.lld: error: relocation refers to a discarded section: .rodata._ZNK4llvm3MVT13getSizeInBitsEv
>>> defined in utils/TableGen/CMakeFiles/llvm-tblgen.dir/CodeGenRegisters.cpp.o
>>> referenced by CodeGenRegisters.cpp
>>> utils/TableGen/CMakeFiles/llvm-tblgen.dir/CodeGenRegisters.cpp.o:(.toc+0x0)

Some other PPC specific sections may have similar problems. We can blacklist more
section names when problems occur.

// A simple program that reproduces the bug.
// Note .rela.toc (outside the group) references a section symbol (STB_LOCAL) in a group.
void puts(const char *);
struct A {
  void foo(int a) {
    switch (a) {
    case 0: puts("0"); break;
    case 1: puts("1"); puts("1"); break;
    case 2: puts("2"); break;
    case 3: puts("3"); puts("4"); break;
    case 4: puts("4"); break;
    case 5: puts("5"); puts("5"); break;
    case 6: puts("6"); break;
    }
  }
  int a;
};
void foo(A x) { x.foo(x.a); }

Diff Detail

Repository
rL LLVM

Event Timeline

MaskRay created this revision.Jun 11 2019, 10:42 PM
MaskRay updated this revision to Diff 204217.Jun 11 2019, 10:47 PM
MaskRay edited the summary of this revision. (Show Details)

.

ruiu added inline comments.Jun 11 2019, 11:52 PM
ELF/Relocations.cpp
721 ↗(On Diff #204217)

Hmm, has the compiler bug fixed? At least someone needs to fix this so that the compilers don't emit wrong code.

MaskRay marked an inline comment as done.Jun 12 2019, 12:12 AM
MaskRay added inline comments.
ELF/Relocations.cpp
721 ↗(On Diff #204217)

Not yet.. Latest clang and powerpc64le gcc 6 (available on goldbolt.org) have the bug. You can find a reference from .toc to a local label in .rodata.blah (clang) or .text.blah (clang). The reference is a section relative relocation.

void puts(const char *);

struct A {
  void foo(int a) {
    switch (a) {
    case 0: puts("0"); break;
    case 1: puts("1"); puts("1"); break;
    case 2: puts("2"); break;
    case 3: puts("3"); puts("4"); break;
    case 4: puts("4"); break;
    case 5: puts("5"); puts("5"); break;
    case 6: puts("6"); break;
    }
  }
  int a;
};

void foo(A x) {
  x.foo(x.a);
}
ruiu accepted this revision.Jun 12 2019, 12:16 AM

LGTM

ELF/Relocations.cpp
721 ↗(On Diff #204217)

OK. We are not responsible for fixing the compiler issues, but we need to take a note which versions of the compilers have that bug. Please include that information to the comment.

This revision is now accepted and ready to land.Jun 12 2019, 12:16 AM
MaskRay updated this revision to Diff 204222.Jun 12 2019, 12:23 AM

Note down clang (as of 2019-06-12) and gcc (as of 8.2.1) have the bug.

MaskRay updated this revision to Diff 204223.Jun 12 2019, 12:31 AM
MaskRay edited the summary of this revision. (Show Details)

Update description

This revision was automatically updated to reflect the committed changes.