[lld] 2b1e324 - [ELF] Change common diagnostics to report both object file location and source file location

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 28 09:38:49 PDT 2021


Author: Fangrui Song
Date: 2021-10-28T09:38:45-07:00
New Revision: 2b1e32410c5234b6245b94a99c25047c0fbf4f13

URL: https://github.com/llvm/llvm-project/commit/2b1e32410c5234b6245b94a99c25047c0fbf4f13
DIFF: https://github.com/llvm/llvm-project/commit/2b1e32410c5234b6245b94a99c25047c0fbf4f13.diff

LOG: [ELF] Change common diagnostics to report both object file location and source file location

Many diagnostics use `getErrorPlace` or `getErrorLocation` to report a location.
In the presence of line table debug information, `getErrorPlace` uses a source
file location and ignores the object file location. However, the object file
location is sometimes more useful.

This patch changes "undefined symbol" and "out of range" diagnostics to report
both object/source file locations. Other diagnostics can use similar format if
needed.

The key idea is to let `InputSectionBase::getLocation` report the object file
location and use `getSrcMsg` for source file/line information. `getSrcMsg`
doesn't leverage `STT_FILE` information yet, but I think the temporary lack of
the functionality is ok.

For the ARM "branch and link relocation" diagnostic, I arbitrarily place the
source file location at the end of the line. The diagnostic is not very common
so its formatting doesn't need to be pretty.

Differential Revision: https://reviews.llvm.org/D112518

Added: 
    

Modified: 
    lld/ELF/Arch/ARM.cpp
    lld/ELF/InputSection.cpp
    lld/ELF/Relocations.cpp
    lld/ELF/Target.cpp
    lld/ELF/Target.h
    lld/test/ELF/arm-thumb-interwork-notfunc.s
    lld/test/ELF/ppc64-error-toc-local-call.s
    lld/test/ELF/x86-64-reloc-error2.s
    lld/test/ELF/x86-64-reloc-range-debug-loc.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 759fef154154..8b5bd138b3e9 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -380,20 +380,25 @@ bool ARM::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
 // or Thumb.
 static void stateChangeWarning(uint8_t *loc, RelType relt, const Symbol &s) {
   assert(!s.isFunc());
+  const ErrorPlace place = getErrorPlace(loc);
+  std::string hint;
+  if (!place.srcLoc.empty())
+    hint = "; " + place.srcLoc;
   if (s.isSection()) {
     // Section symbols must be defined and in a section. Users cannot change
     // the type. Use the section name as getName() returns an empty string.
-    warn(getErrorLocation(loc) + "branch and link relocation: " +
-         toString(relt) + " to STT_SECTION symbol " +
-         cast<Defined>(s).section->name + " ; interworking not performed");
+    warn(place.loc + "branch and link relocation: " + toString(relt) +
+         " to STT_SECTION symbol " + cast<Defined>(s).section->name +
+         " ; interworking not performed" + hint);
   } else {
     // Warn with hint on how to alter the symbol type.
     warn(getErrorLocation(loc) + "branch and link relocation: " +
          toString(relt) + " to non STT_FUNC symbol: " + s.getName() +
          " interworking not performed; consider using directive '.type " +
          s.getName() +
-         ", %function' to give symbol type STT_FUNC if"
-         " interworking between ARM and Thumb is required");
+         ", %function' to give symbol type STT_FUNC if interworking between "
+         "ARM and Thumb is required" +
+         hint);
   }
 }
 

diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 9fe98f5b9f5c..b44791898494 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -284,32 +284,21 @@ Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) {
   return nullptr;
 }
 
-// Returns a source location string. Used to construct an error message.
+// Returns an object file location string. Used to construct an error message.
 template <class ELFT>
 std::string InputSectionBase::getLocation(uint64_t offset) {
-  std::string secAndOffset = (name + "+0x" + utohexstr(offset)).str();
+  std::string secAndOffset =
+      (name + "+0x" + Twine::utohexstr(offset) + ")").str();
 
   // We don't have file for synthetic sections.
   if (getFile<ELFT>() == nullptr)
-    return (config->outputFile + ":(" + secAndOffset + ")")
-        .str();
-
-  // First check if we can get desired values from debugging information.
-  if (Optional<DILineInfo> info = getFile<ELFT>()->getDILineInfo(this, offset))
-    return info->FileName + ":" + std::to_string(info->Line) + ":(" +
-           secAndOffset + ")";
-
-  // File->sourceFile contains STT_FILE symbol that contains a
-  // source file name. If it's missing, we use an object file name.
-  std::string srcFile = std::string(getFile<ELFT>()->sourceFile);
-  if (srcFile.empty())
-    srcFile = toString(file);
+    return (config->outputFile + ":(" + secAndOffset).str();
 
+  std::string file = toString(getFile<ELFT>());
   if (Defined *d = getEnclosingFunction<ELFT>(offset))
-    return srcFile + ":(function " + toString(*d) + ": " + secAndOffset + ")";
+    return file + ":(function " + toString(*d) + ": " + secAndOffset;
 
-  // If there's no symbol, print out the offset in the section.
-  return (srcFile + ":(" + secAndOffset + ")");
+  return file + ":(" + secAndOffset;
 }
 
 // This function is intended to be used for constructing an error message.

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 893e575f983d..6c2076f142b8 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -101,8 +101,11 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v,
   ErrorPlace errPlace = getErrorPlace(loc);
   std::string hint;
   if (rel.sym && !rel.sym->isLocal())
