diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -263,6 +263,9 @@ /// Get a pointer to the parsed DebugLoc object. const DWARFDebugLoclists *getDebugLocDWO(); + /// Get a pointer to the parsed DebugLoclists object. + const DWARFDebugLoclists *getDebugLoclistsDWO(); + /// Get a pointer to the parsed DebugAranges object. const DWARFDebugAranges *getDebugAranges(); diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -60,6 +60,7 @@ virtual StringRef getAbbrevDWOSection() const { return ""; } virtual const DWARFSection &getLineDWOSection() const { return Dummy; } virtual const DWARFSection &getLocDWOSection() const { return Dummy; } + virtual const DWARFSection &getLoclistsDWOSection() const { return Dummy; } virtual StringRef getStrDWOSection() const { return ""; } virtual const DWARFSection &getStrOffsetsDWOSection() const { return Dummy; diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -120,8 +120,9 @@ /// The DWARF v5 locations list section. MCSection *DwarfLoclistsSection; - /// The DWARF v5 range list section for fission. + /// The DWARF v5 range and location list sections for fission. MCSection *DwarfRnglistsDWOSection; + MCSection *DwarfLoclistsDWOSection; // These are for Fission DWP files. MCSection *DwarfCUIndexSection; @@ -297,6 +298,9 @@ MCSection *getDwarfRnglistsDWOSection() const { return DwarfRnglistsDWOSection; } + MCSection *getDwarfLoclistsDWOSection() const { + return DwarfLoclistsDWOSection; + } MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; } MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; } MCSection *getDwarfSwiftASTSection() const { return DwarfSwiftASTSection; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1136,11 +1136,13 @@ if (U.hasRangeLists()) U.addRnglistsBase(); - if (!DebugLocs.getLists().empty() && !useSplitDwarf()) { - DebugLocs.setSym(Asm->createTempSymbol("loclists_table_base")); - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, - DebugLocs.getSym(), - TLOF.getDwarfLoclistsSection()->getBeginSymbol()); + if (!DebugLocs.getLists().empty()) { + useSplitDwarf() + ? DebugLocs.setSym(Asm->createTempSymbol("loclists_dwo_table_base")) + : DebugLocs.setSym(Asm->createTempSymbol("loclists_table_base")), + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, + DebugLocs.getSym(), + TLOF.getDwarfLoclistsSection()->getBeginSymbol()); } } @@ -2453,10 +2455,22 @@ } void DwarfDebug::emitDebugLocDWO() { - for (const auto &List : DebugLocs.getLists()) { + if (DebugLocs.getLists().empty()) + return; + bool IsLocLists = getDwarfVersion() >= 5; + MCSymbol *TableEnd = nullptr; + if (IsLocLists) { Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfLocDWOSection()); + Asm->getObjFileLowering().getDwarfLoclistsDWOSection()); + TableEnd = emitLoclistsTableHeader(Asm, *this); + } + + for (const auto &List : DebugLocs.getLists()) { + if (!IsLocLists) + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLocDWOSection()); Asm->OutStreamer->EmitLabel(List.Label); + for (const auto &Entry : DebugLocs.getEntries(List)) { // GDB only supports startx_length in pre-standard split-DWARF. // (in v5 standard loclists, it currently* /only/ supports base_address + @@ -2465,15 +2479,36 @@ // * as of October 2018, at least // Ideally/in v5, this could use SectionLabels to reuse existing addresses // in the address pool to minimize object size/relocations. - Asm->emitInt8(dwarf::DW_LLE_startx_length); - unsigned idx = AddrPool.getIndex(Entry.Begin); - Asm->EmitULEB128(idx); - Asm->EmitLabelDifference(Entry.End, Entry.Begin, 4); - + if (IsLocLists) { + // .debug_loclists.dwo section emission + Asm->OutStreamer->AddComment("DW_LLE_startx_length"); + Asm->emitInt8(dwarf::DW_LLE_startx_length); + Asm->OutStreamer->AddComment(" start idx"); + Asm->EmitULEB128(AddrPool.getIndex(Entry.Begin)); + Asm->OutStreamer->AddComment(" length"); + Asm->EmitLabelDifferenceAsULEB128(Entry.End, Entry.Begin); + } else { + Asm->emitInt8(dwarf::DW_LLE_startx_length); + unsigned idx = AddrPool.getIndex(Entry.Begin); + Asm->EmitULEB128(idx); + Asm->EmitLabelDifference(Entry.End, Entry.Begin, 4); + } emitDebugLocEntryLocation(Entry, List.CU); } - Asm->emitInt8(dwarf::DW_LLE_end_of_list); + if (IsLocLists) { + // .debug_loclists section ends with DW_LLE_end_of_list. + // Both loclists v5 and + Asm->OutStreamer->AddComment("DW_LLE_end_of_list"); + Asm->emitInt8(dwarf::DW_LLE_end_of_list); + } else { + // Pre-standardized fission uses two 0 to mark + // end of the location list + Asm->OutStreamer->EmitIntValue(0, 1); + Asm->OutStreamer->EmitIntValue(0, 1); + } } + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); } struct ArangeSpan { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -391,6 +391,14 @@ 0); dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off); } + if (const auto *Off = + shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, + DObj->getLoclistsDWOSection().Data)) { + DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), + isLittleEndian(), 0); + dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off); + } + if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, DObj->getLocDWOSection().Data)) { @@ -1377,6 +1385,7 @@ DWARFSectionMap LocSection; DWARFSectionMap LoclistsSection; + DWARFSectionMap LoclistsDWOSection; DWARFSectionMap LineSection; DWARFSectionMap RangesSection; DWARFSectionMap RnglistsSection; @@ -1403,6 +1412,7 @@ return StringSwitch(Name) .Case("debug_loc", &LocSection) .Case("debug_loclists", &LoclistsSection) + .Case("debug_loclists.dwo", &LoclistsDWOSection) .Case("debug_line", &LineSection) .Case("debug_frame", &FrameSection) .Case("eh_frame", &EHFrameSection) @@ -1733,6 +1743,9 @@ const DWARFSection &getRnglistsDWOSection() const override { return RnglistsDWOSection; } + const DWARFSection &getLoclistsDWOSection() const override { + return LoclistsDWOSection; + } const DWARFSection &getAddrSection() const override { return AddrSection; } StringRef getCUIndexSection() const override { return CUIndexSection; } StringRef getGdbIndexSection() const override { return GdbIndexSection; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -118,20 +118,24 @@ return; } - bool UseLocLists = !U->isDWOUnit(); - StringRef LoclistsSectionData = - UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); + // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). + // Modern locations list (.debug_loclists) are used starting from v5. + // Ideally we should take the version from the .debug_loclists section + // header, but using CU's version for simplicity. + bool Loclistsv5 = U->getVersion() >= 5; + bool UseDWO = U->isDWOUnit(); + StringRef LoclistsSectionData; + if (Loclistsv5) + LoclistsSectionData = UseDWO ? Obj.getLoclistsDWOSection().Data + : Obj.getLoclistsSection().Data; + else + LoclistsSectionData = U->getLocSectionData(); if (!LoclistsSectionData.empty()) { DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), Obj.getAddressSize()); - - // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). - // Modern locations list (.debug_loclists) are used starting from v5. - // Ideally we should take the version from the .debug_loclists section - // header, but using CU's version for simplicity. - DumpLL(DWARFDebugLoclists::parseOneLocationList( - Data, &Offset, UseLocLists ? U->getVersion() : 4)); + DumpLL(DWARFDebugLoclists::parseOneLocationList(Data, &Offset, + U->getVersion())); } } } diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -464,6 +464,9 @@ DwarfRnglistsDWOSection = Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE); + DwarfLoclistsDWOSection = + Ctx->getELFSection(".debug_loclists.dwo", DebugSecType, ELF::SHF_EXCLUDE); + // DWP Sections DwarfCUIndexSection = Ctx->getELFSection(".debug_cu_index", DebugSecType, 0); diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-test-loclists-dwo.c b/llvm/test/DebugInfo/Inputs/dwarfdump-test-loclists-dwo.c new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Inputs/dwarfdump-test-loclists-dwo.c @@ -0,0 +1,18 @@ +// clang -c -O2 -gdwarf-5 -gsplit-dwarf dwarfdump-test-loclists-dwo.c + +#include +int func(int *ptr) { + + printf("%d\n", *ptr); + return *ptr + 5; +} + +int main(int argc, char **argv) { + + int a = 4; + int *ptr_a = &a; + + int b = func(ptr_a); + + return 0; +} diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-test-loclists-dwo.dwo b/llvm/test/DebugInfo/Inputs/dwarfdump-test-loclists-dwo.dwo new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ Addr idx 0 (w/ length 4): DW_OP_reg5 RDI +# CHECK-NEXT: DW_LLE_startx_length(0x0000000000000003, 0x0000000000000014) +# CHECK-NEXT: => Addr idx 3 (w/ length 20): DW_OP_reg3 RBX +# CHECK-NEXT DW_LLE_end_of_list () +# CHECK: 0x00000017: +# CHECK-NEXT: DW_LLE_startx_length(0x0000000000000001, 0x0000000000000006) +# CHECK-NEXT: => Addr idx 1 (w/ length 6): DW_OP_reg5 RDI +# CHECK-NEXT: DW_LLE_end_of_list () +# CHECK: 0x0000001d: +# CHECK-NEXT: DW_LLE_startx_length(0x0000000000000001, 0x000000000000000b) +# CHECK-NEXT: => Addr idx 1 (w/ length 11): DW_OP_reg4 RSI +# CHECK-NEXT: DW_LLE_end_of_list ()