aboutsummaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2012-09-13 19:10:35 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-09-13 19:10:35 -0700
commit8f1c32e4f21c4e297f5690acf958a842384ba802 (patch)
tree52800183ec2d22164b8f396842142c3a8aab912a /lib/DebugInfo
parent828ded66831c0caaeecd2291a6bfb084f373d0e4 (diff)
parent1c4ad5ef4fab105f0c8af7edd026e00502fb6279 (diff)
downloadexternal_llvm-8f1c32e4f21c4e297f5690acf958a842384ba802.zip
external_llvm-8f1c32e4f21c4e297f5690acf958a842384ba802.tar.gz
external_llvm-8f1c32e4f21c4e297f5690acf958a842384ba802.tar.bz2
am 1c4ad5ef: Merge branch \'upstream\' into merge-2012_09_10
* commit '1c4ad5ef4fab105f0c8af7edd026e00502fb6279': (446 commits) Revert r163556. Missed updates to tablegen files. Update function names to conform to guidelines. No functional change intended. test/CodeGen/X86/ms-inline-asm.ll: Relax for non-darwin x86 targets. '##InlineAsm' could not be seen in other hosts. [ms-inline asm] Properly emit the asm directives when the AsmPrinterVariant and InlineAsmVariant don't match. Update test case for Release builds. Remove redundant semicolons which are null statements. Disable stack coloring because it makes dragonegg fail bootstrapping. [ms-inline asm] Pass the correct AsmVariant to the PrintAsmOperand() function and update the printOperand() function accordingly. [ms-inline asm] Add support for .att_syntax directive. Enable stack coloring. Don't attempt to use flags from predicated instructions. [Object] Extract Elf_Ehdr. Patch by Hemant Kulkarni! Stack Coloring: Handle the case where END markers come before BEGIN markers properly. Enhance PR11334 fix to support extload from v2f32/v4f32 Add "blocked" heuristic to the Hexagon MI scheduler. Fold multiply by 0 or 1 when in UnsafeFPMath mode in SelectionDAG::getNode(). whitespace Add boolean simplification support from CMOV Fix an assertion failure when optimising a shufflevector incorrectly into concat_vectors, and a followup bug with SelectionDAG::getNode() creating nodes with invalid types. Minor cleanup. No functional change. ...
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/DIContext.cpp6
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.cpp48
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h16
-rw-r--r--lib/DebugInfo/DWARFContext.cpp203
-rw-r--r--lib/DebugInfo/DWARFContext.h27
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.cpp1
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp152
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h54
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp27
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h8
-rw-r--r--lib/DebugInfo/DWARFDebugRangeList.cpp67
-rw-r--r--lib/DebugInfo/DWARFDebugRangeList.h78
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp51
-rw-r--r--lib/DebugInfo/DWARFFormValue.h2
15 files changed, 608 insertions, 133 deletions
diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt
index 441f1e8..1e9e509 100644
--- a/lib/DebugInfo/CMakeLists.txt
+++ b/lib/DebugInfo/CMakeLists.txt
@@ -8,5 +8,6 @@ add_llvm_library(LLVMDebugInfo
DWARFDebugAranges.cpp
DWARFDebugInfoEntry.cpp
DWARFDebugLine.cpp
+ DWARFDebugRangeList.cpp
DWARFFormValue.cpp
)
diff --git a/lib/DebugInfo/DIContext.cpp b/lib/DebugInfo/DIContext.cpp
index e2fd55f..ead57f9 100644
--- a/lib/DebugInfo/DIContext.cpp
+++ b/lib/DebugInfo/DIContext.cpp
@@ -18,7 +18,9 @@ DIContext *DIContext::getDWARFContext(bool isLittleEndian,
StringRef abbrevSection,
StringRef aRangeSection,
StringRef lineSection,
- StringRef stringSection) {
+ StringRef stringSection,
+ StringRef rangeSection) {
return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
- aRangeSection, lineSection, stringSection);
+ aRangeSection, lineSection, stringSection,
+ rangeSection);
}
diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp
index b27d57b..bdd65b7 100644
--- a/lib/DebugInfo/DWARFCompileUnit.cpp
+++ b/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/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h
index b34a596..03e2862 100644
--- a/lib/DebugInfo/DWARFCompileUnit.h
+++ b/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/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 797662b..241f55e 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -32,15 +32,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 +56,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() {
@@ -131,75 +145,152 @@ 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 DWARFDebugLine::LineTable *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 DWARFDebugLine::LineTable *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 DWARFDebugLine::LineTable *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 DWARFDebugLine::LineTable *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/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index e55a27e..7633997 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/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"
@@ -53,9 +54,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,8 +64,10 @@ 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; }
@@ -76,12 +76,19 @@ public:
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 +100,22 @@ 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)
+ StringRef stringSection,
+ StringRef rangeSection)
: DWARFContext(isLittleEndian),
InfoSection(infoSection),
AbbrevSection(abbrevSection),
ARangeSection(aRangeSection),
LineSection(lineSection),
- StringSection(stringSection)
+ StringSection(stringSection),
+ RangeSection(rangeSection)
{}
virtual StringRef getInfoSection() { return InfoSection; }
@@ -113,6 +123,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/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp
index ef470e5..f9a34c9 100644
--- a/lib/DebugInfo/DWARFDebugAranges.cpp
+++ b/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/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index 429a36c..1bfd126 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/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,
@@ -418,24 +456,31 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
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 +488,90 @@ 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/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h
index d5d86b9..9c1b2be 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/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/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index d99575d..267364a 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/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/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
index 6382b45..586dd7e 100644
--- a/lib/DebugInfo/DWARFDebugLine.h
+++ b/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/lib/DebugInfo/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARFDebugRangeList.cpp
new file mode 100644
index 0000000..1806bee
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFDebugRangeList.h b/lib/DebugInfo/DWARFDebugRangeList.h
new file mode 100644
index 0000000..4e34a91
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index ee2a3ab..c9ecbbb 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -41,6 +41,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 +71,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 *
@@ -93,6 +101,7 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
case DW_FORM_ref_addr:
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;
@@ -141,12 +150,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 +200,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 +233,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 +260,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 +276,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 +300,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 +382,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 +452,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/lib/DebugInfo/DWARFFormValue.h b/lib/DebugInfo/DWARFFormValue.h
index 22ac011..c5b590d 100644
--- a/lib/DebugInfo/DWARFFormValue.h
+++ b/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;