-    hint = "; references " + lld::toString(*rel.sym) +
-           getDefinedLocation(*rel.sym);
+    hint = "; references " + lld::toString(*rel.sym);
+  if (!errPlace.srcLoc.empty())
+    hint += "\n>>> referenced by " + errPlace.srcLoc;
+  if (rel.sym && !rel.sym->isLocal())
+    hint += getDefinedLocation(*rel.sym);
 
   if (errPlace.isec && errPlace.isec->name.startswith(".debug"))
     hint += "; consider recompiling with -fdebug-types-section to reduce size "

diff  --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index baf2c1009c3c..88d3006f9a2d 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -106,8 +106,14 @@ template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *loc) {
       assert(isa<SyntheticSection>(isec) && "No data but not synthetic?");
       continue;
     }
-    if (isecLoc <= loc && loc < isecLoc + isec->getSize())
-      return {isec, isec->template getLocation<ELFT>(loc - isecLoc) + ": "};
+    if (isecLoc <= loc && loc < isecLoc + isec->getSize()) {
+      auto objLoc = isec->template getLocation<ELFT>(loc - isecLoc);
+      // Return object file location and source file location.
+      // TODO: Refactor getSrcMsg not to take a variable.
+      Undefined dummy(nullptr, "", STB_LOCAL, 0, 0);
+      return {isec, objLoc + ": ",
+              isec->file ? isec->getSrcMsg(dummy, loc - isecLoc) : ""};
+    }
   }
   return {};
 }

diff  --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 305edf5fa5d8..abb769b25dfb 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -188,6 +188,7 @@ template <class ELFT> TargetInfo *getMipsTargetInfo();
 struct ErrorPlace {
   InputSectionBase *isec;
   std::string loc;
+  std::string srcLoc;
 };
 
 // Returns input section and corresponding source string for the given location.

diff  --git a/lld/test/ELF/arm-thumb-interwork-notfunc.s b/lld/test/ELF/arm-thumb-interwork-notfunc.s
index d6b6a3190c68..28904a59d0f4 100644
--- a/lld/test/ELF/arm-thumb-interwork-notfunc.s
+++ b/lld/test/ELF/arm-thumb-interwork-notfunc.s
@@ -45,17 +45,17 @@ _start:
  bl .thumb_target
  bl thumb_func_with_notype
  bl thumb_func_with_explicit_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x30): branch and link relocation: R_ARM_CALL to STT_SECTION symbol .arm_target ; interworking not performed
+// WARN: {{.*}}.o:(.arm_caller+0x30): branch and link relocation: R_ARM_CALL to STT_SECTION symbol .arm_target ; interworking not performed; {{.*}}.s:[[#@LINE+1]]
  blx .arm_target
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x34): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: arm_func_with_notype interworking not performed; consider using directive '.type arm_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.arm_caller+0x34): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: arm_func_with_notype interworking not performed; consider using directive '.type arm_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  blx arm_func_with_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x38): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: arm_func_with_explicit_notype interworking not performed; consider using directive '.type arm_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.arm_caller+0x38): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: arm_func_with_explicit_notype interworking not performed; consider using directive '.type arm_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  blx arm_func_with_explicit_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x3C): branch and link relocation: R_ARM_CALL to STT_SECTION symbol .thumb_target ; interworking not performed
+// WARN: {{.*}}.o:(.arm_caller+0x3c): branch and link relocation: R_ARM_CALL to STT_SECTION symbol .thumb_target ; interworking not performed; {{.*}}.s:[[#@LINE+1]]
  blx .thumb_target
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x40): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: thumb_func_with_notype interworking not performed; consider using directive '.type thumb_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.arm_caller+0x40): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: thumb_func_with_notype interworking not performed; consider using directive '.type thumb_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  blx thumb_func_with_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.arm_caller+0x44): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: thumb_func_with_explicit_notype interworking not performed; consider using directive '.type thumb_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.arm_caller+0x44): branch and link relocation: R_ARM_CALL to non STT_FUNC symbol: thumb_func_with_explicit_notype interworking not performed; consider using directive '.type thumb_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  blx thumb_func_with_explicit_notype
 
  .section .thumb_caller, "ax", %progbits
@@ -75,17 +75,17 @@ thumb_caller:
  beq.w .thumb_target
  beq.w thumb_func_with_notype
  beq.w thumb_func_with_explicit_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x30): branch and link relocation: R_ARM_THM_CALL to STT_SECTION symbol .arm_target ; interworking not performed
