summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp164
1 files changed, 88 insertions, 76 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 7bb0194661615..a6d44f04e4680 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -21,7 +21,6 @@
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -74,12 +73,15 @@ void DWARFUnitVector::addUnitsImpl(
DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
if (!Data.isValidOffset(Offset))
return nullptr;
- const DWARFUnitIndex *Index = nullptr;
- if (IsDWO)
- Index = &getDWARFUnitIndex(Context, SectionKind);
DWARFUnitHeader Header;
- if (!Header.extract(Context, Data, &Offset, SectionKind, Index,
- IndexEntry))
+ if (!Header.extract(Context, Data, &Offset, SectionKind))
+ return nullptr;
+ if (!IndexEntry && IsDWO) {
+ const DWARFUnitIndex &Index = getDWARFUnitIndex(
+ Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO);
+ IndexEntry = Index.getFromOffset(Header.getOffset());
+ }
+ if (IndexEntry && !Header.applyIndexEntry(IndexEntry))
return nullptr;
std::unique_ptr<DWARFUnit> U;
if (Header.isTypeUnit())
@@ -140,7 +142,7 @@ DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const {
DWARFUnit *
DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
- const auto *CUOff = E.getOffset(DW_SECT_INFO);
+ const auto *CUOff = E.getContribution(DW_SECT_INFO);
if (!CUOff)
return nullptr;
@@ -182,20 +184,17 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
if (IsDWO) {
// If we are reading a package file, we need to adjust the location list
// data based on the index entries.
- StringRef Data = LocSection->Data;
+ StringRef Data = Header.getVersion() >= 5
+ ? Context.getDWARFObj().getLoclistsDWOSection().Data
+ : LocSection->Data;
if (auto *IndexEntry = Header.getIndexEntry())
- if (const auto *C = IndexEntry->getOffset(DW_SECT_LOC))
+ if (const auto *C = IndexEntry->getContribution(
+ Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
Data = Data.substr(C->Offset, C->Length);
- DWARFDataExtractor DWARFData =
- Header.getVersion() >= 5
- ? DWARFDataExtractor(Context.getDWARFObj(),
- Context.getDWARFObj().getLoclistsDWOSection(),
- isLittleEndian, getAddressByteSize())
- : DWARFDataExtractor(Data, isLittleEndian, getAddressByteSize());
+ DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize());
LocTable =
std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
-
} else if (Header.getVersion() >= 5) {
LocTable = std::make_unique<DWARFDebugLoclists>(
DWARFDataExtractor(Context.getDWARFObj(),
@@ -255,20 +254,12 @@ Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
bool DWARFUnitHeader::extract(DWARFContext &Context,
const DWARFDataExtractor &debug_info,
uint64_t *offset_ptr,
- DWARFSectionKind SectionKind,
- const DWARFUnitIndex *Index,
- const DWARFUnitIndex::Entry *Entry) {
+ DWARFSectionKind SectionKind) {
Offset = *offset_ptr;
Error Err = Error::success();
- IndexEntry = Entry;
- if (!IndexEntry && Index)
- IndexEntry = Index->getFromOffset(*offset_ptr);
- Length = debug_info.getRelocatedValue(4, offset_ptr, nullptr, &Err);
- FormParams.Format = DWARF32;
- if (Length == dwarf::DW_LENGTH_DWARF64) {
- Length = debug_info.getU64(offset_ptr, &Err);
- FormParams.Format = DWARF64;
- }
+ IndexEntry = nullptr;
+ std::tie(Length, FormParams.Format) =
+ debug_info.getInitialLength(offset_ptr, &Err);
FormParams.Version = debug_info.getU16(offset_ptr, &Err);
if (FormParams.Version >= 5) {
UnitType = debug_info.getU8(offset_ptr, &Err);
@@ -281,22 +272,11 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err);
// Fake a unit type based on the section type. This isn't perfect,
// but distinguishing compile and type units is generally enough.
- if (SectionKind == DW_SECT_TYPES)
+ if (SectionKind == DW_SECT_EXT_TYPES)
UnitType = DW_UT_type;
else
UnitType = DW_UT_compile;
}
- if (IndexEntry) {
- if (AbbrOffset)
- return false;
- auto *UnitContrib = IndexEntry->getOffset();
- if (!UnitContrib || UnitContrib->Length != (Length + 4))
- return false;
- auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
- if (!AbbrEntry)
- return false;
- AbbrOffset = AbbrEntry->Offset;
- }
if (isTypeUnit()) {
TypeHash = debug_info.getU64(offset_ptr, &Err);
TypeOffset = debug_info.getUnsigned(
@@ -320,7 +300,7 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
TypeOffset < getLength() + getUnitLengthFieldByteSize();
bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
- bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;
+ bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize());
if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
return false;
@@ -330,6 +310,23 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
return true;
}
+bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) {
+ assert(Entry);
+ assert(!IndexEntry);
+ IndexEntry = Entry;
+ if (AbbrOffset)
+ return false;
+ auto *UnitContrib = IndexEntry->getContribution();
+ if (!UnitContrib ||
+ UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize()))
+ return false;
+ auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
+ if (!AbbrEntry)
+ return false;
+ AbbrOffset = AbbrEntry->Offset;
+ return true;
+}
+
// Parse the rangelist table header, including the optional array of offsets
// following it (DWARF v5 and later).
template<typename ListTableType>
@@ -426,15 +423,17 @@ void DWARFUnit::extractDIEsToVector(
// should always terminate at or before the start of the next compilation
// unit header).
if (DIEOffset > NextCUOffset)
- WithColor::warning() << format("DWARF compile unit extends beyond its "
- "bounds cu 0x%8.8" PRIx64 " "
- "at 0x%8.8" PRIx64 "\n",
- getOffset(), DIEOffset);
+ Context.getWarningHandler()(
+ createStringError(errc::invalid_argument,
+ "DWARF compile unit extends beyond its "
+ "bounds cu 0x%8.8" PRIx64 " "
+ "at 0x%8.8" PRIx64 "\n",
+ getOffset(), DIEOffset));
}
void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
if (Error e = tryExtractDIEsIfNeeded(CUDieOnly))
- WithColor::error() << toString(std::move(e));
+ Context.getRecoverableErrorHandler()(std::move(e));
}
Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
@@ -492,9 +491,17 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
// describe address ranges.
if (getVersion() >= 5) {
- if (IsDWO)
- setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
- else
+ // In case of DWP, the base offset from the index has to be added.
+ uint64_t ContributionBaseOffset = 0;
+ if (IsDWO) {
+ if (auto *IndexEntry = Header.getIndexEntry())
+ if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
+ ContributionBaseOffset = Contrib->Offset;
+ setRangesSection(
+ &Context.getDWARFObj().getRnglistsDWOSection(),
+ ContributionBaseOffset +
+ DWARFListTableHeader::getHeaderSize(Header.getFormat()));
+ } else
setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0));
if (RangeSection->Data.size()) {
@@ -514,19 +521,26 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
// In a split dwarf unit, there is no DW_AT_rnglists_base attribute.
// Adjust RangeSectionBase to point past the table header.
if (IsDWO && RngListTable)
- RangeSectionBase = RngListTable->getHeaderSize();
+ RangeSectionBase =
+ ContributionBaseOffset + RngListTable->getHeaderSize();
}
// In a split dwarf unit, there is no DW_AT_loclists_base attribute.
// Setting LocSectionBase to point past the table header.
- if (IsDWO)
- setLocSection(&Context.getDWARFObj().getLoclistsDWOSection(),
+ if (IsDWO) {
+ auto &DWOSection = Context.getDWARFObj().getLoclistsDWOSection();
+ if (DWOSection.Data.empty())
+ return Error::success();
+ setLocSection(&DWOSection,
DWARFListTableHeader::getHeaderSize(Header.getFormat()));
- else
+ } else if (auto X = UnitDie.find(DW_AT_loclists_base)) {
setLocSection(&Context.getDWARFObj().getLoclistsSection(),
- toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0));
+ toSectionOffset(X, 0));
+ } else {
+ return Error::success();
+ }
- if (LocSection->Data.size()) {
+ if (LocSection) {
if (IsDWO)
LoclistTableHeader.emplace(".debug_loclists.dwo", "locations");
else
@@ -542,6 +556,9 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
" list table with base = 0x%" PRIx64 "\n",
Offset);
Offset -= HeaderSize;
+ if (auto *IndexEntry = Header.getIndexEntry())
+ if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LOCLISTS))
+ Offset += Contrib->Offset;
if (Error E = LoclistTableHeader->extract(Data, &Offset))
return createStringError(errc::invalid_argument,
"parsing a loclist table: " +
@@ -596,9 +613,10 @@ bool DWARFUnit::parseDWO() {
RangesDA, RangeSectionBase, Header.getFormat()))
DWO->RngListTable = TableOrError.get();
else
- WithColor::error() << "parsing a range list table: "
- << toString(TableOrError.takeError())
- << '\n';
+ Context.getRecoverableErrorHandler()(createStringError(
+ errc::invalid_argument, "parsing a range list table: %s",
+ toString(TableOrError.takeError()).c_str()));
+
if (DWO->RngListTable)
DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
} else {
@@ -759,7 +777,7 @@ const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
DWARFSectionKind Kind) {
if (Kind == DW_SECT_INFO)
return Context.getCUIndex();
- assert(Kind == DW_SECT_TYPES);
+ assert(Kind == DW_SECT_EXT_TYPES);
return Context.getTUIndex();
}
@@ -944,18 +962,12 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
Expected<Optional<StrOffsetsContributionDescriptor>>
DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
- uint64_t Offset;
- if (IsDWO) {
- Offset = 0;
- if (DA.getData().data() == nullptr)
- return None;
- } else {
- auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base));
- if (!OptOffset)
- return None;
- Offset = *OptOffset;
- }
- auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
+ assert(!IsDWO);
+ auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base));
+ if (!OptOffset)
+ return None;
+ auto DescOrError =
+ parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset);
if (!DescOrError)
return DescOrError.takeError();
return *DescOrError;
@@ -963,10 +975,11 @@ DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
Expected<Optional<StrOffsetsContributionDescriptor>>
DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
+ assert(IsDWO);
uint64_t Offset = 0;
auto IndexEntry = Header.getIndexEntry();
const auto *C =
- IndexEntry ? IndexEntry->getOffset(DW_SECT_STR_OFFSETS) : nullptr;
+ IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr;
if (C)
Offset = C->Offset;
if (getVersion() >= 5) {
@@ -983,11 +996,10 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
// index table (in a package file). In a .dwo file it is simply
// the length of the string offsets section.
if (!IndexEntry)
- return {
- Optional<StrOffsetsContributionDescriptor>(
- {0, StringOffsetSection.Data.size(), 4, DWARF32})};
+ return {Optional<StrOffsetsContributionDescriptor>(
+ {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})};
if (C)
return {Optional<StrOffsetsContributionDescriptor>(
- {C->Offset, C->Length, 4, DWARF32})};
+ {C->Offset, C->Length, 4, Header.getFormat()})};
return None;
}