Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -69,7 +69,7 @@ public: DIHelper(InputFile *F); ~DIHelper(); - std::string getLineInfo(uintX_t Offset); + std::string getLineInfo(InputSectionBase *S, uintX_t Offset); private: std::unique_ptr DwarfLine; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/Module.h" #include "llvm/LTO/LTO.h" #include "llvm/MC/StringTableBuilder.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -36,13 +37,38 @@ std::vector InputFile::Pool; -template DIHelper::DIHelper(elf::InputFile *F) { +namespace { +// In ELF object file all section addresses are zero. If we have multiple +// .text sections (when using -ffunction-section or comdat group) then +// LLVM DWARF parser will not be able to parse .debug_line correctly, unless +// we assign each section some unique address. This callback method assigns +// each section an address equal to its offset in ELF object file. +class ObjectInfo : public LoadedObjectInfo { +public: + uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override; + std::unique_ptr clone() const override; +}; +} + +uint64_t +ObjectInfo::getSectionLoadAddress(const object::SectionRef &Sec) const { + + const ELFSectionRef &ELFSec = static_cast(Sec); + return ELFSec.getOffset(); +} + +std::unique_ptr ObjectInfo::clone() const { + return std::unique_ptr(); +} + +template DIHelper::DIHelper(InputFile *F) { Expected> Obj = object::ObjectFile::createObjectFile(F->MB); if (!Obj) return; - DWARFContextInMemory Dwarf(*Obj.get()); + ObjectInfo ObjInfo; + DWARFContextInMemory Dwarf(*Obj.get(), &ObjInfo); DwarfLine.reset(new DWARFDebugLine(&Dwarf.getLineSection().Relocs)); DataExtractor LineData(Dwarf.getLineSection().Data, ELFT::TargetEndianness == support::little, @@ -55,7 +81,9 @@ template DIHelper::~DIHelper() {} -template std::string DIHelper::getLineInfo(uintX_t Offset) { +template +std::string DIHelper::getLineInfo(InputSectionBase *S, + uintX_t Offset) { if (!DwarfLine) return ""; @@ -65,7 +93,12 @@ const DWARFDebugLine::LineTable *LineTbl = DwarfLine->getLineTable(0); if (!LineTbl) return ""; - LineTbl->getFileLineInfoForAddress(Offset, nullptr, Spec.FLIKind, LineInfo); + + // Use fake address calcuated by adding section file offset and offset in + // section. + // See comments for ObjectInfo class + LineTbl->getFileLineInfoForAddress(S->Offset + Offset, nullptr, Spec.FLIKind, + LineInfo); return LineInfo.Line != 0 ? LineInfo.FileName + " (" + std::to_string(LineInfo.Line) + ")" : ""; Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -88,6 +88,7 @@ public: // These corresponds to the fields in Elf_Shdr. uintX_t Flags; + uintX_t Offset = 0; uintX_t Entsize; uint32_t Type; uint32_t Link; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -75,7 +75,9 @@ Kind SectionKind) : InputSectionBase(File, Hdr->sh_flags, Hdr->sh_type, Hdr->sh_entsize, Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, - getSectionContents(File, Hdr), Name, SectionKind) {} + getSectionContents(File, Hdr), Name, SectionKind) { + this->Offset = Hdr->sh_offset; +} template size_t InputSectionBase::getSize() const { if (auto *D = dyn_cast>(this)) Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -544,7 +544,7 @@ ObjectFile *File = S.getFile(); // First check if we can get desired values from debugging information. - std::string LineInfo = File->getDIHelper()->getLineInfo(Offset); + std::string LineInfo = File->getDIHelper()->getLineInfo(&S, Offset); if (!LineInfo.empty()) return LineInfo; Index: test/ELF/Inputs/undef-debug.s =================================================================== --- test/ELF/Inputs/undef-debug.s +++ test/ELF/Inputs/undef-debug.s @@ -1,3 +1,11 @@ .file 1 "undef-debug.s" .loc 1 3 .quad zed3 + +.section .text.1,"ax" +.loc 1 7 + .quad zed4 + +.section .text.2,"ax" +.loc 1 11 + .quad zed5 Index: test/ELF/undef.s =================================================================== --- test/ELF/undef.s +++ test/ELF/undef.s @@ -10,6 +10,8 @@ # CHECK: error: undef.s (.text+0x10): undefined symbol 'foo(int)' # CHECK: error: {{.*}}2.a({{.*}}.o) (.text+0x0): undefined symbol 'zed2' # CHECK: error: undef-debug.s (3): undefined symbol 'zed3' +# CHECK: error: undef-debug.s (7): undefined symbol 'zed4' +# CHECK: error: undef-debug.s (11): undefined symbol 'zed5' # RUN: not ld.lld %t.o %t2.a -o %t.exe -no-demangle 2>&1 | \ # RUN: FileCheck -check-prefix=NO-DEMANGLE %s