Commit 1981b1b6 authored by Fangrui Song's avatar Fangrui Song
Browse files

[ELF] Demote symbols in /DISCARD/ discarded sections to Undefined (#69295)



When an input section is matched by /DISCARD/ in a linker script, GNU ld
reports errors for relocations referencing symbols defined in the section:

    `.aaa' referenced in section `.bbb' of a.o: defined in discarded section `.aaa' of a.o

Implement the error by demoting eligible symbols to `Undefined` and changing
STB_WEAK to STB_GLOBAL. As a side benefit, in relocatable links, relocations
referencing symbols defined relative to /DISCARD/ discarded sections no longer
set symbol/type to zeros.

It's arguable whether a weak reference to a discarded symbol should lead to
errors. GNU ld reports an error and our demoting approach reports an error as
well.

Close #58891

Co-authored-by: default avatarBevin Hansson <bevin.hansson@ericsson.com>
parent ef0e0adc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -613,6 +613,7 @@ void LinkerScript::processSectionCommands() {
        discard(*s);
      discardSynthetic(*osec);
      osec->commands.clear();
      seenDiscard = true;
      return false;
    }

+1 −0
Original line number Diff line number Diff line
@@ -356,6 +356,7 @@ public:

  bool hasSectionsCommand = false;
  bool seenDataAlign = false;
  bool seenDiscard = false;
  bool seenRelroEnd = false;
  bool errorOnMissingSection = false;
  std::string backwardDotErr;
+1 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ static void writeCref(raw_fd_ostream &os) {
      if (isa<SharedSymbol>(sym))
        map[sym].insert(file);
      if (auto *d = dyn_cast<Defined>(sym))
        if (!d->isLocal() && (!d->section || d->section->isLive()))
        if (!d->isLocal())
          map[d].insert(file);
    }
  }
+3 −3
Original line number Diff line number Diff line
@@ -507,8 +507,7 @@ int64_t RelocationScanner::computeMipsAddend(const RelTy &rel, RelExpr expr,
template <class ELFT>
static std::string maybeReportDiscarded(Undefined &sym) {
  auto *file = dyn_cast_or_null<ObjFile<ELFT>>(sym.file);
  if (!file || !sym.discardedSecIdx ||
      file->getSections()[sym.discardedSecIdx] != &InputSection::discarded)
  if (!file || !sym.discardedSecIdx)
    return "";
  ArrayRef<typename ELFT::Shdr> objSections =
      file->template getELFShdrs<ELFT>();
@@ -1575,6 +1574,7 @@ template <class ELFT> void elf::scanRelocations() {
        scanner.template scanSection<ELFT>(*sec);
      if (part.armExidx && part.armExidx->isLive())
        for (InputSection *sec : part.armExidx->exidxSections)
          if (sec->isLive())
            scanner.template scanSection<ELFT>(*sec);
    }
  });
+10 −6
Original line number Diff line number Diff line
@@ -316,12 +316,13 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
  if (!config->warnSymbolOrdering)
    return;

  // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning
  // is emitted. It makes sense to not warn on undefined symbols.
  // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning is
  // emitted. It makes sense to not warn on undefined symbols (excluding those
  // demoted by demoteSymbols).
  //
  // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols,
  // but we don't have to be compatible here.
  if (sym->isUndefined() &&
  if (sym->isUndefined() && !cast<Undefined>(sym)->discardedSecIdx &&
      config->unresolvedSymbols == UnresolvedPolicy::Ignore)
    return;

@@ -330,9 +331,12 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {

  auto report = [&](StringRef s) { warn(toString(file) + s + sym->getName()); };

  if (sym->isUndefined())
  if (sym->isUndefined()) {
    if (cast<Undefined>(sym)->discardedSecIdx)
      report(": unable to order discarded symbol: ");
    else
      report(": unable to order undefined symbol: ");
  else if (sym->isShared())
  } else if (sym->isShared())
    report(": unable to order shared symbol: ");
  else if (d && !d->section)
    report(": unable to order absolute symbol: ");
Loading