diff --git a/llvm/test/tools/dsymutil/X86/basic-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test index 4b47263b7b12..1dae3d341973 100644 --- a/llvm/test/tools/dsymutil/X86/basic-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test @@ -17,6 +17,7 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LL CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ea0) CHECK: DW_TAG_subprogram [2] * CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main") CHECK: DW_AT_decl_line [DW_FORM_data1] (23) @@ -61,6 +62,7 @@ CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ed0) CHECK: DW_TAG_base_type [4] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int") CHECK: DW_TAG_variable [7] @@ -97,6 +99,7 @@ CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40) CHECK: DW_TAG_variable [9] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val") CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000162}) diff --git a/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test index 5f85952ba201..83f35f43903b 100644 --- a/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test @@ -11,6 +11,8 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang versio CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000016] = "basic1.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000001f] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40) +CHECK: DW_AT_high_pc [DW_FORM_data4] (0x0000000b) CHECK: DW_TAG_subprogram [2] * CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40) CHECK: DW_AT_high_pc [DW_FORM_data4] (0x0000000b) @@ -40,6 +42,8 @@ CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang version 3.7.0 ") CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000003b] = "basic2.c") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f50) +CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000037) CHECK: DW_TAG_base_type [7] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000044] = "int") CHECK: DW_TAG_variable [8] @@ -74,6 +78,8 @@ CHECK: Compile Unit: {{.*}} version = 0x0004 CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang version 3.7.0 ") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000064] = "basic3.c") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90) +CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000024) CHECK: DW_TAG_variable [13] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000006d] = "val") CHECK: DW_AT_location [DW_FORM_exprloc] (<0x9> 03 04 10 00 00 01 00 00 00 ) diff --git a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test index 0fafb238ae32..7349a33b3150 100644 --- a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test @@ -11,6 +11,7 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LL CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40) CHECK: DW_TAG_subprogram [2] * CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main") CHECK: DW_AT_decl_line [DW_FORM_data1] (23) @@ -52,6 +53,7 @@ CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f50) CHECK: DW_TAG_variable [7] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int") CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063) @@ -87,6 +89,7 @@ CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)") CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c") CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs") +CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90) CHECK: DW_TAG_variable [12] CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val") CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000176}) diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index f71a01d7c626..d8d8fc1ee556 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -70,7 +70,8 @@ public: }; CompileUnit(DWARFUnit &OrigUnit) - : OrigUnit(OrigUnit), RangeAlloc(), Ranges(RangeAlloc) { + : OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), + Ranges(RangeAlloc) { Info.resize(OrigUnit.getNumDIEs()); } @@ -94,6 +95,9 @@ public: uint64_t getStartOffset() const { return StartOffset; } uint64_t getNextUnitOffset() const { return NextUnitOffset; } + uint64_t getLowPc() const { return LowPc; } + uint64_t getHighPc() const { return HighPc; } + void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; } /// \brief Compute the end offset for this unit. Must be @@ -122,6 +126,9 @@ private: uint64_t StartOffset; uint64_t NextUnitOffset; + uint64_t LowPc; + uint64_t HighPc; + /// \brief A list of attributes to fixup with the absolute offset of /// a DIE in the debug_info section. /// @@ -158,9 +165,11 @@ void CompileUnit::fixupForwardReferences() { Ref.second->setValue(Ref.first->getOffset() + getStartOffset()); } -void CompileUnit::addFunctionRange(uint64_t LowPC, uint64_t HighPC, - int64_t PCOffset) { - Ranges.insert(LowPC, HighPC, PCOffset); +void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, + int64_t PcOffset) { + Ranges.insert(FuncLowPc, FuncHighPc, PcOffset); + this->LowPc = std::min(LowPc, FuncLowPc + PcOffset); + this->HighPc = std::max(HighPc, FuncHighPc + PcOffset); } /// \brief A string table that doesn't need relocations. @@ -603,7 +612,7 @@ private: /// \brief Helper for cloneDIE. unsigned cloneScalarAttribute(DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, - const DWARFUnit &U, AttributeSpec AttrSpec, + const CompileUnit &U, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize); /// \brief Helper for cloneDIE. @@ -1258,16 +1267,27 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, const CompileUnit &Unit, AttributesInfo &Info) { - int64_t Addr = *Val.getAsAddress(&Unit.getOrigUnit()); + uint64_t Addr = *Val.getAsAddress(&Unit.getOrigUnit()); if (AttrSpec.Attr == dwarf::DW_AT_low_pc) { if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine || Die.getTag() == dwarf::DW_TAG_lexical_block) Addr += Info.PCOffset; + else if (Die.getTag() == dwarf::DW_TAG_compile_unit) { + Addr = Unit.getLowPc(); + if (Addr == UINT64_MAX) + return 0; + } } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) { - // If we have a high_pc recorded for the input DIE, use - // it. Otherwise (when no relocations where applied) just use the - // one we just decoded. - Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset; + if (Die.getTag() == dwarf::DW_TAG_compile_unit) { + if (uint64_t HighPc = Unit.getHighPc()) + Addr = HighPc; + else + return 0; + } else + // If we have a high_pc recorded for the input DIE, use + // it. Otherwise (when no relocations where applied) just use the + // one we just decoded. + Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset; } Die.addValue(static_cast(AttrSpec.Attr), @@ -1279,18 +1299,25 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec, /// \brief Clone a scalar attribute and add it to \p Die. /// \returns the size of the new attribute. unsigned DwarfLinker::cloneScalarAttribute( - DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, const DWARFUnit &U, - AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize) { + DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, + const CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, + unsigned AttrSize) { uint64_t Value; - if (AttrSpec.Form == dwarf::DW_FORM_sec_offset) + if (AttrSpec.Attr == dwarf::DW_AT_high_pc && + Die.getTag() == dwarf::DW_TAG_compile_unit) { + if (Unit.getLowPc() == -1ULL) + return 0; + // Dwarf >= 4 high_pc is an size, not an address. + Value = Unit.getHighPc() - Unit.getLowPc(); + } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset) Value = *Val.getAsSectionOffset(); else if (AttrSpec.Form == dwarf::DW_FORM_sdata) Value = *Val.getAsSignedConstant(); else if (auto OptionalValue = Val.getAsUnsignedConstant()) Value = *OptionalValue; else { - reportWarning("Unsupported scalar attribute form. Dropping attribute.", &U, - &InputDIE); + reportWarning("Unsupported scalar attribute form. Dropping attribute.", + &Unit.getOrigUnit(), &InputDIE); return 0; } Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), @@ -1337,7 +1364,7 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die, case dwarf::DW_FORM_sec_offset: case dwarf::DW_FORM_flag: case dwarf::DW_FORM_flag_present: - return cloneScalarAttribute(Die, InputDIE, U, AttrSpec, Val, AttrSize); + return cloneScalarAttribute(Die, InputDIE, Unit, AttrSpec, Val, AttrSize); default: reportWarning("Unsupported attribute form in cloneAttribute. Dropping.", &U, &InputDIE);