[lld] [lld][ELF] Use the containing symbol, not the referenced symbol, for undefined symbol errors. (PR #70800)

Bevin Hansson via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 31 06:18:46 PDT 2023


https://github.com/bevin-hansson created https://github.com/llvm/llvm-project/pull/70800

When reporting undefined symbols, the symbol being used to find
the source location for where the symbol was referenced from was
the symbol being referenced, not the symbol where the reference
was made from.

Use the relocation offset to locate the correct symbol.

With this, the following program:

```
extern int ex;

int * p[] = { &ex };

int main() {
  return 0;
}
```

When built with `clang -fuse-ld=lld a.c -g`, it goes from
```
ld.lld: error: undefined symbol: ex
>>> referenced by a.c
>>>               /tmp/a-0e7dc8.o:(p)
```
to
```
ld.lld: error: undefined symbol: ex
>>> referenced by a.c:3 ([...]/a.c:3)
>>>               /tmp/a-0e7dc8.o:(p)
```

I'm unsure how to construct a reasonable lit test for this.


>From f2d5efdb7250eaf8481c86d13a45528cb77c612c Mon Sep 17 00:00:00 2001
From: Bevin Hansson <bevin.hansson at ericsson.com>
Date: Fri, 30 Jun 2023 11:01:42 +0200
Subject: [PATCH] [lld][ELF] Use the containing symbol, not the referenced
 symbol, for undefined symbol errors.

When reporting undefined symbols, the symbol being used to find
the source location for where the symbol was referenced from was
the symbol being referenced, not the symbol where the reference
was made from.

Use the relocation offset to locate the correct symbol.

With this, the following program:

```
extern int ex;

int * p[] = { &ex };

int main() {
  return 0;
}
```

When built with `clang -fuse-ld=lld a.c -g`, it goes from
```
ld.lld: error: undefined symbol: ex
>>> referenced by a.c
>>>               /tmp/a-0e7dc8.o:(p)
```
to
```
ld.lld: error: undefined symbol: ex
>>> referenced by a.c:3 ([...]/a.c:3)
>>>               /tmp/a-0e7dc8.o:(p)
```

I'm unsure how to construct a reasonable lit test for this.
---
 lld/ELF/Relocations.cpp | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index f3fb0c71a8b3064..bf4d452f3ed9f79 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -693,6 +693,34 @@ static const Symbol *getAlternativeSpelling(const Undefined &sym,
   return nullptr;
 }
 
+static Symbol &
+getSymAtOffset(InputSectionBase &sec, uint64_t off, Symbol &sym) {
+  ArrayRef<Symbol *> syms;
+  switch (config->ekind) {
+  case ELF32LEKind:
+    syms = sec.getFile<ELF32LE>()->getSymbols();
+    break;
+  case ELF32BEKind:
+    syms = sec.getFile<ELF32BE>()->getSymbols();
+    break;
+  case ELF64LEKind:
+    syms = sec.getFile<ELF64LE>()->getSymbols();
+    break;
+  case ELF64BEKind:
+    syms = sec.getFile<ELF64BE>()->getSymbols();
+    break;
+  default:
+    llvm_unreachable("");
+  }
+  // Get the symbol that contains this offset.
+  for (Symbol *b : syms)
+    if (auto *d = dyn_cast_or_null<Defined>(b))
+      if (d->section == &sec && d->value <= off && off < d->value + d->size)
+        return *d;
+  // Fall back to the supplied symbol otherwise.
+  return sym;
+}
+
 static void reportUndefinedSymbol(const UndefinedDiag &undef,
                                   bool correctSpelling) {
   Undefined &sym = *undef.sym;
@@ -739,7 +767,7 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
     uint64_t offset = l.offset;
 
     msg += "\n>>> referenced by ";
-    std::string src = sec.getSrcMsg(sym, offset);
+    std::string src = sec.getSrcMsg(getSymAtOffset(sec, offset, sym), offset);
     if (!src.empty())
       msg += src + "\n>>>               ";
     msg += sec.getObjMsg(offset);



More information about the llvm-commits mailing list