Index: include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDie.h +++ include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -282,9 +282,21 @@ /// This is a utility function that checks for either the DW_AT_rnglists_base /// or DW_AT_GNU_ranges_base attribute. /// - /// \returns anm optional absolute section offset value for the attribute. + /// \returns an optional absolute section offset value for the attribute. Optional getRangesBaseAttribute() const; + /// Get the DW_AT_high_pc attribute value as an address + /// + /// In DWARF version 4 and later the high PC can be encoded as an offset from + /// the DW_AT_low_pc. This function takes care of extracting the value as an + /// address or offset and adds it to the low PC if needed and returns the + /// value as an optional in case the DIE doesn't have a DW_AT_high_pc + /// attribute. + /// + /// \param LowPC the low PC that might be needed to calculate the high PC. + /// \returns an optional address value for the attribute. + Optional getHighPC(uint64_t LowPC) const; + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. /// Returns true if both attributes are present. bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const; Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -245,21 +245,30 @@ return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base); } +Optional DWARFDie::getHighPC(uint64_t LowPC) const { + if (auto FormValue = getAttributeValue(DW_AT_high_pc)) { + if (auto Address = FormValue->getAsAddress()) { + // High PC is an address. + return Address; + } + if (auto Offset = FormValue->getAsUnsignedConstant()) { + // High PC is an offset from LowPC. + return LowPC + *Offset; + } + } + return None; +} + bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { - if (auto LowPCVal = getAttributeValueAsAddress(DW_AT_low_pc)) - LowPC = *LowPCVal; - else + auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc); + if (!LowPcAddr) return false; - - if (auto HighPCVal = getAttributeValueAsAddress(DW_AT_high_pc)) { - // High PC is an address. - HighPC = *HighPCVal; - } else if (auto Offset = getAttributeValueAsUnsignedConstant(DW_AT_high_pc)) { - // High PC is an offset from LowPC. - HighPC = LowPC + *Offset; - } else - return false; - return true; + LowPC = *LowPcAddr; + if (auto HighPcAddr = getHighPC(LowPC)) { + HighPC = *HighPcAddr; + return true; + } + return false; } DWARFAddressRangesVector Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -2134,24 +2134,16 @@ Flags |= TF_Keep; - Optional HighPcValue; - if (!(HighPcValue = DIE.getAttributeValue(dwarf::DW_AT_high_pc))) { + Optional HighPc = DIE.getHighPC(*LowPc); + if (!HighPc) { reportWarning("Function without high_pc. Range will be discarded.\n", &DIE); return Flags; } - uint64_t HighPc; - if (HighPcValue->isFormClass(DWARFFormValue::FC_Address)) { - HighPc = *HighPcValue->getAsAddress(); - } else { - assert(HighPcValue->isFormClass(DWARFFormValue::FC_Constant)); - HighPc = *LowPc + *HighPcValue->getAsUnsignedConstant(); - } - // Replace the debug map range with a more accurate one. - Ranges[*LowPc] = std::make_pair(HighPc, MyInfo.AddrAdjust); - Unit.addFunctionRange(*LowPc, HighPc, MyInfo.AddrAdjust); + Ranges[*LowPc] = std::make_pair(*HighPc, MyInfo.AddrAdjust); + Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust); return Flags; }