[ELF] Don't suggest an alternative spelling for a symbol in a discarded section

For undef-not-suggest.test, we currently make redundant alternative
spelling suggestions:

```
ld.lld: error: relocation refers to a discarded section: .text.foo
>>> defined in a.o
>>> section group signature: foo
>>> prevailing definition is in a.o
>>> referenced by a.o:(.rodata+0x0)
>>> did you mean:
>>> defined in: a.o

ld.lld: error: relocation refers to a symbol in a discarded section: foo
>>> defined in a.o
>>> section group signature: foo
>>> prevailing definition is in a.o
>>> referenced by a.o:(.rodata+0x8)
>>> did you mean: for
>>> defined in: a.o
```

Reviewed By: grimar, ruiu

Differential Revision: https://reviews.llvm.org/D71735
This commit is contained in:
Fangrui Song 2019-12-19 16:04:45 -08:00
parent c7c05b0c8a
commit 261b7b4a6b
2 changed files with 67 additions and 4 deletions

View File

@ -714,12 +714,19 @@ static bool canSuggestExternCForCXX(StringRef ref, StringRef def) {
// Suggest an alternative spelling of an "undefined symbol" diagnostic. Returns
// the suggested symbol, which is either in the symbol table, or in the same
// file of sym.
template <class ELFT>
static const Symbol *getAlternativeSpelling(const Undefined &sym,
std::string &pre_hint,
std::string &post_hint) {
// Build a map of local defined symbols.
DenseMap<StringRef, const Symbol *> map;
if (sym.file && !isa<SharedFile>(sym.file)) {
if (auto *file = dyn_cast_or_null<ObjFile<ELFT>>(sym.file)) {
// If sym is a symbol defined in a discarded section, maybeReportDiscarded()
// will give an error. Don't suggest an alternative spelling.
if (file && sym.discardedSecIdx != 0 &&
file->getSections()[sym.discardedSecIdx] == &InputSection::discarded)
return nullptr;
// Build a map of local defined symbols.
for (const Symbol *s : sym.file->getSymbols())
if (s->isLocal() && s->isDefined())
map.try_emplace(s->getName(), s);
@ -865,8 +872,8 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
if (correctSpelling) {
std::string pre_hint = ": ", post_hint;
if (const Symbol *corrected =
getAlternativeSpelling(cast<Undefined>(sym), pre_hint, post_hint)) {
if (const Symbol *corrected = getAlternativeSpelling<ELFT>(
cast<Undefined>(sym), pre_hint, post_hint)) {
msg += "\n>>> did you mean" + pre_hint + toString(*corrected) + post_hint;
if (corrected->file)
msg += "\n>>> defined in: " + toString(corrected->file);

View File

@ -0,0 +1,56 @@
## Check we don't suggest alternative spelling for relocations to symbols
## defined in discarded sections.
# RUN: yaml2obj %s -o %t.o
# RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck %s
# CHECK-NOT: did you mean:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
Info: foo
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .text.foo
- Name: .text.foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- Name: .rodata
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
- Name: .rela.rodata
Type: SHT_RELA
Link: .symtab
Info: .rodata
Relocations:
## Relocation which references ".text.foo". Check we don't suggest the
## section symbol for ".data", which has an empty name.
- Offset: 0x0
## .text.foo
Symbol: 1
Type: R_X86_64_64
## Relocation which references "foo". Check we don't suggest "for".
- Offset: 0x8
Symbol: foo
Type: R_X86_64_64
- Name: .data
Type: SHT_PROGBITS
Symbols:
- Name: ""
Type: STT_SECTION
Section: .text.foo
- Name: ""
Type: STT_SECTION
Section: .data
- Name: foo
Section: .text.foo
- Name: for
Section: .data