aboutsummaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
committerStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
commitdce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch)
treedcebc53f2b182f145a2e659393bf9a0472cedf23 /lib/DebugInfo
parent220b921aed042f9e520c26cffd8282a94c66c3d5 (diff)
downloadexternal_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h6
-rw-r--r--lib/DebugInfo/DWARFContext.cpp246
-rw-r--r--lib/DebugInfo/DWARFContext.h2
-rw-r--r--lib/DebugInfo/DWARFDebugAbbrev.cpp112
-rw-r--r--lib/DebugInfo/DWARFDebugAbbrev.h50
-rw-r--r--lib/DebugInfo/DWARFDebugArangeSet.h1
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.cpp36
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.h17
-rw-r--r--lib/DebugInfo/DWARFDebugFrame.cpp72
-rw-r--r--lib/DebugInfo/DWARFDebugFrame.h6
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp95
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h57
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp348
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h109
-rw-r--r--lib/DebugInfo/DWARFDebugRangeList.cpp15
-rw-r--r--lib/DebugInfo/DWARFDebugRangeList.h15
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp10
-rw-r--r--lib/DebugInfo/DWARFTypeUnit.h10
-rw-r--r--lib/DebugInfo/DWARFUnit.cpp145
-rw-r--r--lib/DebugInfo/DWARFUnit.h24
-rw-r--r--lib/DebugInfo/module.modulemap1
21 files changed, 673 insertions, 704 deletions
diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h
index d1853d8..2ed188e 100644
--- a/lib/DebugInfo/DWARFCompileUnit.h
+++ b/lib/DebugInfo/DWARFCompileUnit.h
@@ -16,10 +16,10 @@ namespace llvm {
class DWARFCompileUnit : public DWARFUnit {
public:
- DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
- StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS,
+ StringRef SS, StringRef SOS, StringRef AOS,
const RelocAddrMap *M, bool LE)
- : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {}
+ : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {}
void dump(raw_ostream &OS);
// VTable anchor.
~DWARFCompileUnit() override;
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 60c5f6a..e52e8af 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "DWARFContext.h"
+#include "DWARFDebugArangeSet.h"
+
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compression.h"
@@ -20,7 +22,11 @@ using namespace llvm;
using namespace dwarf;
using namespace object;
+#define DEBUG_TYPE "dwarf"
+
typedef DWARFDebugLine::LineTable DWARFLineTable;
+typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
+typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
bool LittleEndian, bool GnuStyle) {
@@ -126,8 +132,9 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
- DWARFDebugLine::DumpingState state(OS);
- DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state);
+ DWARFDebugLine::LineTable LineTable;
+ LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset);
+ LineTable.dump(OS);
}
}
}
@@ -137,9 +144,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
unsigned stmtOffset = 0;
DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(),
savedAddressByteSize);
- DWARFDebugLine::DumpingState state(OS);
- while (DWARFDebugLine::parsePrologue(lineData, &stmtOffset, &state.Prologue))
- state.finalize();
+ DWARFDebugLine::LineTable LineTable;
+ while (LineTable.Prologue.parse(lineData, &stmtOffset)) {
+ LineTable.dump(OS);
+ LineTable.clear();
+ }
}
if (DumpType == DIDT_All || DumpType == DIDT_Str) {
@@ -216,7 +225,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
Abbrev.reset(new DWARFDebugAbbrev());
- Abbrev->parse(abbrData);
+ Abbrev->extract(abbrData);
return Abbrev.get();
}
@@ -226,7 +235,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
AbbrevDWO.reset(new DWARFDebugAbbrev());
- AbbrevDWO->parse(abbrData);
+ AbbrevDWO->extract(abbrData);
return AbbrevDWO.get();
}
@@ -290,7 +299,7 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
cu, DW_AT_stmt_list, -1U);
if (stmtOffset == -1U)
- return 0; // No line table for this compile unit.
+ return nullptr; // No line table for this compile unit.
// See if the line table is cached.
if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
@@ -310,8 +319,8 @@ void DWARFContext::parseCompileUnits() {
isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
std::unique_ptr<DWARFCompileUnit> CU(new DWARFCompileUnit(
- getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(),
- getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
+ getDebugAbbrev(), getInfoSection().Data, getRangeSection(),
+ getStringSection(), StringRef(), getAddrSection(),
&getInfoSection().Relocs, isLittleEndian()));
if (!CU->extract(DIData, &offset)) {
break;
@@ -329,10 +338,10 @@ void DWARFContext::parseTypeUnits() {
const DataExtractor &DIData =
DataExtractor(I.second.Data, isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit(
- getDebugAbbrev(), I.second.Data, getAbbrevSection(),
- getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
- &I.second.Relocs, isLittleEndian()));
+ std::unique_ptr<DWARFTypeUnit> TU(
+ new DWARFTypeUnit(getDebugAbbrev(), I.second.Data, getRangeSection(),
+ getStringSection(), StringRef(), getAddrSection(),
+ &I.second.Relocs, isLittleEndian()));
if (!TU->extract(DIData, &offset))
break;
TUs.push_back(std::move(TU));
@@ -349,9 +358,8 @@ void DWARFContext::parseDWOCompileUnits() {
DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
std::unique_ptr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit(
- getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(),
- getRangeDWOSection(), getStringDWOSection(),
- getStringOffsetDWOSection(), getAddrSection(),
+ getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(),
+ getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(),
&getInfoDWOSection().Relocs, isLittleEndian()));
if (!DWOCU->extract(DIData, &offset)) {
break;
@@ -370,10 +378,9 @@ void DWARFContext::parseDWOTypeUnits() {
DataExtractor(I.second.Data, isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit(
- getDebugAbbrevDWO(), I.second.Data, getAbbrevDWOSection(),
- getRangeDWOSection(), getStringDWOSection(),
- getStringOffsetDWOSection(), getAddrSection(), &I.second.Relocs,
- isLittleEndian()));
+ getDebugAbbrevDWO(), I.second.Data, getRangeDWOSection(),
+ getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(),
+ &I.second.Relocs, isLittleEndian()));
if (!TU->extract(DIData, &offset))
break;
DWOTUs.push_back(std::move(TU));
@@ -408,7 +415,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
if (CU != CUs.end()) {
return CU->get();
}
- return 0;
+ return nullptr;
}
DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
@@ -420,15 +427,13 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
static bool getFileNameForCompileUnit(DWARFCompileUnit *CU,
const DWARFLineTable *LineTable,
- uint64_t FileIndex,
- bool NeedsAbsoluteFilePath,
+ uint64_t FileIndex, FileLineInfoKind Kind,
std::string &FileName) {
- if (CU == 0 ||
- LineTable == 0 ||
- !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath,
- FileName))
+ if (!CU || !LineTable || Kind == FileLineInfoKind::None ||
+ !LineTable->getFileNameByIndex(FileIndex, Kind, FileName))
return false;
- if (NeedsAbsoluteFilePath && sys::path::is_relative(FileName)) {
+ if (Kind == FileLineInfoKind::AbsoluteFilePath &&
+ sys::path::is_relative(FileName)) {
// We may still need to append compilation directory of compile unit.
SmallString<16> AbsolutePath;
if (const char *CompilationDir = CU->getCompilationDir()) {
@@ -443,10 +448,9 @@ static bool getFileNameForCompileUnit(DWARFCompileUnit *CU,
static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
const DWARFLineTable *LineTable,
uint64_t Address,
- bool NeedsAbsoluteFilePath,
- std::string &FileName,
- uint32_t &Line, uint32_t &Column) {
- if (CU == 0 || LineTable == 0)
+ FileLineInfoKind Kind,
+ DILineInfo &Result) {
+ if (!CU || !LineTable)
return false;
// Get the index of row we're looking for in the line table.
uint32_t RowIndex = LineTable->lookupAddress(Address);
@@ -454,80 +458,71 @@ static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
return false;
// Take file number and line/column from the row.
const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
- if (!getFileNameForCompileUnit(CU, LineTable, Row.File,
- NeedsAbsoluteFilePath, FileName))
+ if (!getFileNameForCompileUnit(CU, LineTable, Row.File, Kind,
+ Result.FileName))
return false;
- Line = Row.Line;
- Column = Row.Column;
+ Result.Line = Row.Line;
+ Result.Column = Row.Column;
return true;
}
+static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
+ FunctionNameKind Kind,
+ std::string &FunctionName) {
+ if (Kind == FunctionNameKind::None)
+ return false;
+ // The address may correspond to instruction in some inlined function,
+ // so we have to build the chain of inlined functions and take the
+ // name of the topmost function in it.
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.DIEs.size() == 0)
+ return false;
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name =
+ TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) {
+ FunctionName = Name;
+ return true;
+ }
+ return false;
+}
+
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
- DILineInfoSpecifier Specifier) {
+ DILineInfoSpecifier Spec) {
+ DILineInfo Result;
+
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
if (!CU)
- return DILineInfo();
- std::string FileName = "<invalid>";
- std::string FunctionName = "<invalid>";
- uint32_t Line = 0;
- uint32_t Column = 0;
- if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
- // The address may correspond to instruction in some inlined function,
- // so we have to build the chain of inlined functions and take the
- // name of the topmost function in it.
- const DWARFDebugInfoEntryInlinedChain &InlinedChain =
- CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
- FunctionName = Name;
- }
- }
- if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
+ return Result;
+ getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
+ if (Spec.FLIKind != FileLineInfoKind::None) {
const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
- const bool NeedsAbsoluteFilePath =
- Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
- getFileLineInfoForCompileUnit(CU, LineTable, Address,
- NeedsAbsoluteFilePath,
- FileName, Line, Column);
+ getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, Result);
}
- return DILineInfo(StringRef(FileName), StringRef(FunctionName),
- Line, Column);
+ return Result;
}
-DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
- uint64_t Size,
- DILineInfoSpecifier Specifier) {
+DILineInfoTable
+DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+ DILineInfoSpecifier Spec) {
DILineInfoTable Lines;
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
if (!CU)
return Lines;
std::string FunctionName = "<invalid>";
- if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
- // The address may correspond to instruction in some inlined function,
- // so we have to build the chain of inlined functions and take the
- // name of the topmost function in it.
- const DWARFDebugInfoEntryInlinedChain &InlinedChain =
- CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
- FunctionName = Name;
- }
- }
+ getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
// If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address.
- if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- Lines.push_back(
- std::make_pair(Address, DILineInfo("<invalid>", FunctionName, 0, 0)));
+ if (Spec.FLIKind == FileLineInfoKind::None) {
+ DILineInfo Result;
+ Result.FunctionName = FunctionName;
+ Lines.push_back(std::make_pair(Address, Result));
return Lines;
}
const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
- const bool NeedsAbsoluteFilePath =
- Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
// Get the index of row we're looking for in the line table.
std::vector<uint32_t> RowVector;
@@ -537,59 +532,67 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
for (uint32_t RowIndex : RowVector) {
// Take file number and line/column from the row.
const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
- std::string FileName = "<invalid>";
- getFileNameForCompileUnit(CU, LineTable, Row.File,
- NeedsAbsoluteFilePath, FileName);
- Lines.push_back(std::make_pair(
- Row.Address, DILineInfo(FileName, FunctionName, Row.Line, Row.Column)));
+ DILineInfo Result;
+ getFileNameForCompileUnit(CU, LineTable, Row.File, Spec.FLIKind,
+ Result.FileName);
+ Result.FunctionName = FunctionName;
+ Result.Line = Row.Line;
+ Result.Column = Row.Column;
+ Lines.push_back(std::make_pair(Row.Address, Result));
}
return Lines;
}
-DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
- DILineInfoSpecifier Specifier) {
+DIInliningInfo
+DWARFContext::getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Spec) {
+ DIInliningInfo InliningInfo;
+
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
if (!CU)
- return DIInliningInfo();
+ return InliningInfo;
+ const DWARFLineTable *LineTable = nullptr;
const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() == 0)
- return DIInliningInfo();
+ if (InlinedChain.DIEs.size() == 0) {
+ // If there is no DIE for address (e.g. it is in unavailable .dwo file),
+ // try to at least get file/line info from symbol table.
+ if (Spec.FLIKind != FileLineInfoKind::None) {
+ DILineInfo Frame;
+ LineTable = getLineTableForCompileUnit(CU);
+ if (getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind,
+ Frame)) {
+ InliningInfo.addFrame(Frame);
+ }
+ }
+ return InliningInfo;
+ }
- DIInliningInfo InliningInfo;
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
- const DWARFLineTable *LineTable = 0;
for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
- std::string FileName = "<invalid>";
- std::string FunctionName = "<invalid>";
- uint32_t Line = 0;
- uint32_t Column = 0;
+ DILineInfo Frame;
// Get function name if necessary.
- if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
- if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U))
- FunctionName = Name;
- }
- if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- const bool NeedsAbsoluteFilePath =
- Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
+ if (const char *Name =
+ FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind))
+ Frame.FunctionName = Name;
+ if (Spec.FLIKind != FileLineInfoKind::None) {
if (i == 0) {
// For the topmost frame, initialize the line table of this
// compile unit and fetch file/line info from it.
LineTable = getLineTableForCompileUnit(CU);
// For the topmost routine, get file/line info from line table.
- getFileLineInfoForCompileUnit(CU, LineTable, Address,
- NeedsAbsoluteFilePath,
- FileName, Line, Column);
+ getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind,
+ Frame);
} else {
// Otherwise, use call file, call line and call column from
// previous DIE in inlined chain.
- getFileNameForCompileUnit(CU, LineTable, CallFile,
- NeedsAbsoluteFilePath, FileName);
- Line = CallLine;
- Column = CallColumn;
+ getFileNameForCompileUnit(CU, LineTable, CallFile, Spec.FLIKind,
+ Frame.FileName);
+ Frame.Line = CallLine;
+ Frame.Column = CallColumn;
}
// Get call file/line/column of a current DIE.
if (i + 1 < n) {
@@ -597,8 +600,6 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
CallColumn);
}
}
- DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
- Line, Column);
InliningInfo.addFrame(Frame);
}
return InliningInfo;
@@ -637,14 +638,15 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj)
if (!zlib::isAvailable() ||
!consumeCompressedDebugSectionHeader(data, OriginalSize))
continue;
- std::unique_ptr<MemoryBuffer> UncompressedSection;
- if (zlib::uncompress(data, UncompressedSection, OriginalSize) !=
- zlib::StatusOK)
+ UncompressedSections.resize(UncompressedSections.size() + 1);
+ if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
+ zlib::StatusOK) {
+ UncompressedSections.pop_back();
continue;
+ }
// Make data point to uncompressed section contents and save its contents.
name = name.substr(1);
- data = UncompressedSection->getBuffer();
- UncompressedSections.push_back(std::move(UncompressedSection));
+ data = UncompressedSections.back();
}
StringRef *SectionData =
@@ -669,7 +671,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
.Case("debug_addr", &AddrSection)
// Any more debug info sections go here.
- .Default(0);
+ .Default(nullptr);
if (SectionData) {
*SectionData = data;
if (name == "debug_ranges") {
@@ -700,7 +702,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj)
.Case("debug_loc", &LocSection.Relocs)
.Case("debug_info.dwo", &InfoDWOSection.Relocs)
.Case("debug_line", &LineSection.Relocs)
- .Default(0);
+ .Default(nullptr);
if (!Map) {
// Find debug_types relocs by section rather than name as there are
// multiple, comdat grouped, debug_types sections.
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index ad6841a..6d1ae92 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -242,7 +242,7 @@ class DWARFContextInMemory : public DWARFContext {
StringRef RangeDWOSection;
StringRef AddrSection;
- SmallVector<std::unique_ptr<MemoryBuffer>, 4> UncompressedSections;
+ SmallVector<SmallString<32>, 4> UncompressedSections;
public:
DWARFContextInMemory(object::ObjectFile *);
diff --git a/lib/DebugInfo/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARFDebugAbbrev.cpp
index fd5f5e9..8426bf9 100644
--- a/lib/DebugInfo/DWARFDebugAbbrev.cpp
+++ b/lib/DebugInfo/DWARFDebugAbbrev.cpp
@@ -12,24 +12,36 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data,
- uint32_t* offset_ptr) {
- const uint32_t beginOffset = *offset_ptr;
- Offset = beginOffset;
+DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
clear();
- DWARFAbbreviationDeclaration abbrevDeclaration;
- uint32_t prevAbbrAode = 0;
- while (abbrevDeclaration.extract(data, offset_ptr)) {
- Decls.push_back(abbrevDeclaration);
- if (IdxOffset == 0) {
- IdxOffset = abbrevDeclaration.getCode();
+}
+
+void DWARFAbbreviationDeclarationSet::clear() {
+ Offset = 0;
+ FirstAbbrCode = 0;
+ Decls.clear();
+}
+
+bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
+ uint32_t *OffsetPtr) {
+ clear();
+ const uint32_t BeginOffset = *OffsetPtr;
+ Offset = BeginOffset;
+ DWARFAbbreviationDeclaration AbbrDecl;
+ uint32_t PrevAbbrCode = 0;
+ while (AbbrDecl.extract(Data, OffsetPtr)) {
+ Decls.push_back(AbbrDecl);
+ if (FirstAbbrCode == 0) {
+ FirstAbbrCode = AbbrDecl.getCode();
} else {
- if (prevAbbrAode + 1 != abbrevDeclaration.getCode())
- IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups
+ if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
+ // Codes are not consecutive, can't do O(1) lookups.
+ FirstAbbrCode = UINT32_MAX;
+ }
}
- prevAbbrAode = abbrevDeclaration.getCode();
+ PrevAbbrCode = AbbrDecl.getCode();
}
- return beginOffset != *offset_ptr;
+ return BeginOffset != *OffsetPtr;
}
void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
@@ -37,67 +49,67 @@ void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
Decl.dump(OS);
}
-const DWARFAbbreviationDeclaration*
-DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode)
- const {
- if (IdxOffset == UINT32_MAX) {
+const DWARFAbbreviationDeclaration *
+DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
+ uint32_t AbbrCode) const {
+ if (FirstAbbrCode == UINT32_MAX) {
for (const auto &Decl : Decls) {
- if (Decl.getCode() == abbrCode)
+ if (Decl.getCode() == AbbrCode)
return &Decl;
}
- } else {
- uint32_t idx = abbrCode - IdxOffset;
- if (idx < Decls.size())
- return &Decls[idx];
+ return nullptr;
}
- return NULL;
+ if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
+ return nullptr;
+ return &Decls[AbbrCode - FirstAbbrCode];
}
-DWARFDebugAbbrev::DWARFDebugAbbrev() :
- AbbrevCollMap(),
- PrevAbbrOffsetPos(AbbrevCollMap.end()) {}
-
+DWARFDebugAbbrev::DWARFDebugAbbrev() {
+ clear();
+}
-void DWARFDebugAbbrev::parse(DataExtractor data) {
- uint32_t offset = 0;
+void DWARFDebugAbbrev::clear() {
+ AbbrDeclSets.clear();
+ PrevAbbrOffsetPos = AbbrDeclSets.end();
+}
- while (data.isValidOffset(offset)) {
- uint32_t initial_cu_offset = offset;
- DWARFAbbreviationDeclarationSet abbrevDeclSet;
+void DWARFDebugAbbrev::extract(DataExtractor Data) {
+ clear();
- if (abbrevDeclSet.extract(data, &offset))
- AbbrevCollMap[initial_cu_offset] = abbrevDeclSet;
- else
+ uint32_t Offset = 0;
+ DWARFAbbreviationDeclarationSet AbbrDecls;
+ while (Data.isValidOffset(Offset)) {
+ uint32_t CUAbbrOffset = Offset;
+ if (!AbbrDecls.extract(Data, &Offset))
break;
+ AbbrDeclSets[CUAbbrOffset] = AbbrDecls;
}
- PrevAbbrOffsetPos = AbbrevCollMap.end();
}
void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
- if (AbbrevCollMap.empty()) {
+ if (AbbrDeclSets.empty()) {
OS << "< EMPTY >\n";
return;
}
- for (const auto &I : AbbrevCollMap) {
+ for (const auto &I : AbbrDeclSets) {
OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
I.second.dump(OS);
}
}
const DWARFAbbreviationDeclarationSet*
-DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const {
- DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end();
- DWARFAbbreviationDeclarationCollMapConstIter pos;
- if (PrevAbbrOffsetPos != end &&
- PrevAbbrOffsetPos->first == cu_abbr_offset) {
+DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
+ const auto End = AbbrDeclSets.end();
+ if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
return &(PrevAbbrOffsetPos->second);
- } else {
- pos = AbbrevCollMap.find(cu_abbr_offset);
- PrevAbbrOffsetPos = pos;
}
- if (pos != AbbrevCollMap.end())
- return &(pos->second);
- return NULL;
+ const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
+ if (Pos != End) {
+ PrevAbbrOffsetPos = Pos;
+ return &(Pos->second);
+ }
+
+ return nullptr;
}
diff --git a/lib/DebugInfo/DWARFDebugAbbrev.h b/lib/DebugInfo/DWARFDebugAbbrev.h
index c7c0436..3a9adba 100644
--- a/lib/DebugInfo/DWARFDebugAbbrev.h
+++ b/lib/DebugInfo/DWARFDebugAbbrev.h
@@ -17,55 +17,45 @@
namespace llvm {
-typedef std::vector<DWARFAbbreviationDeclaration>
- DWARFAbbreviationDeclarationColl;
-typedef DWARFAbbreviationDeclarationColl::iterator
- DWARFAbbreviationDeclarationCollIter;
-typedef DWARFAbbreviationDeclarationColl::const_iterator
- DWARFAbbreviationDeclarationCollConstIter;
-
class DWARFAbbreviationDeclarationSet {
uint32_t Offset;
- uint32_t IdxOffset;
+ /// Code of the first abbreviation, if all abbreviations in the set have
+ /// consecutive codes. UINT32_MAX otherwise.
+ uint32_t FirstAbbrCode;
std::vector<DWARFAbbreviationDeclaration> Decls;
- public:
- DWARFAbbreviationDeclarationSet()
- : Offset(0), IdxOffset(0) {}
- DWARFAbbreviationDeclarationSet(uint32_t offset, uint32_t idxOffset)
- : Offset(offset), IdxOffset(idxOffset) {}
+public:
+ DWARFAbbreviationDeclarationSet();
- void clear() {
- IdxOffset = 0;
- Decls.clear();
- }
uint32_t getOffset() const { return Offset; }
void dump(raw_ostream &OS) const;
- bool extract(DataExtractor data, uint32_t* offset_ptr);
+ bool extract(DataExtractor Data, uint32_t *OffsetPtr);
const DWARFAbbreviationDeclaration *
- getAbbreviationDeclaration(uint32_t abbrCode) const;
+ getAbbreviationDeclaration(uint32_t AbbrCode) const;
+
+private:
+ void clear();
};
class DWARFDebugAbbrev {
-public:
typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet>
- DWARFAbbreviationDeclarationCollMap;
- typedef DWARFAbbreviationDeclarationCollMap::iterator
- DWARFAbbreviationDeclarationCollMapIter;
- typedef DWARFAbbreviationDeclarationCollMap::const_iterator
- DWARFAbbreviationDeclarationCollMapConstIter;
+ DWARFAbbreviationDeclarationSetMap;
-private:
- DWARFAbbreviationDeclarationCollMap AbbrevCollMap;
- mutable DWARFAbbreviationDeclarationCollMapConstIter PrevAbbrOffsetPos;
+ DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
+ mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos;
public:
DWARFDebugAbbrev();
+
const DWARFAbbreviationDeclarationSet *
- getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const;
+ getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const;
+
void dump(raw_ostream &OS) const;
- void parse(DataExtractor data);
+ void extract(DataExtractor Data);
+
+private:
+ void clear();
};
}
diff --git a/lib/DebugInfo/DWARFDebugArangeSet.h b/lib/DebugInfo/DWARFDebugArangeSet.h
index c18b3c5..d6c2d8b 100644
--- a/lib/DebugInfo/DWARFDebugArangeSet.h
+++ b/lib/DebugInfo/DWARFDebugArangeSet.h
@@ -63,7 +63,6 @@ public:
return desc_iterator_range(ArangeDescriptors.begin(),
ArangeDescriptors.end());
}
- uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); }
};
}
diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp
index dfab788..2524adc 100644
--- a/lib/DebugInfo/DWARFDebugAranges.cpp
+++ b/lib/DebugInfo/DWARFDebugAranges.cpp
@@ -10,6 +10,7 @@
#include "DWARFDebugAranges.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
+#include "DWARFDebugArangeSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -20,23 +21,11 @@ void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
if (!DebugArangesData.isValidOffset(0))
return;
uint32_t Offset = 0;
- typedef std::vector<DWARFDebugArangeSet> RangeSetColl;
- RangeSetColl Sets;
DWARFDebugArangeSet Set;
- uint32_t TotalRanges = 0;
while (Set.extract(DebugArangesData, &Offset)) {
- Sets.push_back(Set);
- TotalRanges += Set.getNumDescriptors();
- }
- if (TotalRanges == 0)
- return;
-
- Aranges.reserve(TotalRanges);
- for (const auto &I : Sets) {
- uint32_t CUOffset = I.getCompileUnitDIEOffset();
-
- for (const auto &Desc : I.descriptors()) {
+ uint32_t CUOffset = Set.getCompileUnitDIEOffset();
+ for (const auto &Desc : Set.descriptors()) {
uint64_t LowPC = Desc.Address;
uint64_t HighPC = Desc.getEndAddress();
appendRange(CUOffset, LowPC, HighPC);
@@ -58,13 +47,23 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) {
// manually build aranges for the rest of them.
for (const auto &CU : CTX->compile_units()) {
uint32_t CUOffset = CU->getOffset();
- if (ParsedCUOffsets.insert(CUOffset).second)
- CU->buildAddressRangeTable(this, true, CUOffset);
+ if (ParsedCUOffsets.insert(CUOffset).second) {
+ DWARFAddressRangesVector CURanges;
+ CU->collectAddressRanges(CURanges);
+ for (const auto &R : CURanges) {
+ appendRange(CUOffset, R.first, R.second);
+ }
+ }
}
sortAndMinimize();
}
+void DWARFDebugAranges::clear() {
+ Aranges.clear();
+ ParsedCUOffsets.clear();
+}
+
void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
uint64_t HighPC) {
if (!Aranges.empty()) {
@@ -101,11 +100,6 @@ void DWARFDebugAranges::sortAndMinimize() {
++minimal_size;
}
- // If the sizes are the same, then no consecutive aranges can be
- // combined, we are done.
- if (minimal_size == orig_arange_size)
- return;
-
// Else, make a new RangeColl that _only_ contains what we need.
RangeColl minimal_aranges;
minimal_aranges.resize(minimal_size);
diff --git a/lib/DebugInfo/DWARFDebugAranges.h b/lib/DebugInfo/DWARFDebugAranges.h
index 35ad8e5..de96d7f 100644
--- a/lib/DebugInfo/DWARFDebugAranges.h
+++ b/lib/DebugInfo/DWARFDebugAranges.h
@@ -10,9 +10,9 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
-#include "DWARFDebugArangeSet.h"
#include "llvm/ADT/DenseSet.h"
-#include <list>
+#include "llvm/Support/DataExtractor.h"
+#include <vector>
namespace llvm {
@@ -20,20 +20,15 @@ class DWARFContext;
class DWARFDebugAranges {
public:
- void clear() {
- Aranges.clear();
- ParsedCUOffsets.clear();
- }
-
void generate(DWARFContext *CTX);
-
- // Use appendRange multiple times and then call sortAndMinimize.
- void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
-
uint32_t findAddress(uint64_t Address) const;
private:
+ void clear();
void extract(DataExtractor DebugArangesData);
+
+ // Use appendRange multiple times and then call sortAndMinimize.
+ void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
void sortAndMinimize();
struct Range {
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp
index 5bf7b07..a33548e 100644
--- a/lib/DebugInfo/DWARFDebugFrame.cpp
+++ b/lib/DebugInfo/DWARFDebugFrame.cpp
@@ -26,8 +26,8 @@ using namespace dwarf;
class llvm::FrameEntry {
public:
enum FrameKind {FK_CIE, FK_FDE};
- FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
- : Kind(K), Data(D), Offset(Offset), Length(Length) {}
+ FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
+ : Kind(K), Offset(Offset), Length(Length) {}
virtual ~FrameEntry() {
}
@@ -35,11 +35,12 @@ public:
FrameKind getKind() const { return Kind; }
virtual uint64_t getOffset() const { return Offset; }
- /// \brief Parse and store a sequence of CFI instructions from our data
- /// stream, starting at *Offset and ending at EndOffset. If everything
+ /// \brief Parse and store a sequence of CFI instructions from Data,
+ /// starting at *Offset and ending at EndOffset. If everything
/// goes well, *Offset should be equal to EndOffset when this method
/// returns. Otherwise, an error occurred.
- virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset);
+ virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
+ uint32_t EndOffset);
/// \brief Dump the entry header to the given output stream.
virtual void dumpHeader(raw_ostream &OS) const = 0;
@@ -50,10 +51,6 @@ public:
protected:
const FrameKind Kind;
- /// \brief The data stream holding the section from which the entry was
- /// parsed.
- DataExtractor Data;
-
/// \brief Offset of this entry in the section.
uint64_t Offset;
@@ -97,8 +94,8 @@ protected:
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
-
-void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) {
+void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
+ uint32_t EndOffset) {
while (*Offset < EndOffset) {
uint8_t Opcode = Data.getU8(Offset);
// Some instructions have a primary opcode encoded in the top bits.
@@ -201,13 +198,13 @@ class CIE : public FrameEntry {
public:
// CIEs (and FDEs) are simply container classes, so the only sensible way to
// create them is by providing the full parsed contents in the constructor.
- CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
+ CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
- : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
- Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
- DataAlignmentFactor(DataAlignmentFactor),
- ReturnAddressRegister(ReturnAddressRegister) {}
+ : FrameEntry(FK_CIE, Offset, Length), Version(Version),
+ Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister) {}
~CIE() {
}
@@ -229,7 +226,7 @@ public:
static bool classof(const FrameEntry *FE) {
return FE->getKind() == FK_CIE;
- }
+ }
private:
/// The following fields are defined in section 6.4.1 of the DWARF standard v3
@@ -247,11 +244,11 @@ public:
// Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
// an offset to the CIE (provided by parsing the FDE header). The CIE itself
// is obtained lazily once it's actually required.
- FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
- int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
- : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
- InitialLocation(InitialLocation), AddressRange(AddressRange),
- LinkedCIE(NULL) {}
+ FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ uint64_t InitialLocation, uint64_t AddressRange)
+ : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
+ InitialLocation(InitialLocation), AddressRange(AddressRange),
+ LinkedCIE(nullptr) {}
~FDE() {
}
@@ -270,9 +267,9 @@ public:
static bool classof(const FrameEntry *FE) {
return FE->getKind() == FK_FDE;
- }
-private:
+ }
+private:
/// The following fields are defined in section 6.4.1 of the DWARF standard v3
uint64_t LinkedCIEOffset;
uint64_t InitialLocation;
@@ -285,14 +282,9 @@ private:
DWARFDebugFrame::DWARFDebugFrame() {
}
-
DWARFDebugFrame::~DWARFDebugFrame() {
- for (const auto &Entry : Entries) {
- delete Entry;
- }
}
-
static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
uint32_t Offset, int Length) {
errs() << "DUMP: ";
@@ -334,7 +326,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
- FrameEntry *Entry = 0;
if (IsCIE) {
// Note: this is specifically DWARFv3 CIE header structure. It was
// changed in DWARFv4. We currently don't support reading DWARFv4
@@ -346,30 +337,25 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
- Entry = new CIE(Data, StartOffset, Length, Version,
- StringRef(Augmentation), CodeAlignmentFactor,
- DataAlignmentFactor, ReturnAddressRegister);
+ Entries.emplace_back(new CIE(StartOffset, Length, Version,
+ StringRef(Augmentation), CodeAlignmentFactor,
+ DataAlignmentFactor, ReturnAddressRegister));
} else {
// FDE
uint64_t CIEPointer = Id;
uint64_t InitialLocation = Data.getAddress(&Offset);
uint64_t AddressRange = Data.getAddress(&Offset);
- Entry = new FDE(Data, StartOffset, Length, CIEPointer,
- InitialLocation, AddressRange);
+ Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
+ InitialLocation, AddressRange));
}
- assert(Entry && "Expected Entry to be populated with CIE or FDE");
- Entry->parseInstructions(&Offset, EndStructureOffset);
+ Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
- if (Offset == EndStructureOffset) {
- // Entry instrucitons parsed successfully.
- Entries.push_back(Entry);
- } else {
+ if (Offset != EndStructureOffset) {
std::string Str;
raw_string_ostream OS(Str);
- OS << format("Parsing entry instructions at %lx failed",
- Entry->getOffset());
+ OS << format("Parsing entry instructions at %lx failed", StartOffset);
report_fatal_error(Str);
}
}
diff --git a/lib/DebugInfo/DWARFDebugFrame.h b/lib/DebugInfo/DWARFDebugFrame.h
index 7683849..bd4ef45 100644
--- a/lib/DebugInfo/DWARFDebugFrame.h
+++ b/lib/DebugInfo/DWARFDebugFrame.h
@@ -12,14 +12,13 @@
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/raw_ostream.h"
+#include <memory>
#include <vector>
-
namespace llvm {
class FrameEntry;
-
/// \brief A parsed .debug_frame section
///
class DWARFDebugFrame {
@@ -35,8 +34,7 @@ public:
void parse(DataExtractor Data);
private:
- typedef std::vector<FrameEntry *> EntryVector;
- EntryVector Entries;
+ std::vector<std::unique_ptr<FrameEntry>> Entries;
};
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index bde25ec..b811ed7 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace dwarf;
+typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u,
unsigned recurseDepth,
@@ -99,11 +100,11 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
if (0 == AbbrCode) {
// NULL debug tag entry.
- AbbrevDecl = NULL;
+ AbbrevDecl = nullptr;
return true;
}
AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
- if (0 == AbbrevDecl) {
+ if (nullptr == AbbrevDecl) {
// Restore the original offset.
*OffsetPtr = Offset;
return false;
@@ -226,54 +227,66 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
return (HighPC != -1ULL);
}
-void DWARFDebugInfoEntryMinimal::buildAddressRangeTable(
- const DWARFUnit *U, DWARFDebugAranges *DebugAranges,
- uint32_t UOffsetInAranges) const {
- if (AbbrevDecl) {
- if (isSubprogramDIE()) {
- uint64_t LowPC, HighPC;
- if (getLowAndHighPC(U, LowPC, HighPC))
- DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC);
- // FIXME: try to append ranges from .debug_ranges section.
- }
-
- const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
- while (Child) {
- Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges);
- Child = Child->getSibling();
- }
- }
-}
-
-bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
- const DWARFUnit *U, const uint64_t Address) const {
+DWARFAddressRangesVector
+DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
if (isNULL())
- return false;
+ return DWARFAddressRangesVector();
+ // Single range specified by low/high PC.
uint64_t LowPC, HighPC;
- if (getLowAndHighPC(U, LowPC, HighPC))
- return (LowPC <= Address && Address <= HighPC);
- // Try to get address ranges from .debug_ranges section.
+ if (getLowAndHighPC(U, LowPC, HighPC)) {
+ return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
+ }
+ // Multiple ranges from .debug_ranges section.
uint32_t RangesOffset =
getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
if (RangesOffset != -1U) {
DWARFDebugRangeList RangeList;
if (U->extractRangeList(RangesOffset, RangeList))
- return RangeList.containsAddress(U->getBaseAddress(), Address);
+ return RangeList.getAbsoluteRanges(U->getBaseAddress());
+ }
+ return DWARFAddressRangesVector();
+}
+
+void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges(
+ const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const {
+ if (isNULL())
+ return;
+ if (isSubprogramDIE()) {
+ const auto &DIERanges = getAddressRanges(U);
+ Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
+ }
+
+ const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
+ while (Child) {
+ Child->collectChildrenAddressRanges(U, Ranges);
+ Child = Child->getSibling();
+ }
+}
+
+bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
+ const DWARFUnit *U, const uint64_t Address) const {
+ for (const auto& R : getAddressRanges(U)) {
+ if (R.first <= Address && Address < R.second)
+ return true;
}
return false;
}
const char *
-DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
- if (!isSubroutineDIE())
- return 0;
- // Try to get mangled name if possible.
- if (const char *name =
- getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, 0))
- return name;
- if (const char *name = getAttributeValueAsString(U, DW_AT_linkage_name, 0))
- return name;
- if (const char *name = getAttributeValueAsString(U, DW_AT_name, 0))
+DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U,
+ FunctionNameKind Kind) const {
+ if (!isSubroutineDIE() || Kind == FunctionNameKind::None)
+ return nullptr;
+ // Try to get mangled name only if it was asked for.
+ if (Kind == FunctionNameKind::LinkageName) {
+ if (const char *name =
+ getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr))
+ return name;
+ if (const char *name =
+ getAttributeValueAsString(U, DW_AT_linkage_name, nullptr))
+ return name;
+ }
+ if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr))
return name;
// Try to get name from specification DIE.
uint32_t spec_ref =
@@ -281,7 +294,7 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
if (spec_ref != -1U) {
DWARFDebugInfoEntryMinimal spec_die;
if (spec_die.extractFast(U, &spec_ref)) {
- if (const char *name = spec_die.getSubroutineName(U))
+ if (const char *name = spec_die.getSubroutineName(U, Kind))
return name;
}
}
@@ -291,11 +304,11 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
if (abs_origin_ref != -1U) {
DWARFDebugInfoEntryMinimal abs_origin_die;
if (abs_origin_die.extractFast(U, &abs_origin_ref)) {
- if (const char *name = abs_origin_die.getSubroutineName(U))
+ if (const char *name = abs_origin_die.getSubroutineName(U, Kind))
return name;
}
}
- return 0;
+ return nullptr;
}
void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h
index f30e531..916e1ed 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.h
@@ -11,7 +11,9 @@
#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
#include "DWARFAbbreviationDeclaration.h"
+#include "DWARFDebugRangeList.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -28,17 +30,13 @@ class DWARFDebugInfoEntryMinimal {
/// Offset within the .debug_info of the start of this entry.
uint32_t Offset;
- /// How many to subtract from "this" to get the parent.
- /// If zero this die has no parent.
- uint32_t ParentIdx;
-
/// How many to add to "this" to get the sibling.
uint32_t SiblingIdx;
const DWARFAbbreviationDeclaration *AbbrevDecl;
public:
DWARFDebugInfoEntryMinimal()
- : Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(0) {}
+ : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {}
void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth,
unsigned indent = 0) const;
@@ -51,7 +49,7 @@ public:
bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr);
uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
- bool isNULL() const { return AbbrevDecl == 0; }
+ bool isNULL() const { return AbbrevDecl == nullptr; }
/// Returns true if DIE represents a subprogram (not inlined).
bool isSubprogramDIE() const;
@@ -63,45 +61,23 @@ public:
bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); }
// We know we are kept in a vector of contiguous entries, so we know
- // our parent will be some index behind "this".
- DWARFDebugInfoEntryMinimal *getParent() {
- return ParentIdx > 0 ? this - ParentIdx : 0;
- }
- const DWARFDebugInfoEntryMinimal *getParent() const {
- return ParentIdx > 0 ? this - ParentIdx : 0;
- }
- // We know we are kept in a vector of contiguous entries, so we know
// our sibling will be some index after "this".
- DWARFDebugInfoEntryMinimal *getSibling() {
- return SiblingIdx > 0 ? this + SiblingIdx : 0;
- }
const DWARFDebugInfoEntryMinimal *getSibling() const {
- return SiblingIdx > 0 ? this + SiblingIdx : 0;
+ return SiblingIdx > 0 ? this + SiblingIdx : nullptr;
}
+
// We know we are kept in a vector of contiguous entries, so we know
// we don't need to store our child pointer, if we have a child it will
// be the next entry in the list...
- DWARFDebugInfoEntryMinimal *getFirstChild() {
- return hasChildren() ? this + 1 : 0;
- }
const DWARFDebugInfoEntryMinimal *getFirstChild() const {
- return hasChildren() ? this + 1 : 0;
+ return hasChildren() ? this + 1 : nullptr;
}
- void setParent(DWARFDebugInfoEntryMinimal *parent) {
- if (parent) {
- // We know we are kept in a vector of contiguous entries, so we know
- // our parent will be some index behind "this".
- ParentIdx = this - parent;
- } else
- ParentIdx = 0;
- }
- void setSibling(DWARFDebugInfoEntryMinimal *sibling) {
- if (sibling) {
+ void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) {
+ if (Sibling) {
// We know we are kept in a vector of contiguous entries, so we know
// our sibling will be some index after "this".
- SiblingIdx = sibling - this;
- sibling->setParent(getParent());
+ SiblingIdx = Sibling - this;
} else
SiblingIdx = 0;
}
@@ -135,9 +111,10 @@ public:
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
uint64_t &HighPC) const;
- void buildAddressRangeTable(const DWARFUnit *U,
- DWARFDebugAranges *DebugAranges,
- uint32_t CUOffsetInAranges) const;
+ DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const;
+
+ void collectChildrenAddressRanges(const DWARFUnit *U,
+ DWARFAddressRangesVector &Ranges) const;
bool addressRangeContainsAddress(const DWARFUnit *U,
const uint64_t Address) const;
@@ -146,7 +123,9 @@ public:
/// returns its mangled name (or short name, if mangled is missing).
/// This name may be fetched from specification or abstract origin
/// for this subprogram. Returns null if no name is found.
- const char *getSubroutineName(const DWARFUnit *U) const;
+ const char *
+ getSubroutineName(const DWARFUnit *U,
+ DILineInfoSpecifier::FunctionNameKind Kind) const;
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and
/// DW_AT_call_column from DIE (or zeroes if they are missing).
@@ -166,7 +145,7 @@ public:
/// (except the last DIE) in this chain is contained in address
/// range for next DIE in the chain.
struct DWARFDebugInfoEntryInlinedChain {
- DWARFDebugInfoEntryInlinedChain() : U(0) {}
+ DWARFDebugInfoEntryInlinedChain() : U(nullptr) {}
SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs;
const DWARFUnit *U;
};
diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index 43d9764..ce87635 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/lib/DebugInfo/DWARFDebugLine.cpp
@@ -15,6 +15,20 @@
#include <algorithm>
using namespace llvm;
using namespace dwarf;
+typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
+
+DWARFDebugLine::Prologue::Prologue() {
+ clear();
+}
+
+void DWARFDebugLine::Prologue::clear() {
+ TotalLength = Version = PrologueLength = 0;
+ MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
+ OpcodeBase = 0;
+ StandardOpcodeLengths.clear();
+ IncludeDirectories.clear();
+ FileNames.clear();
+}
void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
OS << "Line table prologue:\n"
@@ -51,6 +65,67 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
}
}
+bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
+ uint32_t *offset_ptr) {
+ const uint32_t prologue_offset = *offset_ptr;
+
+ clear();
+ TotalLength = debug_line_data.getU32(offset_ptr);
+ Version = debug_line_data.getU16(offset_ptr);
+ if (Version < 2)
+ return false;
+
+ PrologueLength = debug_line_data.getU32(offset_ptr);
+ const uint32_t end_prologue_offset = PrologueLength + *offset_ptr;
+ MinInstLength = debug_line_data.getU8(offset_ptr);
+ if (Version >= 4)
+ MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
+ DefaultIsStmt = debug_line_data.getU8(offset_ptr);
+ LineBase = debug_line_data.getU8(offset_ptr);
+ LineRange = debug_line_data.getU8(offset_ptr);
+ OpcodeBase = debug_line_data.getU8(offset_ptr);
+
+ StandardOpcodeLengths.reserve(OpcodeBase - 1);
+ for (uint32_t i = 1; i < OpcodeBase; ++i) {
+ uint8_t op_len = debug_line_data.getU8(offset_ptr);
+ StandardOpcodeLengths.push_back(op_len);
+ }
+
+ while (*offset_ptr < end_prologue_offset) {
+ const char *s = debug_line_data.getCStr(offset_ptr);
+ if (s && s[0])
+ IncludeDirectories.push_back(s);
+ else
+ break;
+ }
+
+ while (*offset_ptr < end_prologue_offset) {
+ const char *name = debug_line_data.getCStr(offset_ptr);
+ if (name && name[0]) {
+ FileNameEntry fileEntry;
+ fileEntry.Name = name;
+ fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
+ FileNames.push_back(fileEntry);
+ } else {
+ break;
+ }
+ }
+
+ if (*offset_ptr != end_prologue_offset) {
+ fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
+ " have ended at 0x%8.8x but it ended at 0x%8.8x\n",
+ prologue_offset, end_prologue_offset, *offset_ptr);
+ return false;
+ }
+ return true;
+}
+
+DWARFDebugLine::Row::Row(bool default_is_stmt) {
+ reset(default_is_stmt);
+}
+
void DWARFDebugLine::Row::postAppend() {
BasicBlock = false;
PrologueEnd = false;
@@ -82,6 +157,22 @@ void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
<< '\n';
}
+DWARFDebugLine::Sequence::Sequence() {
+ reset();
+}
+
+void DWARFDebugLine::Sequence::reset() {
+ LowPC = 0;
+ HighPC = 0;
+ FirstRowIndex = 0;
+ LastRowIndex = 0;
+ Empty = true;
+}
+
+DWARFDebugLine::LineTable::LineTable() {
+ clear();
+}
+
void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
Prologue.dump(OS);
OS << '\n';
@@ -96,50 +187,40 @@ void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
}
}
-DWARFDebugLine::State::~State() {}
-
-void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) {
- if (Sequence::Empty) {
- // Record the beginning of instruction sequence.
- Sequence::Empty = false;
- Sequence::LowPC = Address;
- Sequence::FirstRowIndex = row;
- }
- ++row; // Increase the row number.
- LineTable::appendRow(*this);
- if (EndSequence) {
- // Record the end of instruction sequence.
- Sequence::HighPC = Address;
- Sequence::LastRowIndex = row;
- if (Sequence::isValid())
- LineTable::appendSequence(*this);
- Sequence::reset();
- }
- Row::postAppend();
+void DWARFDebugLine::LineTable::clear() {
+ Prologue.clear();
+ Rows.clear();
+ Sequences.clear();
}
-void DWARFDebugLine::State::finalize() {
- row = DoneParsingLineTable;
- if (!Sequence::Empty) {
- fprintf(stderr, "warning: last sequence in debug line table is not"
- "terminated!\n");
- }
- // Sort all sequences so that address lookup will work faster.
- if (!Sequences.empty()) {
- std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
- // Note: actually, instruction address ranges of sequences should not
- // overlap (in shared objects and executables). If they do, the address
- // lookup would still work, though, but result would be ambiguous.
- // We don't report warning in this case. For example,
- // sometimes .so compiled from multiple object files contains a few
- // rudimentary sequences for address ranges [0x0, 0xsomething).
- }
+DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
+ : LineTable(LT), RowNumber(0) {
+ resetRowAndSequence();
}
-DWARFDebugLine::DumpingState::~DumpingState() {}
+void DWARFDebugLine::ParsingState::resetRowAndSequence() {
+ Row.reset(LineTable->Prologue.DefaultIsStmt);
+ Sequence.reset();
+}
-void DWARFDebugLine::DumpingState::finalize() {
- LineTable::dump(OS);
+void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) {
+ if (Sequence.Empty) {
+ // Record the beginning of instruction sequence.
+ Sequence.Empty = false;
+ Sequence.LowPC = Row.Address;
+ Sequence.FirstRowIndex = RowNumber;
+ }
+ ++RowNumber;
+ LineTable->appendRow(Row);
+ if (Row.EndSequence) {
+ // Record the end of instruction sequence.
+ Sequence.HighPC = Row.Address;
+ Sequence.LastRowIndex = RowNumber;
+ if (Sequence.isValid())
+ LineTable->appendSequence(Sequence);
+ Sequence.reset();
+ }
+ Row.postAppend();
}
const DWARFDebugLine::LineTable *
@@ -147,7 +228,7 @@ DWARFDebugLine::getLineTable(uint32_t offset) const {
LineTableConstIter pos = LineTableMap.find(offset);
if (pos != LineTableMap.end())
return &pos->second;
- return 0;
+ return nullptr;
}
const DWARFDebugLine::LineTable *
@@ -155,91 +236,31 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
uint32_t offset) {
std::pair<LineTableIter, bool> pos =
LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable()));
+ LineTable *LT = &pos.first->second;
if (pos.second) {
- // Parse and cache the line table for at this offset.
- State state;
- if (!parseStatementTable(debug_line_data, RelocMap, &offset, state))
- return 0;
- pos.first->second = state;
+ if (!LT->parse(debug_line_data, RelocMap, &offset))
+ return nullptr;
}
- return &pos.first->second;
+ return LT;
}
-bool
-DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
- uint32_t *offset_ptr, Prologue *prologue) {
- const uint32_t prologue_offset = *offset_ptr;
-
- prologue->clear();
- prologue->TotalLength = debug_line_data.getU32(offset_ptr);
- prologue->Version = debug_line_data.getU16(offset_ptr);
- if (prologue->Version < 2)
- return false;
-
- prologue->PrologueLength = debug_line_data.getU32(offset_ptr);
- const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr;
- prologue->MinInstLength = debug_line_data.getU8(offset_ptr);
- if (prologue->Version >= 4)
- prologue->MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
- prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr);
- prologue->LineBase = debug_line_data.getU8(offset_ptr);
- prologue->LineRange = debug_line_data.getU8(offset_ptr);
- prologue->OpcodeBase = debug_line_data.getU8(offset_ptr);
-
- prologue->StandardOpcodeLengths.reserve(prologue->OpcodeBase-1);
- for (uint32_t i = 1; i < prologue->OpcodeBase; ++i) {
- uint8_t op_len = debug_line_data.getU8(offset_ptr);
- prologue->StandardOpcodeLengths.push_back(op_len);
- }
-
- while (*offset_ptr < end_prologue_offset) {
- const char *s = debug_line_data.getCStr(offset_ptr);
- if (s && s[0])
- prologue->IncludeDirectories.push_back(s);
- else
- break;
- }
-
- while (*offset_ptr < end_prologue_offset) {
- const char *name = debug_line_data.getCStr(offset_ptr);
- if (name && name[0]) {
- FileNameEntry fileEntry;
- fileEntry.Name = name;
- fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
- fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
- fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
- prologue->FileNames.push_back(fileEntry);
- } else {
- break;
- }
- }
-
- if (*offset_ptr != end_prologue_offset) {
- fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
- " have ended at 0x%8.8x but it ended at 0x%8.8x\n",
- prologue_offset, end_prologue_offset, *offset_ptr);
- return false;
- }
- return true;
-}
-
-bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
- const RelocAddrMap *RMap,
- uint32_t *offset_ptr, State &state) {
+bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
+ uint32_t *offset_ptr) {
const uint32_t debug_line_offset = *offset_ptr;
- Prologue *prologue = &state.Prologue;
+ clear();
- if (!parsePrologue(debug_line_data, offset_ptr, prologue)) {
+ if (!Prologue.parse(debug_line_data, offset_ptr)) {
// Restore our offset and return false to indicate failure!
*offset_ptr = debug_line_offset;
return false;
}
- const uint32_t end_offset = debug_line_offset + prologue->TotalLength +
- sizeof(prologue->TotalLength);
+ const uint32_t end_offset = debug_line_offset + Prologue.TotalLength +
+ sizeof(Prologue.TotalLength);
- state.reset();
+ ParsingState State(this);
while (*offset_ptr < end_offset) {
uint8_t opcode = debug_line_data.getU8(offset_ptr);
@@ -261,9 +282,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// with a DW_LNE_end_sequence instruction which creates a row whose
// address is that of the byte after the last target machine instruction
// of the sequence.
- state.EndSequence = true;
- state.appendRowToMatrix(*offset_ptr);
- state.reset();
+ State.Row.EndSequence = true;
+ State.appendRowToMatrix(*offset_ptr);
+ State.resetRowAndSequence();
break;
case DW_LNE_set_address:
@@ -278,9 +299,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr);
if (AI != RMap->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
- state.Address = debug_line_data.getAddress(offset_ptr) + R.second;
+ State.Row.Address =
+ debug_line_data.getAddress(offset_ptr) + R.second;
} else
- state.Address = debug_line_data.getAddress(offset_ptr);
+ State.Row.Address = debug_line_data.getAddress(offset_ptr);
}
break;
@@ -311,12 +333,12 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
- prologue->FileNames.push_back(fileEntry);
+ Prologue.FileNames.push_back(fileEntry);
}
break;
case DW_LNE_set_discriminator:
- state.Discriminator = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr);
break;
default:
@@ -325,52 +347,52 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
(*offset_ptr) += arg_size;
break;
}
- } else if (opcode < prologue->OpcodeBase) {
+ } else if (opcode < Prologue.OpcodeBase) {
switch (opcode) {
// Standard Opcodes
case DW_LNS_copy:
// Takes no arguments. Append a row to the matrix using the
// current values of the state-machine registers. Then set
// the basic_block register to false.
- state.appendRowToMatrix(*offset_ptr);
+ State.appendRowToMatrix(*offset_ptr);
break;
case DW_LNS_advance_pc:
// Takes a single unsigned LEB128 operand, multiplies it by the
// min_inst_length field of the prologue, and adds the
// result to the address register of the state machine.
- state.Address += debug_line_data.getULEB128(offset_ptr) *
- prologue->MinInstLength;
+ State.Row.Address +=
+ debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength;
break;
case DW_LNS_advance_line:
// Takes a single signed LEB128 operand and adds that value to
// the line register of the state machine.
- state.Line += debug_line_data.getSLEB128(offset_ptr);
+ State.Row.Line += debug_line_data.getSLEB128(offset_ptr);
break;
case DW_LNS_set_file:
// Takes a single unsigned LEB128 operand and stores it in the file
// register of the state machine.
- state.File = debug_line_data.getULEB128(offset_ptr);
+ State.Row.File = debug_line_data.getULEB128(offset_ptr);
break;
case DW_LNS_set_column:
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
- state.Column = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Column = debug_line_data.getULEB128(offset_ptr);
break;
case DW_LNS_negate_stmt:
// Takes no arguments. Set the is_stmt register of the state
// machine to the logical negation of its current value.
- state.IsStmt = !state.IsStmt;
+ State.Row.IsStmt = !State.Row.IsStmt;
break;
case DW_LNS_set_basic_block:
// Takes no arguments. Set the basic_block register of the
// state machine to true
- state.BasicBlock = true;
+ State.Row.BasicBlock = true;
break;
case DW_LNS_const_add_pc:
@@ -386,10 +408,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// than twice that range will it need to use both DW_LNS_advance_pc
// and a special opcode, requiring three or more bytes.
{
- uint8_t adjust_opcode = 255 - prologue->OpcodeBase;
- uint64_t addr_offset = (adjust_opcode / prologue->LineRange) *
- prologue->MinInstLength;
- state.Address += addr_offset;
+ uint8_t adjust_opcode = 255 - Prologue.OpcodeBase;
+ uint64_t addr_offset =
+ (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
+ State.Row.Address += addr_offset;
}
break;
@@ -403,25 +425,25 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// judge when the computation of a special opcode overflows and
// requires the use of DW_LNS_advance_pc. Such assemblers, however,
// can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
- state.Address += debug_line_data.getU16(offset_ptr);
+ State.Row.Address += debug_line_data.getU16(offset_ptr);
break;
case DW_LNS_set_prologue_end:
// Takes no arguments. Set the prologue_end register of the
// state machine to true
- state.PrologueEnd = true;
+ State.Row.PrologueEnd = true;
break;
case DW_LNS_set_epilogue_begin:
// Takes no arguments. Set the basic_block register of the
// state machine to true
- state.EpilogueBegin = true;
+ State.Row.EpilogueBegin = true;
break;
case DW_LNS_set_isa:
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
- state.Isa = debug_line_data.getULEB128(offset_ptr);
+ State.Row.Isa = debug_line_data.getULEB128(offset_ptr);
break;
default:
@@ -429,9 +451,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// of such opcodes because they are specified in the prologue
// as a multiple of LEB128 operands for each opcode.
{
- assert(opcode - 1U < prologue->StandardOpcodeLengths.size());
- uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1];
- for (uint8_t i=0; i<opcode_length; ++i)
+ assert(opcode - 1U < Prologue.StandardOpcodeLengths.size());
+ uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1];
+ for (uint8_t i = 0; i < opcode_length; ++i)
debug_line_data.getULEB128(offset_ptr);
}
break;
@@ -470,24 +492,37 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
//
// line increment = line_base + (adjusted opcode % line_range)
- uint8_t adjust_opcode = opcode - prologue->OpcodeBase;
- uint64_t addr_offset = (adjust_opcode / prologue->LineRange) *
- prologue->MinInstLength;
- int32_t line_offset = prologue->LineBase +
- (adjust_opcode % prologue->LineRange);
- state.Line += line_offset;
- state.Address += addr_offset;
- state.appendRowToMatrix(*offset_ptr);
+ uint8_t adjust_opcode = opcode - Prologue.OpcodeBase;
+ uint64_t addr_offset =
+ (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
+ int32_t line_offset =
+ Prologue.LineBase + (adjust_opcode % Prologue.LineRange);
+ State.Row.Line += line_offset;
+ State.Row.Address += addr_offset;
+ State.appendRowToMatrix(*offset_ptr);
}
}
- state.finalize();
+ if (!State.Sequence.Empty) {
+ fprintf(stderr, "warning: last sequence in debug line table is not"
+ "terminated!\n");
+ }
+
+ // Sort all sequences so that address lookup will work faster.
+ if (!Sequences.empty()) {
+ std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
+ // Note: actually, instruction address ranges of sequences should not
+ // overlap (in shared objects and executables). If they do, the address
+ // lookup would still work, though, but result would be ambiguous.
+ // We don't report warning in this case. For example,
+ // sometimes .so compiled from multiple object files contains a few
+ // rudimentary sequences for address ranges [0x0, 0xsomething).
+ }
return end_offset;
}
-uint32_t
-DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
+uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
uint32_t unknown_index = UINT32_MAX;
if (Sequences.empty())
return unknown_index;
@@ -532,10 +567,8 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
return index;
}
-bool
-DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
- uint64_t size,
- std::vector<uint32_t>& result) const {
+bool DWARFDebugLine::LineTable::lookupAddressRange(
+ uint64_t address, uint64_t size, std::vector<uint32_t> &result) const {
if (Sequences.empty())
return false;
uint64_t end_addr = address + size;
@@ -611,13 +644,14 @@ DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
bool
DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
- bool NeedsAbsoluteFilePath,
+ FileLineInfoKind Kind,
std::string &Result) const {
- if (FileIndex == 0 || FileIndex > Prologue.FileNames.size())
+ if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() ||
+ Kind == FileLineInfoKind::None)
return false;
const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
const char *FileName = Entry.Name;
- if (!NeedsAbsoluteFilePath ||
+ if (Kind != FileLineInfoKind::AbsoluteFilePath ||
sys::path::is_absolute(FileName)) {
Result = FileName;
return true;
diff --git a/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
index a336f49..c7b7ec2 100644
--- a/lib/DebugInfo/DWARFDebugLine.h
+++ b/lib/DebugInfo/DWARFDebugLine.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#include "DWARFRelocMap.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/DataExtractor.h"
#include <map>
#include <string>
@@ -24,7 +25,7 @@ class DWARFDebugLine {
public:
DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
struct FileNameEntry {
- FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {}
+ FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {}
const char *Name;
uint64_t DirIdx;
@@ -33,10 +34,7 @@ public:
};
struct Prologue {
- Prologue()
- : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0),
- MaxOpsPerInst(0), DefaultIsStmt(0), LineBase(0), LineRange(0),
- OpcodeBase(0) {}
+ Prologue();
// The size in bytes of the statement information for this compilation unit
// (not including the total_length field itself).
@@ -77,19 +75,16 @@ public:
int32_t getMaxLineIncrementForSpecialOpcode() const {
return LineBase + (int8_t)LineRange - 1;
}
+
+ void clear();
void dump(raw_ostream &OS) const;
- void clear() {
- TotalLength = Version = PrologueLength = 0;
- MinInstLength = LineBase = LineRange = OpcodeBase = 0;
- StandardOpcodeLengths.clear();
- IncludeDirectories.clear();
- FileNames.clear();
- }
+ bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr);
};
// Standard .debug_line state machine structure.
struct Row {
- Row(bool default_is_stmt = false) { reset(default_is_stmt); }
+ explicit Row(bool default_is_stmt = false);
+
/// Called after a row is appended to the matrix.
void postAppend();
void reset(bool default_is_stmt);
@@ -151,14 +146,9 @@ public:
unsigned LastRowIndex;
bool Empty;
- Sequence() { reset(); }
- void reset() {
- LowPC = 0;
- HighPC = 0;
- FirstRowIndex = 0;
- LastRowIndex = 0;
- Empty = true;
- }
+ Sequence();
+ void reset();
+
static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) {
return LHS.LowPC < RHS.LowPC;
}
@@ -171,31 +161,34 @@ public:
};
struct LineTable {
- void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); }
- void appendSequence(const DWARFDebugLine::Sequence &sequence) {
- Sequences.push_back(sequence);
+ LineTable();
+
+ void appendRow(const DWARFDebugLine::Row &R) {
+ Rows.push_back(R);
}
- void clear() {
- Prologue.clear();
- Rows.clear();
- Sequences.clear();
+ void appendSequence(const DWARFDebugLine::Sequence &S) {
+ Sequences.push_back(S);
}
// Returns the index of the row with file/line info for a given address,
// or -1 if there is no such row.
uint32_t lookupAddress(uint64_t address) const;
- bool lookupAddressRange(uint64_t address,
- uint64_t size,
- std::vector<uint32_t>& result) const;
+ bool lookupAddressRange(uint64_t address, uint64_t size,
+ std::vector<uint32_t> &result) const;
// Extracts filename by its index in filename table in prologue.
// Returns true on success.
bool getFileNameByIndex(uint64_t FileIndex,
- bool NeedsAbsoluteFilePath,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
std::string &Result) const;
void dump(raw_ostream &OS) const;
+ void clear();
+
+ /// Parse prologue and all rows.
+ bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap,
+ uint32_t *offset_ptr);
struct Prologue Prologue;
typedef std::vector<Row> RowVector;
@@ -206,48 +199,26 @@ public:
SequenceVector Sequences;
};
- struct State : public Row, public Sequence, public LineTable {
- // Special row codes.
- enum {
- StartParsingLineTable = 0,
- DoneParsingLineTable = -1
- };
-
- State() : row(StartParsingLineTable) {}
- virtual ~State();
-
- virtual void appendRowToMatrix(uint32_t offset);
- virtual void finalize();
- virtual void reset() {
- Row::reset(Prologue.DefaultIsStmt);
- Sequence::reset();
- }
-
- // The row number that starts at zero for the prologue, and increases for
- // each row added to the matrix.
- unsigned row;
- };
-
- struct DumpingState : public State {
- DumpingState(raw_ostream &OS) : OS(OS) {}
- virtual ~DumpingState();
- void finalize() override;
- private:
- raw_ostream &OS;
- };
-
- static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr,
- Prologue *prologue);
- /// Parse a single line table (prologue and all rows).
- static bool parseStatementTable(DataExtractor debug_line_data,
- const RelocAddrMap *RMap,
- uint32_t *offset_ptr, State &state);
-
const LineTable *getLineTable(uint32_t offset) const;
const LineTable *getOrParseLineTable(DataExtractor debug_line_data,
uint32_t offset);
private:
+ struct ParsingState {
+ ParsingState(struct LineTable *LT);
+
+ void resetRowAndSequence();
+ void appendRowToMatrix(uint32_t offset);
+
+ // Line table we're currently parsing.
+ struct LineTable *LineTable;
+ // The row number that starts at zero for the prologue, and increases for
+ // each row added to the matrix.
+ unsigned RowNumber;
+ struct Row Row;
+ struct Sequence Sequence;
+ };
+
typedef std::map<uint32_t, LineTable> LineTableMapTy;
typedef LineTableMapTy::iterator LineTableIter;
typedef LineTableMapTy::const_iterator LineTableConstIter;
diff --git a/lib/DebugInfo/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARFDebugRangeList.cpp
index aa2a2be..07b23b3 100644
--- a/lib/DebugInfo/DWARFDebugRangeList.cpp
+++ b/lib/DebugInfo/DWARFDebugRangeList.cpp
@@ -54,13 +54,16 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
OS << format("%08x <End of list>\n", Offset);
}
-bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress,
- uint64_t Address) const {
+DWARFAddressRangesVector
+DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
+ DWARFAddressRangesVector Res;
for (const RangeListEntry &RLE : Entries) {
- if (RLE.isBaseAddressSelectionEntry(AddressSize))
+ if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
BaseAddress = RLE.EndAddress;
- else if (RLE.containsAddress(BaseAddress, Address))
- return true;
+ } else {
+ Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress,
+ BaseAddress + RLE.EndAddress));
+ }
}
- return false;
+ return Res;
}
diff --git a/lib/DebugInfo/DWARFDebugRangeList.h b/lib/DebugInfo/DWARFDebugRangeList.h
index 4e34a91..587b550 100644
--- a/lib/DebugInfo/DWARFDebugRangeList.h
+++ b/lib/DebugInfo/DWARFDebugRangeList.h
@@ -17,6 +17,9 @@ namespace llvm {
class raw_ostream;
+/// DWARFAddressRangesVector - represents a set of absolute address ranges.
+typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector;
+
class DWARFDebugRangeList {
public:
struct RangeListEntry {
@@ -50,10 +53,6 @@ public:
else
return StartAddress == -1ULL;
}
- bool containsAddress(uint64_t BaseAddress, uint64_t Address) const {
- return (BaseAddress + StartAddress <= Address) &&
- (Address < BaseAddress + EndAddress);
- }
};
private:
@@ -67,10 +66,10 @@ public:
void clear();
void dump(raw_ostream &OS) const;
bool extract(DataExtractor data, uint32_t *offset_ptr);
- /// containsAddress - Returns true if range list contains the given
- /// address. Has to be passed base address of the compile unit that
- /// references this range list.
- bool containsAddress(uint64_t BaseAddress, uint64_t Address) const;
+ /// getAbsoluteRanges - Returns absolute address ranges defined by this range
+ /// list. Has to be passed base address of the compile unit referencing this
+ /// range list.
+ DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
};
} // namespace llvm
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index da71fb3..8d0f966 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -131,7 +131,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
const DWARFUnit *cu) {
bool indirect = false;
bool is_block = false;
- Value.data = NULL;
+ Value.data = nullptr;
// Read the value for the form into value and follow and DW_FORM_indirect
// instances we run into
do {
@@ -241,7 +241,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
if (is_block) {
StringRef str = data.getData().substr(*offset_ptr, Value.uval);
- Value.data = NULL;
+ Value.data = nullptr;
if (!str.empty()) {
Value.data = reinterpret_cast<const uint8_t *>(str.data());
*offset_ptr += Value.uval;
@@ -488,7 +488,7 @@ Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
return None;
if (Form == DW_FORM_string)
return Value.cstr;
- if (U == 0)
+ if (!U)
return None;
uint32_t Offset = Value.uval;
if (Form == DW_FORM_GNU_str_index) {
@@ -509,7 +509,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
if (Form == DW_FORM_GNU_addr_index) {
uint32_t Index = Value.uval;
uint64_t Result;
- if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
+ if (!U || !U->getAddrOffsetSectionItem(Index, Result))
return None;
return Result;
}
@@ -525,7 +525,7 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- if (U == 0)
+ if (!U)
return None;
return Value.uval + U->getOffset();
case DW_FORM_ref_addr:
diff --git a/lib/DebugInfo/DWARFTypeUnit.h b/lib/DebugInfo/DWARFTypeUnit.h
index 05e13ff..cf773b8 100644
--- a/lib/DebugInfo/DWARFTypeUnit.h
+++ b/lib/DebugInfo/DWARFTypeUnit.h
@@ -19,11 +19,13 @@ private:
uint64_t TypeHash;
uint32_t TypeOffset;
public:
- DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
- StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS,
+ StringRef SS, StringRef SOS, StringRef AOS,
const RelocAddrMap *M, bool LE)
- : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {}
- uint32_t getSize() const override { return DWARFUnit::getSize() + 12; }
+ : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {}
+ uint32_t getHeaderSize() const override {
+ return DWARFUnit::getHeaderSize() + 12;
+ }
void dump(raw_ostream &OS);
protected:
bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
diff --git a/lib/DebugInfo/DWARFUnit.cpp b/lib/DebugInfo/DWARFUnit.cpp
index 316c208..f5f5072 100644
--- a/lib/DebugInfo/DWARFUnit.cpp
+++ b/lib/DebugInfo/DWARFUnit.cpp
@@ -17,12 +17,12 @@
using namespace llvm;
using namespace dwarf;
-DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
- StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS,
+ StringRef SS, StringRef SOS, StringRef AOS,
const RelocAddrMap *M, bool LE)
- : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS),
- StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
- RelocMap(M), isLittleEndian(LE) {
+ : Abbrev(DA), InfoSection(IS), RangeSection(RS), StringSection(SS),
+ StringOffsetSection(SOS), AddrOffsetSection(AOS), RelocMap(M),
+ isLittleEndian(LE) {
clear();
}
@@ -54,18 +54,20 @@ bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
Length = debug_info.getU32(offset_ptr);
Version = debug_info.getU16(offset_ptr);
- uint64_t abbrOffset = debug_info.getU32(offset_ptr);
+ uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
AddrSize = debug_info.getU8(offset_ptr);
- bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
- bool versionOK = DWARFContext::isSupportedVersion(Version);
- bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
- bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
+ bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
+ bool VersionOK = DWARFContext::isSupportedVersion(Version);
+ bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
- if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK)
+ if (!LengthOK || !VersionOK || !AddrSizeOK)
+ return false;
+
+ Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
+ if (Abbrevs == nullptr)
return false;
- Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
return true;
}
@@ -98,7 +100,7 @@ void DWARFUnit::clear() {
Offset = 0;
Length = 0;
Version = 0;
- Abbrevs = 0;
+ Abbrevs = nullptr;
AddrSize = 0;
BaseAddr = 0;
RangeSectionBase = 0;
@@ -110,8 +112,8 @@ void DWARFUnit::clear() {
const char *DWARFUnit::getCompilationDir() {
extractDIEsIfNeeded(true);
if (DieArray.empty())
- return 0;
- return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
+ return nullptr;
+ return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
}
uint64_t DWARFUnit::getDWOId() {
@@ -124,38 +126,32 @@ uint64_t DWARFUnit::getDWOId() {
}
void DWARFUnit::setDIERelations() {
- if (DieArray.empty())
+ if (DieArray.size() <= 1)
return;
- DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front();
- DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back();
- DWARFDebugInfoEntryMinimal *curr_die;
- // We purposely are skipping the last element in the array in the loop below
- // so that we can always have a valid next item
- for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) {
- // Since our loop doesn't include the last element, we can always
- // safely access the next die in the array.
- DWARFDebugInfoEntryMinimal *next_die = curr_die + 1;
-
- const DWARFAbbreviationDeclaration *curr_die_abbrev =
- curr_die->getAbbreviationDeclarationPtr();
-
- if (curr_die_abbrev) {
- // Normal DIE
- if (curr_die_abbrev->hasChildren())
- next_die->setParent(curr_die);
- else
- curr_die->setSibling(next_die);
+
+ std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
+ DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
+ for (auto &DIE : DieArray) {
+ if (SiblingChain) {
+ SiblingChain->setSibling(&DIE);
+ }
+ if (const DWARFAbbreviationDeclaration *AbbrDecl =
+ DIE.getAbbreviationDeclarationPtr()) {
+ // Normal DIE.
+ if (AbbrDecl->hasChildren()) {
+ ParentChain.push_back(&DIE);
+ SiblingChain = nullptr;
+ } else {
+ SiblingChain = &DIE;
+ }
} else {
- // NULL DIE that terminates a sibling chain
- DWARFDebugInfoEntryMinimal *parent = curr_die->getParent();
- if (parent)
- parent->setSibling(next_die);
+ // NULL entry terminates the sibling chain.
+ SiblingChain = ParentChain.back();
+ ParentChain.pop_back();
}
}
-
- // Since we skipped the last element, we need to fix it up!
- if (die_array_begin < die_array_end)
- curr_die->setParent(die_array_begin);
+ assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);
+ assert(ParentChain.empty());
}
void DWARFUnit::extractDIEsToVector(
@@ -166,13 +162,13 @@ void DWARFUnit::extractDIEsToVector(
// Set the offset to that of the first DIE and calculate the start of the
// next compilation unit header.
- uint32_t Offset = getFirstDIEOffset();
+ uint32_t DIEOffset = Offset + getHeaderSize();
uint32_t NextCUOffset = getNextUnitOffset();
DWARFDebugInfoEntryMinimal DIE;
uint32_t Depth = 0;
bool IsCUDie = true;
- while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) {
+ while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) {
if (IsCUDie) {
if (AppendCUDie)
Dies.push_back(DIE);
@@ -187,9 +183,8 @@ void DWARFUnit::extractDIEsToVector(
Dies.push_back(DIE);
}
- const DWARFAbbreviationDeclaration *AbbrDecl =
- DIE.getAbbreviationDeclarationPtr();
- if (AbbrDecl) {
+ if (const DWARFAbbreviationDeclaration *AbbrDecl =
+ DIE.getAbbreviationDeclarationPtr()) {
// Normal DIE
if (AbbrDecl->hasChildren())
++Depth;
@@ -205,9 +200,9 @@ void DWARFUnit::extractDIEsToVector(
// Give a little bit of info if we encounter corrupt DWARF (our offset
// should always terminate at or before the start of the next compilation
// unit header).
- if (Offset > NextCUOffset)
+ if (DIEOffset > NextCUOffset)
fprintf(stderr, "warning: DWARF compile unit extends beyond its "
- "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset);
+ "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset);
}
size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
@@ -241,25 +236,25 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
DWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile)
: DWOFile(DWOFile),
DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))),
- DWOU(0) {
+ DWOU(nullptr) {
if (DWOContext->getNumDWOCompileUnits() > 0)
DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
}
bool DWARFUnit::parseDWO() {
- if (DWO.get() != 0)
+ if (DWO.get())
return false;
extractDIEsIfNeeded(true);
if (DieArray.empty())
return false;
const char *DWOFileName =
- DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0);
- if (DWOFileName == 0)
+ DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr);
+ if (!DWOFileName)
return false;
const char *CompilationDir =
- DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
+ DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
SmallString<16> AbsolutePath;
- if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) {
+ if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
sys::path::append(AbsolutePath, CompilationDir);
}
sys::path::append(AbsolutePath, DWOFileName);
@@ -271,7 +266,7 @@ bool DWARFUnit::parseDWO() {
DWO.reset(new DWOHolder(DWOFile.get()));
DWARFUnit *DWOCU = DWO->getUnit();
// Verify that compile unit in .dwo file is valid.
- if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) {
+ if (!DWOCU || DWOCU->getDWOId() != getDWOId()) {
DWO.reset();
return false;
}
@@ -298,33 +293,33 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
}
}
-void
-DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
- bool clear_dies_if_already_not_parsed,
- uint32_t CUOffsetInAranges) {
+void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
+ // First, check if CU DIE describes address ranges for the unit.
+ const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this);
+ if (!CUDIERanges.empty()) {
+ CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
+ return;
+ }
+
// This function is usually called if there in no .debug_aranges section
// in order to produce a compile unit level set of address ranges that
// is accurate. If the DIEs weren't parsed, then we don't want all dies for
// all compile units to stay loaded when they weren't needed. So we can end
// up parsing the DWARF and then throwing them all away to keep memory usage
// down.
- const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
- clear_dies_if_already_not_parsed;
- DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
+ const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
+ DieArray[0].collectChildrenAddressRanges(this, CURanges);
+
+ // Collect address ranges from DIEs in .dwo if necessary.
bool DWOCreated = parseDWO();
- if (DWO.get()) {
- // If there is a .dwo file for this compile unit, then skeleton CU DIE
- // doesn't have children, and we should instead build address range table
- // from DIEs in the .debug_info.dwo section of .dwo file.
- DWO->getUnit()->buildAddressRangeTable(
- debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges);
- }
- if (DWOCreated && clear_dies_if_already_not_parsed)
+ if (DWO.get())
+ DWO->getUnit()->collectAddressRanges(CURanges);
+ if (DWOCreated)
DWO.reset();
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed.
- if (clear_dies)
+ if (ClearDIEs)
clearDIEs(true);
}
@@ -337,14 +332,14 @@ DWARFUnit::getSubprogramForAddress(uint64_t Address) {
return &DIE;
}
}
- return 0;
+ return nullptr;
}
DWARFDebugInfoEntryInlinedChain
DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
// First, find a subprogram that contains the given address (the root
// of inlined chain).
- const DWARFUnit *ChainCU = 0;
+ const DWARFUnit *ChainCU = nullptr;
const DWARFDebugInfoEntryMinimal *SubprogramDIE =
getSubprogramForAddress(Address);
if (SubprogramDIE) {
diff --git a/lib/DebugInfo/DWARFUnit.h b/lib/DebugInfo/DWARFUnit.h
index 5b4cf09..471da36 100644
--- a/lib/DebugInfo/DWARFUnit.h
+++ b/lib/DebugInfo/DWARFUnit.h
@@ -29,7 +29,6 @@ class raw_ostream;
class DWARFUnit {
const DWARFDebugAbbrev *Abbrev;
StringRef InfoSection;
- StringRef AbbrevSection;
StringRef RangeSection;
uint32_t RangeSectionBase;
StringRef StringSection;
@@ -60,12 +59,13 @@ class DWARFUnit {
protected:
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+ /// Size in bytes of the unit header.
+ virtual uint32_t getHeaderSize() const { return 11; }
public:
-
- DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
- StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
- const RelocAddrMap *M, bool LE);
+ DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS,
+ StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M,
+ bool LE);
virtual ~DWARFUnit();
@@ -102,12 +102,7 @@ public:
DWARFDebugRangeList &RangeList) const;
void clear();
uint32_t getOffset() const { return Offset; }
- /// Size in bytes of the compile unit header.
- virtual uint32_t getSize() const { return 11; }
- uint32_t getFirstDIEOffset() const { return Offset + getSize(); }
uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
- /// Size in bytes of the .debug_info data associated with this compile unit.
- size_t getDebugInfoSize() const { return Length + 4 - getSize(); }
uint32_t getLength() const { return Length; }
uint16_t getVersion() const { return Version; }
const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
@@ -123,15 +118,13 @@ public:
const DWARFDebugInfoEntryMinimal *
getCompileUnitDIE(bool extract_cu_die_only = true) {
extractDIEsIfNeeded(extract_cu_die_only);
- return DieArray.empty() ? NULL : &DieArray[0];
+ return DieArray.empty() ? nullptr : &DieArray[0];
}
const char *getCompilationDir();
uint64_t getDWOId();
- void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
- bool clear_dies_if_already_not_parsed,
- uint32_t CUOffsetInAranges);
+ void collectAddressRanges(DWARFAddressRangesVector &CURanges);
/// getInlinedChainForAddress - fetches inlined chain for a given address.
/// Returns empty chain if there is no subprogram containing address. The
@@ -139,6 +132,9 @@ public:
DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address);
private:
+ /// Size in bytes of the .debug_info data associated with this compile unit.
+ size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
+
/// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
/// hasn't already been done. Returns the number of DIEs parsed at this call.
size_t extractDIEsIfNeeded(bool CUDieOnly);
diff --git a/lib/DebugInfo/module.modulemap b/lib/DebugInfo/module.modulemap
new file mode 100644
index 0000000..1fe5ab1
--- /dev/null
+++ b/lib/DebugInfo/module.modulemap
@@ -0,0 +1 @@
+module DebugInfo { requires cplusplus umbrella "." module * { export * } }