/// describes an address.
uint64_t getAttributeValueAsAddress(dwarf::Attribute Attr,
uint64_t FailValue) const;
+
+ /// Extract the specified attribute from this DIE as an address.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional value for the attribute.
+ Optional<uint64_t> getAttributeValueAsAddress(dwarf::Attribute Attr) const;
/// Extract the specified attribute from this DIE as a signed integer.
///
/// that describes a signed integer.
int64_t getAttributeValueAsSignedConstant(dwarf::Attribute Attr,
int64_t FailValue) const;
+
+ /// Extract the specified attribute from this DIE as a signed integer.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional value for the attribute.
+ Optional<int64_t>
+ getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const;
/// Extract the specified attribute from this DIE as an unsigned integer.
///
uint64_t getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr,
uint64_t FailValue) const;
+ /// Extract the specified attribute from this DIE as an unsigned integer.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional value for the attribute.
+ Optional<uint64_t>
+ getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const;
+
/// Extract the specified attribute from this DIE as absolute DIE Offset.
///
/// Extract an attribute value from this DIE only. This call doesn't look
uint64_t getAttributeValueAsReference(dwarf::Attribute Attr,
uint64_t FailValue) const;
+ /// Extract the specified attribute from this DIE as absolute DIE Offset.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional value for the attribute.
+ Optional<uint64_t> getAttributeValueAsReference(dwarf::Attribute Attr) const;
+
/// Extract the specified attribute from this DIE as absolute section offset.
///
/// Extract an attribute value from this DIE only. This call doesn't look
/// that describes a section offset.
uint64_t getAttributeValueAsSectionOffset(dwarf::Attribute Attr,
uint64_t FailValue) const;
+ /// Extract the specified attribute from this DIE as absolute section offset.
+ ///
+ /// Extract an attribute value from this DIE only. This call doesn't look
+ /// for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs.
+ ///
+ /// \param Attr the attribute to extract.
+ /// \returns an optional value for the attribute.
+ Optional<uint64_t>
+ getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const;
/// Extract the specified attribute from this DIE as the referenced DIE.
///
/// This is a utility function that checks for either the DW_AT_rnglists_base
/// or DW_AT_GNU_ranges_base attribute.
///
- /// \returns the absolute section offset value of the attribute or FailValue
- /// if the attribute doesn't exist.
- uint64_t getRangesBaseAttribute(uint64_t FailValue) const;
+ /// \returns anm optional absolute section offset value for the attribute.
+ Optional<uint64_t> getRangesBaseAttribute() const;
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
/// Returns true if both attributes are present.
#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H
#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
}
const char *getCompilationDir();
- uint64_t getDWOId();
+ Optional<uint64_t> getDWOId();
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
auto CUDIE = CU->getUnitDIE();
if (!CUDIE)
continue;
- unsigned stmtOffset = CUDIE.getAttributeValueAsSectionOffset(
- DW_AT_stmt_list, -1U);
- if (stmtOffset != -1U) {
+ if (auto StmtOffset =
+ CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::LineTable LineTable;
- LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset);
+ uint32_t Offset = *StmtOffset;
+ LineTable.parse(lineData, &getLineSection().Relocs, &Offset);
LineTable.dump(OS);
}
}
if (!UnitDIE)
return nullptr;
- unsigned stmtOffset =
- UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list, -1U);
- if (stmtOffset == -1U)
+ auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list);
+ if (!Offset)
return nullptr; // No line table for this compile unit.
- stmtOffset += U->getLineTableOffset();
+ uint32_t stmtOffset = *Offset + U->getLineTableOffset();
// See if the line table is cached.
if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
return lt;
uint64_t DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr,
uint64_t FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<uint64_t> Result = FormValue->getAsAddress();
- return Result.hasValue() ? Result.getValue() : FailValue;
+ if (auto Value = getAttributeValueAsAddress(Attr))
+ return *Value;
+ return FailValue;
+}
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsAddress();
+ return None;
}
int64_t DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr,
int64_t FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<int64_t> Result = FormValue->getAsSignedConstant();
- return Result.hasValue() ? Result.getValue() : FailValue;
+ if (auto Value = getAttributeValueAsSignedConstant(Attr))
+ return *Value;
+ return FailValue;
+}
+
+Optional<int64_t>
+DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsSignedConstant();
+ return None;
}
uint64_t
DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr,
uint64_t FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<uint64_t> Result = FormValue->getAsUnsignedConstant();
- return Result.hasValue() ? Result.getValue() : FailValue;
+ if (auto Value = getAttributeValueAsUnsignedConstant(Attr))
+ return *Value;
+ return FailValue;
+}
+
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsUnsignedConstant();
+ return None;
}
uint64_t DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr,
uint64_t FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<uint64_t> Result = FormValue->getAsReference();
- return Result.hasValue() ? Result.getValue() : FailValue;
+ if (auto Value = getAttributeValueAsReference(Attr))
+ return *Value;
+ return FailValue;
+}
+
+
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsReference();
+ return None;
}
uint64_t DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr,
uint64_t FailValue) const {
- auto FormValue = getAttributeValue(Attr);
- if (!FormValue)
- return FailValue;
- Optional<uint64_t> Result = FormValue->getAsSectionOffset();
- return Result.hasValue() ? Result.getValue() : FailValue;
+ if (auto Value = getAttributeValueAsSectionOffset(Attr))
+ return *Value;
+ return FailValue;
}
+Optional<uint64_t>
+DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const {
+ if (auto FormValue = getAttributeValue(Attr))
+ return FormValue->getAsSectionOffset();
+ return None;
+}
+
+
DWARFDie
DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
- uint32_t SpecRef = getAttributeValueAsReference(Attr, -1U);
- if (SpecRef != -1U) {
- auto SpecUnit = U->getUnitSection().getUnitForOffset(SpecRef);
+ auto SpecRef = getAttributeValueAsReference(Attr);
+ if (SpecRef) {
+ auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
if (SpecUnit)
- return SpecUnit->getDIEForOffset(SpecRef);
+ return SpecUnit->getDIEForOffset(*SpecRef);
}
return DWARFDie();
}
-uint64_t
-DWARFDie::getRangesBaseAttribute(uint64_t FailValue) const {
- auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base, -1ULL);
- if (Result != -1ULL)
+Optional<uint64_t>
+DWARFDie::getRangesBaseAttribute() const {
+ auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base);
+ if (Result)
return Result;
- return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base, FailValue);
+ return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base);
}
bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
- LowPC = getAttributeValueAsAddress(DW_AT_low_pc, -1ULL);
- if (LowPC == -1ULL)
+ if (auto LowPCVal = getAttributeValueAsAddress(DW_AT_low_pc))
+ LowPC = *LowPCVal;
+ else
return false;
- HighPC = getAttributeValueAsAddress(DW_AT_high_pc, -1ULL);
- if (HighPC == -1ULL) {
- // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
- // it represents function size.
- HighPC = getAttributeValueAsUnsignedConstant(DW_AT_high_pc, -1ULL);
- if (HighPC != -1ULL)
- HighPC += LowPC;
- }
- return (HighPC != -1ULL);
+
+ 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;
}
DWARFAddressRangesVector
return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
}
// Multiple ranges from .debug_ranges section.
- uint32_t RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges, -1U);
- if (RangesOffset != -1U) {
+ auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges);
+ if (RangesOffset) {
DWARFDebugRangeList RangeList;
- if (U->extractRangeList(RangesOffset, RangeList))
+ if (U->extractRangeList(*RangesOffset, RangeList))
return RangeList.getAbsoluteRanges(U->getBaseAddress());
}
return DWARFAddressRangesVector();
return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
}
-uint64_t DWARFUnit::getDWOId() {
- return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id,
- -1ULL);
+Optional<uint64_t> DWARFUnit::getDWOId() {
+ return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id);
}
void DWARFUnit::setDIERelations() {
// If CU DIE was just parsed, copy several attribute values from it.
if (!HasCUDie) {
DWARFDie UnitDie = getUnitDIE();
- uint64_t BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc, -1ULL);
- if (BaseAddr == -1ULL)
- BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc, 0);
- setBaseAddress(BaseAddr);
+ auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc);
+ if (!BaseAddr)
+ BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc);
+ if (BaseAddr)
+ setBaseAddress(*BaseAddr);
AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset(
DW_AT_GNU_addr_base, 0);
RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset(
}
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
- uint32_t DWORangesBase = UnitDie.getRangesBaseAttribute(0);
- DWOCU->setRangesSection(RangeSection, DWORangesBase);
+ auto DWORangesBase = UnitDie.getRangesBaseAttribute();
+ DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
return true;
}
DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
int64_t UnitPcOffset = 0;
- uint64_t OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(
- dwarf::DW_AT_low_pc, -1ULL);
- if (OrigLowPc != -1ULL)
- UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
+ auto OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc);
+ if (OrigLowPc)
+ UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
for (const auto &Attr : Attributes) {
uint32_t Offset = Attr.first.get();
std::tie(LowPcOffset, LowPcEndOffset) =
getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit);
- uint64_t LowPc =
- DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc, -1ULL);
- assert(LowPc != -1ULL && "low_pc attribute is not an address.");
- if (LowPc == -1ULL ||
+ auto LowPc = DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc);
+ assert(LowPc.hasValue() && "low_pc attribute is not an address.");
+ if (!LowPc ||
!RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
return Flags;
HighPc = *HighPcValue->getAsAddress();
} else {
assert(HighPcValue->isFormClass(DWARFFormValue::FC_Constant));
- HighPc = LowPc + *HighPcValue->getAsUnsignedConstant();
+ 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;
}
void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
DWARFContext &OrigDwarf) {
DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
- uint64_t StmtList = CUDie.getAttributeValueAsSectionOffset(
- dwarf::DW_AT_stmt_list, -1ULL);
- if (StmtList == -1ULL)
+ auto StmtList = CUDie.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list);
+ if (!StmtList)
return;
// Update the cloned DW_AT_stmt_list with the correct debug_line offset.
// Parse the original line info for the unit.
DWARFDebugLine::LineTable LineTable;
- uint32_t StmtOffset = StmtList;
+ uint32_t StmtOffset = *StmtList;
StringRef LineData = OrigDwarf.getLineSection().Data;
DataExtractor LineExtractor(LineData, OrigDwarf.isLittleEndian(),
Unit.getOrigUnit().getAddressByteSize());
}
// Finished extracting, now emit the line tables.
- uint32_t PrologueEnd = StmtList + 10 + LineTable.Prologue.PrologueLength;
+ uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength;
// FIXME: LLVM hardcodes it's prologue values. We just copy the
// prologue over and that works because we act as both producer and
// consumer. It would be nicer to have a real configurable line
Params.DWARF2LineBase = LineTable.Prologue.LineBase;
Params.DWARF2LineRange = LineTable.Prologue.LineRange;
Streamer->emitLineTableForUnit(Params,
- LineData.slice(StmtList + 4, PrologueEnd),
+ LineData.slice(*StmtList + 4, PrologueEnd),
LineTable.Prologue.MinInstLength, NewRows,
Unit.getOrigUnit().getAddressByteSize());
}
static uint64_t getDwoId(const DWARFDie &CUDie,
const DWARFUnit &Unit) {
- uint64_t DwoId =
- CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id, 0);
- if (!DwoId)
- DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id,
- 0);
- return DwoId;
+ auto DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id);
+ if (DwoId)
+ return *DwoId;
+ DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id);
+ if (DwoId)
+ return *DwoId;
+ return 0;
}
bool DwarfLinker::registerModuleReference(