Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1420,12 +1420,15 @@ static bool shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint16_t Tag, bool InDebugMap, bool SkipPC, - bool InFunctionScope) { + bool InFunctionScope, bool RewriteHighPC) { switch (AttrSpec.Attr) { default: return false; - case dwarf::DW_AT_low_pc: case dwarf::DW_AT_high_pc: + if (RewriteHighPC) + return true; + [[fallthrough]]; + case dwarf::DW_AT_low_pc: case dwarf::DW_AT_ranges: return SkipPC; case dwarf::DW_AT_str_offsets_base: @@ -1444,6 +1447,13 @@ } } +static dwarf::Form getDwarfSectionOffsetForm(DWARFUnit &Unit) { + if (Unit.getVersion() >= 4) + return dwarf::Form::DW_FORM_sec_offset; + return Unit.getFormat() == dwarf::DWARF64 ? dwarf::Form::DW_FORM_data8 + : dwarf::Form::DW_FORM_data4; +} + DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, const DWARFFile &File, CompileUnit &Unit, OffsetsStringPool &StringPool, @@ -1532,6 +1542,8 @@ PCOffset = Info.AddrAdjust; AttrInfo.PCOffset = PCOffset; + bool RewriteHighPC = false; + if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) { Flags |= TF_InFunctionScope; if (!Info.InDebugMap && LLVM_LIKELY(!Update)) @@ -1541,12 +1553,18 @@ // is not, e.g., inlined functions. if ((Flags & TF_InFunctionScope) && Info.InDebugMap) Flags &= ~TF_SkipPC; + } else if (Abbrev->getTag() == dwarf::DW_TAG_compile_unit) { + // FIXME: Enable this optimization for DWARF 5 once we support + // .debug_rnglists. + RewriteHighPC = static_cast(InputDIE.find(dwarf::DW_AT_high_pc)) && + U.getVersion() <= 4; } for (const auto &AttrSpec : Abbrev->attributes()) { if (LLVM_LIKELY(!Update) && shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap, - Flags & TF_SkipPC, Flags & TF_InFunctionScope)) { + Flags & TF_SkipPC, Flags & TF_InFunctionScope, + RewriteHighPC)) { DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, U.getFormParams()); continue; @@ -1561,6 +1579,15 @@ AttrSpec, AttrSize, AttrInfo, IsLittleEndian); } + if (RewriteHighPC) { + PatchLocation Patch = + Die->addValue(DIEAlloc, dwarf::DW_AT_ranges, + getDwarfSectionOffsetForm(U), DIEInteger(UINT64_MAX)); + Unit.noteRangeAttribute(*Die, Patch); + AttrInfo.HasRanges = true; + OutOffset += U.getDwarfOffsetByteSize(); + } + // Look for accelerator entries. uint16_t Tag = InputDIE.getTag(); // FIXME: This is slightly wrong. An inline_subroutine without a @@ -1672,10 +1699,12 @@ for (const auto &RangeAttribute : Unit.getRangesAttributes()) { uint64_t Offset = RangeAttribute.get(); RangeAttribute.set(TheDwarfEmitter->getRangesSectionSize()); - if (Error E = RangeList.extract(RangeExtractor, &Offset)) { - llvm::consumeError(std::move(E)); - reportWarning("invalid range list ignored.", File); - RangeList.clear(); + if (Offset != UINT64_MAX) { + if (Error E = RangeList.extract(RangeExtractor, &Offset)) { + llvm::consumeError(std::move(E)); + reportWarning("invalid range list ignored.", File); + RangeList.clear(); + } } const auto &Entries = RangeList.getEntries(); if (!Entries.empty()) { Index: llvm/test/tools/dsymutil/ARM/obfuscated.test =================================================================== --- llvm/test/tools/dsymutil/ARM/obfuscated.test +++ llvm/test/tools/dsymutil/ARM/obfuscated.test @@ -123,48 +123,48 @@ CHECK: length: 0x00000000 PUB: .debug_pubnames contents: -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000000, unit_size = 0x00000044 -PUB: 0x0000002e "main" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000044, unit_size = 0x00000044 -PUB: 0x0000002e "one" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000088, unit_size = 0x00000044 -PUB: 0x0000002e "two" -PUB: length = 0x00000018, format = DWARF32, version = 0x0002, unit_offset = 0x000000cc, unit_size = 0x00000044 -PUB: 0x0000002e "three" -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000110, unit_size = 0x00000044 -PUB: 0x0000002e "four" -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000154, unit_size = 0x00000044 -PUB: 0x0000002e "five" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000198, unit_size = 0x00000044 -PUB: 0x0000002e "six" +PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000000, unit_size = 0x00000048 +PUB: 0x00000032 "main" +PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000048, unit_size = 0x00000048 +PUB: 0x00000032 "one" +PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000090, unit_size = 0x00000048 +PUB: 0x00000032 "two" +PUB: length = 0x00000018, format = DWARF32, version = 0x0002, unit_offset = 0x000000d8, unit_size = 0x00000048 +PUB: 0x00000032 "three" +PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000120, unit_size = 0x00000048 +PUB: 0x00000032 "four" +PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000168, unit_size = 0x00000048 +PUB: 0x00000032 "five" +PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x000001b0, unit_size = 0x00000048 +PUB: 0x00000032 "six" CHECK: .apple_names contents: CHECK: String: 0x00000091 "five" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x00000182 +CHECK-NEXT: Atom[0]: 0x0000019a CHECK-NEXT: ] CHECK: String: 0x0000009c "six" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000001c6 +CHECK-NEXT: Atom[0]: 0x000001e2 CHECK-NEXT: ] CHECK: String: 0x00000078 "three" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000000fa +CHECK-NEXT: Atom[0]: 0x0000010a CHECK-NEXT: ] CHECK: String: 0x0000006c "two" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000000b6 +CHECK-NEXT: Atom[0]: 0x000000c2 CHECK-NEXT: ] CHECK: String: 0x00000057 "main" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x0000002e +CHECK-NEXT: Atom[0]: 0x00000032 CHECK-NEXT: ] CHECK: String: 0x00000085 "four" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x0000013e +CHECK-NEXT: Atom[0]: 0x00000152 CHECK-NEXT: ] CHECK: String: 0x00000062 "one" CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x00000072 +CHECK-NEXT: Atom[0]: 0x0000007a CHECK-NEXT: ] Index: llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test =================================================================== --- llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test +++ llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test @@ -12,7 +12,8 @@ CHECK: DW_AT_stmt_list (0x00000000) CHECK: DW_AT_comp_dir ("/Inputs") CHECK: DW_AT_low_pc (0x0000000100000f40) -CHECK: DW_AT_high_pc (0x0000000100000f4b) +CHECK: DW_AT_ranges (0x00000030 +CHECK: [0x0000000100000f40, 0x0000000100000f4b)) CHECK: DW_TAG_subprogram CHECK: DW_AT_low_pc (0x0000000100000f40) CHECK: DW_AT_high_pc (0x0000000100000f4b) @@ -50,7 +51,8 @@ CHECK: DW_AT_name ("basic2.c") CHECK: DW_AT_stmt_list (0x00000044) CHECK: DW_AT_low_pc (0x0000000100000f50) -CHECK: DW_AT_high_pc (0x0000000100000f87) +CHECK: DW_AT_ranges (0x00000050 +CHECK: [0x0000000100000f50, 0x0000000100000f87)) CHECK: DW_TAG_base_type CHECK: DW_AT_name ("int") CHECK: DW_TAG_variable @@ -91,7 +93,8 @@ CHECK: DW_AT_name ("basic3.c") CHECK: DW_AT_stmt_list (0x0000009a) CHECK: DW_AT_low_pc (0x0000000100000f90) -CHECK: DW_AT_high_pc (0x0000000100000fb4) +CHECK: DW_AT_ranges (0x00000070 +CHECK: [0x0000000100000f90, 0x0000000100000fb4)) CHECK: DW_TAG_variable CHECK: DW_AT_name ("val") CHECK: DW_AT_decl_file ("/Inputs{{[/\\]}}basic3.c") Index: llvm/test/tools/dsymutil/X86/dead-stripped.cpp =================================================================== --- llvm/test/tools/dsymutil/X86/dead-stripped.cpp +++ llvm/test/tools/dsymutil/X86/dead-stripped.cpp @@ -14,7 +14,7 @@ // CHECK: DW_TAG_compile_unit // CHECK: DW_AT_low_pc -// CHECK: DW_AT_high_pc +// CHECK: DW_AT_ranges // CHECK: DW_TAG_namespace namespace N { int blah = 42; Index: llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp =================================================================== --- llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp +++ llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp @@ -28,7 +28,7 @@ // CHECK: DW_TAG_compile_unit // CHECK: DW_AT_low_pc -// CHECK: DW_AT_high_pc +// CHECK: DW_AT_ranges // CHECK: DW_TAG_subprogram // CHECK: DW_AT_name ("removed")