+// WARN: {{.*}}.o:(.thumb_caller+0x30): branch and link relocation: R_ARM_THM_CALL to STT_SECTION symbol .arm_target ; interworking not performed; {{.*}}.s:[[#@LINE+1]]
  bl .arm_target
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x34): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: arm_func_with_notype interworking not performed; consider using directive '.type arm_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.thumb_caller+0x34): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: arm_func_with_notype interworking not performed; consider using directive '.type arm_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  bl arm_func_with_notype
- // WARN: {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x38): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: arm_func_with_explicit_notype interworking not performed; consider using directive '.type arm_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+ // WARN: {{.*}}.o:(.thumb_caller+0x38): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: arm_func_with_explicit_notype interworking not performed; consider using directive '.type arm_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  bl arm_func_with_explicit_notype
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x3C): branch and link relocation: R_ARM_THM_CALL to STT_SECTION symbol .thumb_target ; interworking not performed
+// WARN: {{.*}}.o:(.thumb_caller+0x3c): branch and link relocation: R_ARM_THM_CALL to STT_SECTION symbol .thumb_target ; interworking not performed; {{.*}}.s:[[#@LINE+1]]
  bl .thumb_target
-// WARN: {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x40): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: thumb_func_with_notype interworking not performed; consider using directive '.type thumb_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// WARN: {{.*}}.o:(.thumb_caller+0x40): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: thumb_func_with_notype interworking not performed; consider using directive '.type thumb_func_with_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  bl thumb_func_with_notype
-// {{.*}}.s:[[# @LINE+1]]:(.thumb_caller+0x44): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: thumb_func_with_explicit_notype interworking not performed; consider using directive '.type thumb_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required
+// {{.*}}.o:(.thumb_caller+0x44): branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: thumb_func_with_explicit_notype interworking not performed; consider using directive '.type thumb_func_with_explicit_notype, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required; {{.*}}.s:[[#@LINE+1]]
  bl thumb_func_with_explicit_notype
  blx .arm_target
  blx arm_func_with_notype

diff  --git a/lld/test/ELF/ppc64-error-toc-local-call.s b/lld/test/ELF/ppc64-error-toc-local-call.s
index 606f6ead5463..8cb04c149496 100644
--- a/lld/test/ELF/ppc64-error-toc-local-call.s
+++ b/lld/test/ELF/ppc64-error-toc-local-call.s
@@ -8,8 +8,8 @@
 ## This test checks that the linker produces errors when it is missing the nop
 ## after a local call to a callee with st_other=1.
 
-# CHECK: (.text+0xC): call to save_callee lacks nop, can't restore toc
-# CHECK: (.text+0x1C): call to save_callee lacks nop, can't restore toc
+# CHECK:      {{.*}}.o:(.text+0xc): call to save_callee lacks nop, can't restore toc
+# CHECK-NEXT: {{.*}}.o:(.text+0x1c): call to save_callee lacks nop, can't restore toc
 
 callee:
 	.localentry	callee, 1

diff  --git a/lld/test/ELF/x86-64-reloc-error2.s b/lld/test/ELF/x86-64-reloc-error2.s
index a082a94e6adb..d1803c9e6cff 100644
--- a/lld/test/ELF/x86-64-reloc-error2.s
+++ b/lld/test/ELF/x86-64-reloc-error2.s
@@ -6,6 +6,7 @@
 ## a given location when reporting error messages.
 # CHECK: {{.*}}.o:(function func: .text.func+0x3): relocation R_X86_64_32S out of range: -281474974609120 is not in [-2147483648, 2147483647]; references func
 # CHECK-NEXT: >>> defined in {{.*}}.o
+# CHECK-EMPTY:
 
 # This mergeable section will be garbage collected. We had a crash issue in that case. Test it.
 .section .rodata.str1,"aMS", at progbits,1

diff  --git a/lld/test/ELF/x86-64-reloc-range-debug-loc.s b/lld/test/ELF/x86-64-reloc-range-debug-loc.s
index 08a49607e806..7635870061bb 100644
--- a/lld/test/ELF/x86-64-reloc-range-debug-loc.s
+++ b/lld/test/ELF/x86-64-reloc-range-debug-loc.s
@@ -3,12 +3,22 @@
 # RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj
 # RUN: not ld.lld %tabs %t.o -o /dev/null -shared 2>&1 | FileCheck %s
 
+# RUN: rm -f %t.a && llvm-ar rc %t.a %t.o
+# RUN: not ld.lld -shared %t.a %tabs -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK2
+
 ## Check we are able to report file and location from debug information
 ## when reporting such kind of errors.
-# CHECK: error: test.s:3:(.text+0x1): relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295]
+# CHECK:      error: {{.*}}.o:(.text+0x1): relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295]; references big
+# CHECK-NEXT: >>> referenced by test.s:3
+# CHECK-NEXT: >>> defined in {{.*}}abs
+
+# CHECK2:      error: {{.*}}.a({{.*}}.o):(.text+0x1): relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295]; references big
+# CHECK2-NEXT: >>> referenced by test.s:3
+# CHECK2-NEXT: >>> defined in {{.*}}abs
 
 .section .text,"ax", at progbits
-foo:
+.globl _start
+_start:
 .file 1 "test.s"
 .loc 1 3
  movl $big, %edx


        


More information about the llvm-commits mailing list