summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/DebugInfo')
-rw-r--r--contrib/llvm/lib/DebugInfo/DIContext.cpp7
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp48
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h16
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFContext.cpp220
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFContext.h40
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp1
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp184
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h54
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp27
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugLine.h8
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp67
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h78
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp76
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARFFormValue.h2
14 files changed, 669 insertions, 159 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DIContext.cpp b/contrib/llvm/lib/DebugInfo/DIContext.cpp
index e2fd55f..691a92c 100644
--- a/contrib/llvm/lib/DebugInfo/DIContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/DIContext.cpp
@@ -18,7 +18,10 @@ DIContext *DIContext::getDWARFContext(bool isLittleEndian,
StringRef abbrevSection,
StringRef aRangeSection,
StringRef lineSection,
- StringRef stringSection) {
+ StringRef stringSection,
+ StringRef rangeSection,
+ const RelocAddrMap &Map) {
return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
- aRangeSection, lineSection, stringSection);
+ aRangeSection, lineSection, stringSection,
+ rangeSection, Map);
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
index b27d57b..bdd65b7 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp
@@ -63,7 +63,7 @@ DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
Version = debug_info_data.getU16(&offset);
bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset();
Abbrevs = abbrevs;
- AddrSize = debug_info_data.getU8 (&offset);
+ AddrSize = debug_info_data.getU8(&offset);
bool versionOK = DWARFContext::isSupportedVersion(Version);
bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
@@ -75,6 +75,15 @@ DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
return 0;
}
+bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const {
+ // Require that compile unit is extracted.
+ assert(DieArray.size() > 0);
+ DataExtractor RangesData(Context.getRangeSection(),
+ Context.isLittleEndian(), AddrSize);
+ return RangeList.extract(RangesData, &RangeListOffset);
+}
+
void DWARFCompileUnit::clear() {
Offset = 0;
Length = 0;
@@ -94,7 +103,9 @@ void DWARFCompileUnit::dump(raw_ostream &OS) {
<< " (next CU at " << format("0x%08x", getNextCompileUnitOffset())
<< ")\n";
- getCompileUnitDIE(false)->dump(OS, this, -1U);
+ const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false);
+ assert(CU && "Null Compile Unit?");
+ CU->dump(OS, this, -1U);
}
const char *DWARFCompileUnit::getCompilationDir() {
@@ -174,11 +185,11 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
addDIE(die);
return 1;
}
- else if (depth == 0 && initial_die_array_size == 1) {
+ else if (depth == 0 && initial_die_array_size == 1)
// Don't append the CU die as we already did that
- } else {
- addDIE (die);
- }
+ ;
+ else
+ addDIE(die);
const DWARFAbbreviationDeclaration *abbrDecl =
die.getAbbreviationDeclarationPtr();
@@ -199,9 +210,9 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
// 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 > next_cu_offset) {
- fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
- }
+ if (offset > next_cu_offset)
+ fprintf(stderr, "warning: DWARF compile unit extends beyond its"
+ "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
setDIERelations();
return DieArray.size();
@@ -244,12 +255,21 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
clearDIEs(true);
}
-const DWARFDebugInfoEntryMinimal*
-DWARFCompileUnit::getFunctionDIEForAddress(int64_t address) {
+DWARFDebugInfoEntryMinimal::InlinedChain
+DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) {
+ // First, find a subprogram that contains the given address (the root
+ // of inlined chain).
extractDIEsIfNeeded(false);
+ const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0;
for (size_t i = 0, n = DieArray.size(); i != n; i++) {
- if (DieArray[i].addressRangeContainsAddress(this, address))
- return &DieArray[i];
+ if (DieArray[i].isSubprogramDIE() &&
+ DieArray[i].addressRangeContainsAddress(this, Address)) {
+ SubprogramDIE = &DieArray[i];
+ break;
+ }
}
- return 0;
+ // Get inlined chain rooted at this subprogram DIE.
+ if (!SubprogramDIE)
+ return DWARFDebugInfoEntryMinimal::InlinedChain();
+ return SubprogramDIE->getInlinedChainForAddress(this, Address);
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
index b34a596..03e2862 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h
@@ -12,6 +12,7 @@
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugRangeList.h"
#include <vector>
namespace llvm {
@@ -45,6 +46,11 @@ public:
/// 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 cu_die_only);
+ /// extractRangeList - extracts the range list referenced by this compile
+ /// unit from .debug_ranges section. Returns true on success.
+ /// Requires that compile unit is already extracted.
+ bool extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
void clear();
void dump(raw_ostream &OS);
uint32_t getOffset() const { return Offset; }
@@ -106,11 +112,11 @@ public:
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
bool clear_dies_if_already_not_parsed);
- /// getFunctionDIEForAddress - Returns pointer to parsed subprogram DIE,
- /// address ranges of which contain the provided address,
- /// or NULL if there is no such subprogram. The pointer
- /// is valid until DWARFCompileUnit::clear() or clearDIEs() is called.
- const DWARFDebugInfoEntryMinimal *getFunctionDIEForAddress(int64_t address);
+
+ /// getInlinedChainForAddress - fetches inlined chain for a given address.
+ /// Returns empty chain if there is no subprogram containing address.
+ DWARFDebugInfoEntryMinimal::InlinedChain getInlinedChainForAddress(
+ uint64_t Address);
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
index 797662b..afd614c 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp
@@ -17,6 +17,8 @@
using namespace llvm;
using namespace dwarf;
+typedef DWARFDebugLine::LineTable DWARFLineTable;
+
void DWARFContext::dump(raw_ostream &OS) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
@@ -32,15 +34,17 @@ void DWARFContext::dump(raw_ostream &OS) {
while (set.extract(arangesData, &offset))
set.dump(OS);
+ uint8_t savedAddressByteSize = 0;
OS << "\n.debug_lines contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
+ savedAddressByteSize = cu->getAddressByteSize();
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-1U);
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection(), isLittleEndian(),
- cu->getAddressByteSize());
+ savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
}
@@ -54,6 +58,18 @@ void DWARFContext::dump(raw_ostream &OS) {
OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
lastOffset = offset;
}
+
+ OS << "\n.debug_ranges contents:\n";
+ // In fact, different compile units may have different address byte
+ // sizes, but for simplicity we just use the address byte size of the last
+ // compile unit (there is no easy and fast way to associate address range
+ // list and the compile unit it describes).
+ DataExtractor rangesData(getRangeSection(), isLittleEndian(),
+ savedAddressByteSize);
+ offset = 0;
+ DWARFDebugRangeList rangeList;
+ while (rangeList.extract(rangesData, &offset))
+ rangeList.dump(OS);
}
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@@ -80,7 +96,7 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
return Aranges.get();
}
-const DWARFDebugLine::LineTable *
+const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
Line.reset(new DWARFDebugLine());
@@ -92,7 +108,7 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
return 0; // No line table for this compile unit.
// See if the line table is cached.
- if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset))
+ if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
return lt;
// We have to parse it first.
@@ -103,11 +119,11 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
void DWARFContext::parseCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
- isLittleEndian(), 0);
- while (debug_info_data.isValidOffset(offset)) {
+ const DataExtractor &DIData = DataExtractor(getInfoSection(),
+ isLittleEndian(), 0);
+ while (DIData.isValidOffset(offset)) {
CUs.push_back(DWARFCompileUnit(*this));
- if (!CUs.back().extract(debug_info_data, &offset)) {
+ if (!CUs.back().extract(DIData, &offset)) {
CUs.pop_back();
break;
}
@@ -131,75 +147,155 @@ namespace {
};
}
-DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) {
+DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
if (CUs.empty())
parseCompileUnits();
- DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset,
- OffsetComparator());
- if (i != CUs.end())
- return &*i;
+ DWARFCompileUnit *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset,
+ OffsetComparator());
+ if (CU != CUs.end())
+ return &*CU;
return 0;
}
-DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address,
- DILineInfoSpecifier specifier) {
+DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
// First, get the offset of the compile unit.
- uint32_t cuOffset = getDebugAranges()->findAddress(address);
+ uint32_t CUOffset = getDebugAranges()->findAddress(Address);
// Retrieve the compile unit.
- DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset);
- if (!cu)
+ return getCompileUnitForOffset(CUOffset);
+}
+
+static bool getFileNameForCompileUnit(DWARFCompileUnit *CU,
+ const DWARFLineTable *LineTable,
+ uint64_t FileIndex,
+ bool NeedsAbsoluteFilePath,
+ std::string &FileName) {
+ if (CU == 0 ||
+ LineTable == 0 ||
+ !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath,
+ FileName))
+ return false;
+ if (NeedsAbsoluteFilePath && 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()) {
+ sys::path::append(AbsolutePath, CompilationDir);
+ }
+ sys::path::append(AbsolutePath, FileName);
+ FileName = AbsolutePath.str();
+ }
+ return true;
+}
+
+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)
+ return false;
+ // Get the index of row we're looking for in the line table.
+ uint32_t RowIndex = LineTable->lookupAddress(Address);
+ if (RowIndex == -1U)
+ 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))
+ return false;
+ Line = Row.Line;
+ Column = Row.Column;
+ return true;
+}
+
+DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier) {
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
return DILineInfo();
- SmallString<16> fileName("<invalid>");
- SmallString<16> functionName("<invalid>");
- uint32_t line = 0;
- uint32_t column = 0;
- if (specifier.needs(DILineInfoSpecifier::FunctionName)) {
- const DWARFDebugInfoEntryMinimal *function_die =
- cu->getFunctionDIEForAddress(address);
- if (function_die) {
- if (const char *name = function_die->getSubprogramName(cu))
- functionName = name;
+ 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 DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ FunctionName = Name;
}
}
- if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- // Get the line table for this compile unit.
- const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu);
- if (lineTable) {
- // Get the index of the row we're looking for in the line table.
- uint32_t rowIndex = lineTable->lookupAddress(address);
- if (rowIndex != -1U) {
- const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex];
- // Take file/line info from the line table.
- const DWARFDebugLine::FileNameEntry &fileNameEntry =
- lineTable->Prologue.FileNames[row.File - 1];
- fileName = fileNameEntry.Name;
- if (specifier.needs(DILineInfoSpecifier::AbsoluteFilePath) &&
- sys::path::is_relative(fileName.str())) {
- // Append include directory of file (if it is present in line table)
- // and compilation directory of compile unit to make path absolute.
- const char *includeDir = 0;
- if (uint64_t includeDirIndex = fileNameEntry.DirIdx) {
- includeDir = lineTable->Prologue
- .IncludeDirectories[includeDirIndex - 1];
- }
- SmallString<16> absFileName;
- if (includeDir == 0 || sys::path::is_relative(includeDir)) {
- if (const char *compilationDir = cu->getCompilationDir())
- sys::path::append(absFileName, compilationDir);
- }
- if (includeDir) {
- sys::path::append(absFileName, includeDir);
- }
- sys::path::append(absFileName, fileName.str());
- fileName = absFileName;
- }
- line = row.Line;
- column = row.Column;
+ if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
+ const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
+ const bool NeedsAbsoluteFilePath =
+ Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
+ getFileLineInfoForCompileUnit(CU, LineTable, Address,
+ NeedsAbsoluteFilePath,
+ FileName, Line, Column);
+ }
+ return DILineInfo(StringRef(FileName), StringRef(FunctionName),
+ Line, Column);
+}
+
+DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier) {
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return DIInliningInfo();
+
+ const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.size() == 0)
+ return DIInliningInfo();
+
+ DIInliningInfo InliningInfo;
+ uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
+ const DWARFLineTable *LineTable = 0;
+ for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
+ const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
+ std::string FileName = "<invalid>";
+ std::string FunctionName = "<invalid>";
+ uint32_t Line = 0;
+ uint32_t Column = 0;
+ // Get function name if necessary.
+ if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
+ if (const char *Name = FunctionDIE.getSubroutineName(CU))
+ FunctionName = Name;
+ }
+ if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
+ const bool NeedsAbsoluteFilePath =
+ Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
+ 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);
+ } 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;
+ }
+ // Get call file/line/column of a current DIE.
+ if (i + 1 < n) {
+ FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn);
}
}
+ DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
+ Line, Column);
+ InliningInfo.addFrame(Frame);
}
- return DILineInfo(fileName, functionName, line, column);
+ return InliningInfo;
}
void DWARFContextInMemory::anchor() { }
diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.h b/contrib/llvm/lib/DebugInfo/DWARFContext.h
index e55a27e..4001792 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFContext.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFContext.h
@@ -13,6 +13,7 @@
#include "DWARFCompileUnit.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugLine.h"
+#include "DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,21 +26,24 @@ namespace llvm {
/// methods that a concrete implementation provides.
class DWARFContext : public DIContext {
bool IsLittleEndian;
+ const RelocAddrMap &RelocMap;
SmallVector<DWARFCompileUnit, 1> CUs;
OwningPtr<DWARFDebugAbbrev> Abbrev;
OwningPtr<DWARFDebugAranges> Aranges;
OwningPtr<DWARFDebugLine> Line;
- DWARFContext(DWARFContext &); // = delete
- DWARFContext &operator=(DWARFContext &); // = delete
+ DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
+ DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
/// Read compile units from the debug_info section and store them in CUs.
void parseCompileUnits();
protected:
- DWARFContext(bool isLittleEndian) : IsLittleEndian(isLittleEndian) {}
+ DWARFContext(bool isLittleEndian, const RelocAddrMap &Map) :
+ IsLittleEndian(isLittleEndian), RelocMap(Map) {}
public:
virtual void dump(raw_ostream &OS);
+
/// Get the number of compile units in this context.
unsigned getNumCompileUnits() {
if (CUs.empty())
@@ -53,9 +57,6 @@ public:
return &CUs[index];
}
- /// Return the compile unit that includes an offset (relative to .debug_info).
- DWARFCompileUnit *getCompileUnitForOffset(uint32_t offset);
-
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
@@ -66,22 +67,32 @@ public:
const DWARFDebugLine::LineTable *
getLineTableForCompileUnit(DWARFCompileUnit *cu);
- virtual DILineInfo getLineInfoForAddress(uint64_t address,
- DILineInfoSpecifier specifier = DILineInfoSpecifier());
+ virtual DILineInfo getLineInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier());
+ virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier = DILineInfoSpecifier());
bool isLittleEndian() const { return IsLittleEndian; }
+ const RelocAddrMap &relocMap() const { return RelocMap; }
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getLineSection() = 0;
virtual StringRef getStringSection() = 0;
+ virtual StringRef getRangeSection() = 0;
static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3;
}
-};
+private:
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
+ /// Return the compile unit which contains instruction with provided
+ /// address.
+ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
+};
/// DWARFContextInMemory is the simplest possible implementation of a
/// DWARFContext. It assumes all content is available in memory and stores
@@ -93,19 +104,23 @@ class DWARFContextInMemory : public DWARFContext {
StringRef ARangeSection;
StringRef LineSection;
StringRef StringSection;
+ StringRef RangeSection;
public:
DWARFContextInMemory(bool isLittleEndian,
StringRef infoSection,
StringRef abbrevSection,
StringRef aRangeSection,
StringRef lineSection,
- StringRef stringSection)
- : DWARFContext(isLittleEndian),
+ StringRef stringSection,
+ StringRef rangeSection,
+ const RelocAddrMap &Map = RelocAddrMap())
+ : DWARFContext(isLittleEndian, Map),
InfoSection(infoSection),
AbbrevSection(abbrevSection),
ARangeSection(aRangeSection),
LineSection(lineSection),
- StringSection(stringSection)
+ StringSection(stringSection),
+ RangeSection(rangeSection)
{}
virtual StringRef getInfoSection() { return InfoSection; }
@@ -113,6 +128,7 @@ public:
virtual StringRef getARangeSection() { return ARangeSection; }
virtual StringRef getLineSection() { return LineSection; }
virtual StringRef getStringSection() { return StringSection; }
+ virtual StringRef getRangeSection() { return RangeSection; }
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
index ef470e5..f9a34c9 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp
@@ -62,7 +62,6 @@ bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) {
uint32_t offset = 0;
typedef std::vector<DWARFDebugArangeSet> SetCollection;
- typedef SetCollection::const_iterator SetCollectionIter;
SetCollection sets;
DWARFDebugArangeSet set;
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index 429a36c..ab67464 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -1,4 +1,4 @@
-//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===//
+//===-- DWARFDebugInfoEntry.cpp -------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -101,7 +101,7 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
DataExtractor debug_info_data = cu->getDebugInfoExtractor();
uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);
- assert (fixed_form_sizes); // For best performance this should be specified!
+ assert(fixed_form_sizes); // For best performance this should be specified!
if (abbrCode) {
uint32_t offset = *offset_ptr;
@@ -126,6 +126,7 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
switch (form) {
// Blocks if inlined data that have a length field and the data bytes
// inlined in the .debug_info.
+ case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.getULEB128(&offset);
break;
@@ -150,6 +151,11 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
form_size = cu->getAddressByteSize();
break;
+ // 0 sized form.
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
@@ -173,6 +179,7 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
form_size = 8;
break;
@@ -188,6 +195,13 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
form = debug_info_data.getULEB128(&offset);
break;
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ debug_info_data.getU32(offset_ptr);
+ else
+ debug_info_data.getU64(offset_ptr);
+ break;
+
default:
*offset_ptr = Offset;
return false;
@@ -249,6 +263,7 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
switch (form) {
// Blocks if inlined data that have a length field and the data
// bytes // inlined in the .debug_info
+ case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.getULEB128(&offset);
break;
@@ -273,6 +288,11 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
form_size = cu_addr_size;
break;
+ // 0 byte value
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
@@ -299,6 +319,7 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
form_size = 8;
break;
@@ -314,6 +335,13 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
form_is_indirect = true;
break;
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ debug_info_data.getU32(offset_ptr);
+ else
+ debug_info_data.getU64(offset_ptr);
+ break;
+
default:
*offset_ptr = offset;
return false;
@@ -336,6 +364,16 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
return false;
}
+bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
+ return getTag() == DW_TAG_subprogram;
+}
+
+bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
+ uint32_t Tag = getTag();
+ return Tag == DW_TAG_subprogram ||
+ Tag == DW_TAG_inlined_subroutine;
+}
+
uint32_t
DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
const uint16_t attr,
@@ -373,9 +411,10 @@ DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
const char*
DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- const char* fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ const char* fail_value)
+ const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value)) {
DataExtractor stringExtractor(cu->getContext().getStringSection(),
@@ -387,9 +426,9 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ uint64_t fail_value) const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getUnsigned();
@@ -398,9 +437,9 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
int64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- int64_t fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ int64_t fail_value) const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getSigned();
@@ -409,33 +448,42 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ uint64_t fail_value)
+ const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getReference(cu);
return fail_value;
}
+bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU,
+ uint64_t &LowPC,
+ uint64_t &HighPC) const {
+ HighPC = -1ULL;
+ LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL);
+ if (LowPC != -1ULL)
+ HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL);
+ return (HighPC != -1ULL);
+}
+
void
-DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
- DWARFDebugAranges *debug_aranges)
+DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
+ DWARFDebugAranges *DebugAranges)
const {
if (AbbrevDecl) {
- uint16_t tag = AbbrevDecl->getTag();
- if (tag == DW_TAG_subprogram) {
- uint64_t hi_pc = -1ULL;
- uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
- if (lo_pc != -1ULL)
- hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
- if (hi_pc != -1ULL)
- debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
+ if (isSubprogramDIE()) {
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(CU, LowPC, HighPC)) {
+ DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC);
+ }
+ // FIXME: try to append ranges from .debug_ranges section.
}
const DWARFDebugInfoEntryMinimal *child = getFirstChild();
while (child) {
- child->buildAddressRangeTable(cu, debug_aranges);
+ child->buildAddressRangeTable(CU, DebugAranges);
child = child->getSibling();
}
}
@@ -443,51 +491,95 @@ DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
bool
DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
- const DWARFCompileUnit *cu, const uint64_t address) const {
- if (!isNULL() && getTag() == DW_TAG_subprogram) {
- uint64_t hi_pc = -1ULL;
- uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
- if (lo_pc != -1ULL)
- hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
- if (hi_pc != -1ULL) {
- return (lo_pc <= address && address < hi_pc);
- }
+ const DWARFCompileUnit *CU,
+ const uint64_t Address)
+ const {
+ if (isNULL())
+ return false;
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(CU, LowPC, HighPC))
+ return (LowPC <= Address && Address <= HighPC);
+ // Try to get address ranges from .debug_ranges section.
+ uint32_t RangesOffset = getAttributeValueAsReference(CU, DW_AT_ranges, -1U);
+ if (RangesOffset != -1U) {
+ DWARFDebugRangeList RangeList;
+ if (CU->extractRangeList(RangesOffset, RangeList))
+ return RangeList.containsAddress(CU->getBaseAddress(), Address);
}
return false;
}
const char*
-DWARFDebugInfoEntryMinimal::getSubprogramName(
- const DWARFCompileUnit *cu) const {
- if (isNULL() || getTag() != DW_TAG_subprogram)
+DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFCompileUnit *CU)
+ const {
+ if (!isSubroutineDIE())
return 0;
// Try to get mangled name if possible.
if (const char *name =
- getAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, 0))
+ getAttributeValueAsString(CU, DW_AT_MIPS_linkage_name, 0))
return name;
- if (const char *name = getAttributeValueAsString(cu, DW_AT_linkage_name, 0))
+ if (const char *name = getAttributeValueAsString(CU, DW_AT_linkage_name, 0))
return name;
- if (const char *name = getAttributeValueAsString(cu, DW_AT_name, 0))
+ if (const char *name = getAttributeValueAsString(CU, DW_AT_name, 0))
return name;
// Try to get name from specification DIE.
uint32_t spec_ref =
- getAttributeValueAsReference(cu, DW_AT_specification, -1U);
+ getAttributeValueAsReference(CU, DW_AT_specification, -1U);
if (spec_ref != -1U) {
DWARFDebugInfoEntryMinimal spec_die;
- if (spec_die.extract(cu, &spec_ref)) {
- if (const char *name = spec_die.getSubprogramName(cu))
+ if (spec_die.extract(CU, &spec_ref)) {
+ if (const char *name = spec_die.getSubroutineName(CU))
return name;
}
}
// Try to get name from abstract origin DIE.
uint32_t abs_origin_ref =
- getAttributeValueAsReference(cu, DW_AT_abstract_origin, -1U);
+ getAttributeValueAsReference(CU, DW_AT_abstract_origin, -1U);
if (abs_origin_ref != -1U) {
DWARFDebugInfoEntryMinimal abs_origin_die;
- if (abs_origin_die.extract(cu, &abs_origin_ref)) {
- if (const char *name = abs_origin_die.getSubprogramName(cu))
+ if (abs_origin_die.extract(CU, &abs_origin_ref)) {
+ if (const char *name = abs_origin_die.getSubroutineName(CU))
return name;
}
}
return 0;
}
+
+void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFCompileUnit *CU,
+ uint32_t &CallFile,
+ uint32_t &CallLine,
+ uint32_t &CallColumn) const {
+ CallFile = getAttributeValueAsUnsigned(CU, DW_AT_call_file, 0);
+ CallLine = getAttributeValueAsUnsigned(CU, DW_AT_call_line, 0);
+ CallColumn = getAttributeValueAsUnsigned(CU, DW_AT_call_column, 0);
+}
+
+DWARFDebugInfoEntryMinimal::InlinedChain
+DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
+ const DWARFCompileUnit *CU,
+ const uint64_t Address)
+ const {
+ DWARFDebugInfoEntryMinimal::InlinedChain InlinedChain;
+ if (isNULL())
+ return InlinedChain;
+ for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
+ // Append current DIE to inlined chain only if it has correct tag
+ // (e.g. it is not a lexical block).
+ if (DIE->isSubroutineDIE()) {
+ InlinedChain.push_back(*DIE);
+ }
+ // Try to get child which also contains provided address.
+ const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
+ while (Child) {
+ if (Child->addressRangeContainsAddress(CU, Address)) {
+ // Assume there is only one such child.
+ break;
+ }
+ Child = Child->getSibling();
+ }
+ DIE = Child;
+ }
+ // Reverse the obtained chain to make the root of inlined chain last.
+ std::reverse(InlinedChain.begin(), InlinedChain.end());
+ return InlinedChain;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
index d5d86b9..9c1b2be 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
#include "DWARFAbbreviationDeclaration.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -19,6 +20,7 @@ class DWARFDebugAranges;
class DWARFCompileUnit;
class DWARFContext;
class DWARFFormValue;
+class DWARFInlinedSubroutineChain;
/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
class DWARFDebugInfoEntryMinimal {
@@ -52,6 +54,13 @@ public:
uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
bool isNULL() const { return AbbrevDecl == 0; }
+
+ /// Returns true if DIE represents a subprogram (not inlined).
+ bool isSubprogramDIE() const;
+ /// Returns true if DIE represents a subprogram or an inlined
+ /// subroutine.
+ bool isSubroutineDIE() const;
+
uint32_t getOffset() const { return Offset; }
uint32_t getNumAttributes() const {
return !isNULL() ? AbbrevDecl->getNumAttributes() : 0;
@@ -126,17 +135,40 @@ public:
const uint16_t attr,
int64_t fail_value) const;
- void buildAddressRangeTable(const DWARFCompileUnit *cu,
- DWARFDebugAranges *debug_aranges) const;
-
- bool addressRangeContainsAddress(const DWARFCompileUnit *cu,
- const uint64_t address) const;
-
- // If a DIE represents a subprogram, 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* getSubprogramName(const DWARFCompileUnit *cu) const;
+ /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
+ /// Returns true if both attributes are present.
+ bool getLowAndHighPC(const DWARFCompileUnit *CU,
+ uint64_t &LowPC, uint64_t &HighPC) const;
+
+ void buildAddressRangeTable(const DWARFCompileUnit *CU,
+ DWARFDebugAranges *DebugAranges) const;
+
+ bool addressRangeContainsAddress(const DWARFCompileUnit *CU,
+ const uint64_t Address) const;
+
+ /// If a DIE represents a subprogram (or inlined subroutine),
+ /// 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 DWARFCompileUnit *CU) 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).
+ void getCallerFrame(const DWARFCompileUnit *CU, uint32_t &CallFile,
+ uint32_t &CallLine, uint32_t &CallColumn) const;
+
+ /// InlinedChain - represents a chain of inlined_subroutine
+ /// DIEs, (possibly ending with subprogram DIE), all of which are contained
+ /// in some concrete inlined instance tree. Address range for each DIE
+ /// (except the last DIE) in this chain is contained in address
+ /// range for next DIE in the chain.
+ typedef SmallVector<DWARFDebugInfoEntryMinimal, 4> InlinedChain;
+
+ /// Get inlined chain for a given address, rooted at the current DIE.
+ /// Returns empty chain if address is not contained in address range
+ /// of current DIE.
+ InlinedChain getInlinedChainForAddress(const DWARFCompileUnit *CU,
+ const uint64_t Address) const;
};
}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
index d99575d..267364a 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp
@@ -10,6 +10,7 @@
#include "DWARFDebugLine.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
@@ -513,3 +514,29 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
}
return index;
}
+
+bool
+DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
+ bool NeedsAbsoluteFilePath,
+ std::string &Result) const {
+ if (FileIndex == 0 || FileIndex > Prologue.FileNames.size())
+ return false;
+ const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
+ const char *FileName = Entry.Name;
+ if (!NeedsAbsoluteFilePath ||
+ sys::path::is_absolute(FileName)) {
+ Result = FileName;
+ return true;
+ }
+ SmallString<16> FilePath;
+ uint64_t IncludeDirIndex = Entry.DirIdx;
+ // Be defensive about the contents of Entry.
+ if (IncludeDirIndex > 0 &&
+ IncludeDirIndex <= Prologue.IncludeDirectories.size()) {
+ const char *IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1];
+ sys::path::append(FilePath, IncludeDir);
+ }
+ sys::path::append(FilePath, FileName);
+ Result = FilePath.str();
+ return true;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h
index 6382b45..586dd7e 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h
@@ -12,6 +12,7 @@
#include "llvm/Support/DataExtractor.h"
#include <map>
+#include <string>
#include <vector>
namespace llvm {
@@ -174,6 +175,13 @@ public:
// 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;
+
+ // Extracts filename by its index in filename table in prologue.
+ // Returns true on success.
+ bool getFileNameByIndex(uint64_t FileIndex,
+ bool NeedsAbsoluteFilePath,
+ std::string &Result) const;
+
void dump(raw_ostream &OS) const;
struct Prologue Prologue;
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp
new file mode 100644
index 0000000..1806bee
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp
@@ -0,0 +1,67 @@
+//===-- DWARFDebugRangesList.cpp ------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugRangeList.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFDebugRangeList::clear() {
+ Offset = -1U;
+ AddressSize = 0;
+ Entries.clear();
+}
+
+bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) {
+ clear();
+ if (!data.isValidOffset(*offset_ptr))
+ return false;
+ AddressSize = data.getAddressSize();
+ if (AddressSize != 4 && AddressSize != 8)
+ return false;
+ Offset = *offset_ptr;
+ while (true) {
+ RangeListEntry entry;
+ uint32_t prev_offset = *offset_ptr;
+ entry.StartAddress = data.getAddress(offset_ptr);
+ entry.EndAddress = data.getAddress(offset_ptr);
+ // Check that both values were extracted correctly.
+ if (*offset_ptr != prev_offset + 2 * AddressSize) {
+ clear();
+ return false;
+ }
+ if (entry.isEndOfListEntry())
+ break;
+ Entries.push_back(entry);
+ }
+ return true;
+}
+
+void DWARFDebugRangeList::dump(raw_ostream &OS) const {
+ for (int i = 0, n = Entries.size(); i != n; ++i) {
+ const char *format_str = (AddressSize == 4
+ ? "%08x %08" PRIx64 " %08" PRIx64 "\n"
+ : "%08x %016" PRIx64 " %016" PRIx64 "\n");
+ OS << format(format_str, Offset, Entries[i].StartAddress,
+ Entries[i].EndAddress);
+ }
+ OS << format("%08x <End of list>\n", Offset);
+}
+
+bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress,
+ uint64_t Address) const {
+ for (int i = 0, n = Entries.size(); i != n; ++i) {
+ if (Entries[i].isBaseAddressSelectionEntry(AddressSize))
+ BaseAddress = Entries[i].EndAddress;
+ else if (Entries[i].containsAddress(BaseAddress, Address))
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h
new file mode 100644
index 0000000..4e34a91
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h
@@ -0,0 +1,78 @@
+//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
+#define LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
+
+#include "llvm/Support/DataExtractor.h"
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugRangeList {
+public:
+ struct RangeListEntry {
+ // A beginning address offset. This address offset has the size of an
+ // address and is relative to the applicable base address of the
+ // compilation unit referencing this range list. It marks the beginning
+ // of an address range.
+ uint64_t StartAddress;
+ // An ending address offset. This address offset again has the size of
+ // an address and is relative to the applicable base address of the
+ // compilation unit referencing this range list. It marks the first
+ // address past the end of the address range. The ending address must
+ // be greater than or equal to the beginning address.
+ uint64_t EndAddress;
+ // The end of any given range list is marked by an end of list entry,
+ // which consists of a 0 for the beginning address offset
+ // and a 0 for the ending address offset.
+ bool isEndOfListEntry() const {
+ return (StartAddress == 0) && (EndAddress == 0);
+ }
+ // A base address selection entry consists of:
+ // 1. The value of the largest representable address offset
+ // (for example, 0xffffffff when the size of an address is 32 bits).
+ // 2. An address, which defines the appropriate base address for
+ // use in interpreting the beginning and ending address offsets of
+ // subsequent entries of the location list.
+ bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
+ assert(AddressSize == 4 || AddressSize == 8);
+ if (AddressSize == 4)
+ return StartAddress == -1U;
+ else
+ return StartAddress == -1ULL;
+ }
+ bool containsAddress(uint64_t BaseAddress, uint64_t Address) const {
+ return (BaseAddress + StartAddress <= Address) &&
+ (Address < BaseAddress + EndAddress);
+ }
+ };
+
+private:
+ // Offset in .debug_ranges section.
+ uint32_t Offset;
+ uint8_t AddressSize;
+ std::vector<RangeListEntry> Entries;
+
+public:
+ DWARFDebugRangeList() { clear(); }
+ 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;
+};
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
index ee2a3ab..fea9fd7 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
+++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp
@@ -10,6 +10,7 @@
#include "DWARFFormValue.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -41,6 +42,10 @@ static const uint8_t form_sizes_addr4[] = {
8, // 0x14 DW_FORM_ref8
0, // 0x15 DW_FORM_ref_udata
0, // 0x16 DW_FORM_indirect
+ 4, // 0x17 DW_FORM_sec_offset
+ 0, // 0x18 DW_FORM_exprloc
+ 0, // 0x19 DW_FORM_flag_present
+ 8, // 0x20 DW_FORM_ref_sig8
};
static const uint8_t form_sizes_addr8[] = {
@@ -67,6 +72,10 @@ static const uint8_t form_sizes_addr8[] = {
8, // 0x14 DW_FORM_ref8
0, // 0x15 DW_FORM_ref_udata
0, // 0x16 DW_FORM_indirect
+ 8, // 0x17 DW_FORM_sec_offset
+ 0, // 0x18 DW_FORM_exprloc
+ 0, // 0x19 DW_FORM_flag_present
+ 8, // 0x20 DW_FORM_ref_sig8
};
const uint8_t *
@@ -90,9 +99,18 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
indirect = false;
switch (Form) {
case DW_FORM_addr:
- case DW_FORM_ref_addr:
- Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
+ case DW_FORM_ref_addr: {
+ RelocAddrMap::const_iterator AI
+ = cu->getContext().relocMap().find(*offset_ptr);
+ if (AI != cu->getContext().relocMap().end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ Value.uval = R.second;
+ *offset_ptr += R.first;
+ } else
+ Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
+ }
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
Value.uval = data.getULEB128(offset_ptr);
is_block = true;
@@ -129,9 +147,17 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
case DW_FORM_sdata:
Value.sval = data.getSLEB128(offset_ptr);
break;
- case DW_FORM_strp:
- Value.uval = data.getU32(offset_ptr);
+ case DW_FORM_strp: {
+ RelocAddrMap::const_iterator AI
+ = cu->getContext().relocMap().find(*offset_ptr);
+ if (AI != cu->getContext().relocMap().end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ Value.uval = R.second;
+ *offset_ptr += R.first;
+ } else
+ Value.uval = data.getU32(offset_ptr);
break;
+ }
case DW_FORM_udata:
case DW_FORM_ref_udata:
Value.uval = data.getULEB128(offset_ptr);
@@ -141,12 +167,24 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
// Set the string value to also be the data for inlined cstr form
// values only so we can tell the differnence between DW_FORM_string
// and DW_FORM_strp form values
- Value.data = (uint8_t*)Value.cstr;
+ Value.data = (const uint8_t*)Value.cstr;
break;
case DW_FORM_indirect:
Form = data.getULEB128(offset_ptr);
indirect = true;
break;
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ Value.uval = data.getU32(offset_ptr);
+ else
+ Value.uval = data.getU64(offset_ptr);
+ break;
+ case DW_FORM_flag_present:
+ Value.uval = 1;
+ break;
+ case DW_FORM_ref_sig8:
+ Value.uval = data.getU64(offset_ptr);
+ break;
default:
return false;
}
@@ -179,6 +217,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
switch (form) {
// Blocks if inlined data that have a length field and the data bytes
// inlined in the .debug_info
+ case DW_FORM_exprloc:
case DW_FORM_block: {
uint64_t size = debug_info_data.getULEB128(offset_ptr);
*offset_ptr += size;
@@ -211,6 +250,10 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
*offset_ptr += cu->getAddressByteSize();
return true;
+ // 0 byte values - implied from the form.
+ case DW_FORM_flag_present:
+ return true;
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
@@ -234,6 +277,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
*offset_ptr += 8;
return true;
@@ -249,6 +293,15 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
indirect = true;
form = debug_info_data.getULEB128(offset_ptr);
break;
+
+ // 4 for DWARF32, 8 for DWARF64.
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ *offset_ptr += 4;
+ else
+ *offset_ptr += 8;
+ return true;
+
default:
return false;
}
@@ -264,22 +317,26 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
switch (Form) {
case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
+ case DW_FORM_flag_present: OS << "true"; break;
case DW_FORM_flag:
case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break;
case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break;
case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break;
+ case DW_FORM_ref_sig8:
case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
case DW_FORM_string:
OS << '"';
OS.write_escaped(getAsCString(NULL));
OS << '"';
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
if (uvalue > 0) {
switch (Form) {
+ case DW_FORM_exprloc:
case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break;
case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break;
case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
@@ -342,6 +399,14 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
case DW_FORM_indirect:
OS << "DW_FORM_indirect";
break;
+
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ OS << format("0x%08x", (uint32_t)uvalue);
+ else
+ OS << format("0x%016" PRIx64, uvalue);
+ break;
+
default:
OS << format("DW_FORM(0x%4.4x)", Form);
break;
@@ -404,6 +469,7 @@ const uint8_t *DWARFFormValue::BlockData() const {
bool DWARFFormValue::isBlockForm(uint16_t form) {
switch (form) {
+ case DW_FORM_exprloc:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.h b/contrib/llvm/lib/DebugInfo/DWARFFormValue.h
index 22ac011..c5b590d 100644
--- a/contrib/llvm/lib/DebugInfo/DWARFFormValue.h
+++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.h
@@ -52,7 +52,7 @@ public:
bool extractValue(DataExtractor data, uint32_t *offset_ptr,
const DWARFCompileUnit *cu);
bool isInlinedCStr() const {
- return Value.data != NULL && Value.data == (uint8_t*)Value.cstr;
+ return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr;
}
const uint8_t *BlockData() const;
uint64_t getReference(const DWARFCompileUnit* cu) const;
OpenPOWER on IntegriCloud