diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -250,11 +250,14 @@ // SHT_LLVM_CALL_GRAPH_PROFILE table ArrayRef cgProfile; + // Get cached DWARF information. + DWARFCache *getDwarf(); + private: void initializeSections(bool ignoreComdats); void initializeSymbols(); void initializeJustSymbols(); - void initializeDwarf(); + InputSectionBase *getRelocTarget(const Elf_Shdr &sec); InputSectionBase *createInputSection(const Elf_Shdr &sec); StringRef getSectionName(const Elf_Shdr &sec); @@ -282,8 +285,8 @@ // reporting. Linker may find reasonable number of errors in a // single object file, so we cache debugging information in order to // parse it only once for each object file we link. - DWARFCache *dwarf; - llvm::once_flag initDwarfLine; + std::unique_ptr dwarf; + llvm::once_flag initDwarf; }; // LazyObjFile is analogous to ArchiveFile in the sense that diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -264,9 +264,17 @@ } } -template void ObjFile::initializeDwarf() { - dwarf = make(std::make_unique( - std::make_unique>(this))); +template DWARFCache *ObjFile::getDwarf() { + llvm::call_once(initDwarf, [this]() { + dwarf = std::make_unique(std::make_unique( + std::make_unique>(this), "", + [&](Error err) { warn(getName() + ": " + toString(std::move(err))); }, + [&](Error warning) { + warn(getName() + ": " + toString(std::move(warning))); + })); + }); + + return dwarf.get(); } // Returns the pair of file name and line number describing location of data @@ -274,9 +282,7 @@ template Optional> ObjFile::getVariableLoc(StringRef name) { - llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); }); - - return dwarf->getVariableLoc(name); + return getDwarf()->getVariableLoc(name); } // Returns source line information for a given offset @@ -284,8 +290,6 @@ template Optional ObjFile::getDILineInfo(InputSectionBase *s, uint64_t offset) { - llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); }); - // Detect SectionIndex for specified section. uint64_t sectionIndex = object::SectionedAddress::UndefSection; ArrayRef sections = s->file->getSections(); @@ -298,7 +302,7 @@ // Use fake address calculated by adding section file offset and offset in // section. See comments for ObjectInfo class. - return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex); + return getDwarf()->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex); } ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -22,6 +22,7 @@ #include "Symbols.h" #include "Target.h" #include "Writer.h" +#include "lld/Common/DWARF.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" @@ -2825,14 +2826,14 @@ std::vector> nameAttrs(sections.size()); parallelForEachN(0, sections.size(), [&](size_t i) { - ObjFile *file = sections[i]->getFile(); - DWARFContext dwarf(std::make_unique>(file)); + DWARFContext *dwarf = + sections[i]->getFile()->getDwarf()->getContext(); chunks[i].sec = sections[i]; - chunks[i].compilationUnits = readCuList(dwarf); - chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); + chunks[i].compilationUnits = readCuList(*dwarf); + chunks[i].addressAreas = readAddressAreas(*dwarf, sections[i]); nameAttrs[i] = readPubNamesAndTypes( - static_cast &>(dwarf.getDWARFObj()), + static_cast &>(dwarf->getDWARFObj()), chunks[i].compilationUnits); }); diff --git a/lld/include/lld/Common/DWARF.h b/lld/include/lld/Common/DWARF.h --- a/lld/include/lld/Common/DWARF.h +++ b/lld/include/lld/Common/DWARF.h @@ -31,6 +31,8 @@ llvm::Optional> getVariableLoc(StringRef name); + llvm::DWARFContext *getContext() { return dwarf.get(); } + private: std::unique_ptr dwarf; std::vector lineTables; diff --git a/lld/test/ELF/gdb-index-invalid-ranges.s b/lld/test/ELF/gdb-index-invalid-ranges.s --- a/lld/test/ELF/gdb-index-invalid-ranges.s +++ b/lld/test/ELF/gdb-index-invalid-ranges.s @@ -5,8 +5,8 @@ # RUN: llvm-ar rc %t.a %t.o # RUN: ld.lld --gdb-index -e main %t2.o %t.a -o /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE %s -# CHECK: ld.lld: warning: {{.*}}gdb-index-invalid-ranges.s.tmp.o:(.debug_info): decoding address ranges: invalid range list entry at offset 0x10 -# ARCHIVE: ld.lld: warning: {{.*}}gdb-index-invalid-ranges.s.tmp.a(gdb-index-invalid-ranges.s.tmp.o):(.debug_info): decoding address ranges: invalid range list entry at offset 0x10 +# CHECK: ld.lld: warning: {{.*}}gdb-index-invalid-ranges.s.tmp.o:{{(\(\.debug_info\):)?}} decoding address ranges: invalid range list entry at offset 0x10 +# ARCHIVE: ld.lld: warning: {{.*}}gdb-index-invalid-ranges.s.tmp.a(gdb-index-invalid-ranges.s.tmp.o):{{(\(\.debug_info\):)?}} decoding address ranges: invalid range list entry at offset 0x10 .section .text.foo1,"ax",@progbits .globl f1 diff --git a/lld/test/ELF/gdb-index-parse-fail.s b/lld/test/ELF/gdb-index-parse-fail.s --- a/lld/test/ELF/gdb-index-parse-fail.s +++ b/lld/test/ELF/gdb-index-parse-fail.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o # RUN: ld.lld --gdb-index %t1.o -o /dev/null 2>&1 | FileCheck %s -# CHECK: warning: {{.*}}:(.debug_info): invalid reference to or invalid content in .debug_str_offsets[.dwo]: insufficient space for 32 bit header prefix +# CHECK: warning: {{.*}}:{{(\(\.debug_info\):)?}} invalid reference to or invalid content in .debug_str_offsets[.dwo]: insufficient space for 32 bit header prefix .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code