diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 109 |
1 files changed, 97 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c9e7a917daf..e12c866def1 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -645,6 +645,12 @@ void DwarfDebug::beginModule() { (useSplitDwarf() ? SkeletonHolder : InfoHolder) .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base")); + // Create the symbol that designates the start of the DWARF v5 range list + // table. It is located past the header and before the offsets table. + if (getDwarfVersion() >= 5) + (useSplitDwarf() ? SkeletonHolder : InfoHolder) + .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base")); + for (DICompileUnit *CUNode : M->debug_compile_units()) { // FIXME: Move local imported entities into a list attached to the // subprogram, then this search won't be needed and a @@ -765,7 +771,7 @@ void DwarfDebug::finalizeModuleInfo() { SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, Sym, Sym); } - if (!SkCU->getRangeLists().empty()) { + if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) { const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol(); SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, Sym, Sym); @@ -1970,9 +1976,11 @@ void DwarfDebug::emitDebugARanges() { } } -/// Emit a single range list. +/// Emit a single range list. We handle both DWARF v5 and earlier. static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, const RangeSpanList &List) { + + auto DwarfVersion = CU->getDwarfVersion(); // Emit our symbol so we can find the beginning of the range. Asm->OutStreamer->EmitLabel(List.getSym()); // Gather all the ranges that apply to the same section so they can share @@ -1992,18 +2000,24 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, // usually consist of single regions from each of many sections // (-ffunction-sections, or just C++ inline functions) except under LTO // or optnone where there may be holes in a single CU's section - // contrubutions. + // contributions. auto *Base = CUBase; if (!Base && P.second.size() > 1 && UseDwarfRangesBaseAddressSpecifier) { BaseIsSet = true; // FIXME/use care: This may not be a useful base address if it's not // the lowest address/range in this object. Base = P.second.front()->getStart(); - Asm->OutStreamer->EmitIntValue(-1, Size); + if (DwarfVersion >= 5) + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1); + else + Asm->OutStreamer->EmitIntValue(-1, Size); Asm->OutStreamer->EmitSymbolValue(Base, Size); } else if (BaseIsSet) { BaseIsSet = false; - Asm->OutStreamer->EmitIntValue(-1, Size); + if (DwarfVersion >= 5) + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1); + else + Asm->OutStreamer->EmitIntValue(-1, Size); Asm->OutStreamer->EmitIntValue(0, Size); } @@ -2013,21 +2027,87 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, assert(Begin && "Range without a begin symbol?"); assert(End && "Range without an end symbol?"); if (Base) { - Asm->EmitLabelDifference(Begin, Base, Size); - Asm->EmitLabelDifference(End, Base, Size); + if (DwarfVersion >= 5) { + // Emit DW_RLE_offset_pair when we have a base. + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1); + Asm->EmitLabelDifferenceAsULEB128(Begin, Base); + Asm->EmitLabelDifferenceAsULEB128(End, Base); + } else { + Asm->EmitLabelDifference(Begin, Base, Size); + Asm->EmitLabelDifference(End, Base, Size); + } + } else if (DwarfVersion >= 5) { + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1); + Asm->OutStreamer->EmitSymbolValue(Begin, Size); + Asm->EmitLabelDifferenceAsULEB128(End, Begin); } else { Asm->OutStreamer->EmitSymbolValue(Begin, Size); Asm->OutStreamer->EmitSymbolValue(End, Size); } } } + if (DwarfVersion >= 5) + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1); + else { + // Terminate the list with two 0 values. + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } +} + +void DwarfDebug::emitDebugRnglists() { - // And terminate the list with two 0 values. - Asm->OutStreamer->EmitIntValue(0, Size); - Asm->OutStreamer->EmitIntValue(0, Size); + // Don't emit a rangelist table if there are no ranges. + if (llvm::all_of(CUMap, + [](const decltype(CUMap)::const_iterator::value_type &Pair) { + DwarfCompileUnit *TheCU = Pair.second; + if (auto *Skel = TheCU->getSkeleton()) + TheCU = Skel; + return TheCU->getRangeLists().empty(); + })) + return; + + assert(getDwarfVersion() >= 5 && "Dwarf version must be 5 or greater"); + // FIXME: As long as we don't support DW_RLE_base_addrx, we cannot generate + // any tables in the .debug_rnglists.dwo section. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfRnglistsSection()); + // The length is described by a starting label right after the length field + // and an end label. + MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); + // Build the range table header, which starts with the length field. + Asm->EmitLabelDifference(TableEnd, TableStart, 4); + Asm->OutStreamer->EmitLabel(TableStart); + // Version number (DWARF v5 and later). + Asm->emitInt16(getDwarfVersion()); + // Address size. + Asm->emitInt8(Asm->MAI->getCodePointerSize()); + // Segment selector size. + Asm->emitInt8(0); + + MCSymbol *RnglistTableBaseSym = + (useSplitDwarf() ? SkeletonHolder : InfoHolder).getRnglistsTableBaseSym(); + + // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the + // DW_AT_ranges attribute. Until then set the number of offsets to 0. + Asm->emitInt32(0); + Asm->OutStreamer->EmitLabel(RnglistTableBaseSym); + + // Emit the individual range lists. + for (const auto &I : CUMap) { + DwarfCompileUnit *TheCU = I.second; + if (auto *Skel = TheCU->getSkeleton()) + TheCU = Skel; + for (const RangeSpanList &List : TheCU->getRangeLists()) + emitRangeList(Asm, TheCU, List); + } + + Asm->OutStreamer->EmitLabel(TableEnd); } -/// Emit address ranges into a debug ranges section. +/// Emit address ranges into the .debug_ranges section or DWARF v5 rangelists +/// into the .debug_rnglists section. void DwarfDebug::emitDebugRanges() { if (CUMap.empty()) return; @@ -2042,6 +2122,11 @@ void DwarfDebug::emitDebugRanges() { return; } + if (getDwarfVersion() >= 5) { + emitDebugRnglists(); + return; + } + // Start the dwarf ranges section. Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); @@ -2134,7 +2219,7 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, -// DW_AT_addr_base, DW_AT_ranges_base. +// DW_AT_addr_base, DW_AT_ranges_base or DW_AT_rnglists_base. DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( |