diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -380,20 +380,25 @@ // 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(s).section->name + " ; interworking not performed"); + warn(place.loc + "branch and link relocation: " + toString(relt) + + " to STT_SECTION symbol " + cast(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 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -284,32 +284,21 @@ 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 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() == nullptr) - return (config->outputFile + ":(" + secAndOffset + ")") - .str(); - - // First check if we can get desired values from debugging information. - if (Optional info = getFile()->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()->sourceFile); - if (srcFile.empty()) - srcFile = toString(file); + return (config->outputFile + ":(" + secAndOffset).str(); + std::string file = toString(getFile()); if (Defined *d = getEnclosingFunction(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 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -101,8 +101,11 @@ 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.h b/lld/ELF/Target.h --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -188,6 +188,7 @@ 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/ELF/Target.cpp b/lld/ELF/Target.cpp --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -106,8 +106,14 @@ assert(isa(isec) && "No data but not synthetic?"); continue; } - if (isecLoc <= loc && loc < isecLoc + isec->getSize()) - return {isec, isec->template getLocation(loc - isecLoc) + ": "}; + if (isecLoc <= loc && loc < isecLoc + isec->getSize()) { + auto objLoc = isec->template getLocation(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/test/ELF/arm-thumb-interwork-notfunc.s b/lld/test/ELF/arm-thumb-interwork-notfunc.s --- a/lld/test/ELF/arm-thumb-interwork-notfunc.s +++ b/lld/test/ELF/arm-thumb-interwork-notfunc.s @@ -45,17 +45,17 @@ 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 @@ 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 --- 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 --- 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",@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 --- 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",@progbits -foo: +.globl _start +_start: .file 1 "test.s" .loc 1 3 movl $big, %edx