summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2013-01-26 00:28:05 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2013-01-26 00:28:05 +0000
commite27a787760ea7c2899da3287002fe8ba316df0d0 (patch)
tree32795882c6c610b3f5157afc05c4b7456f17bb3b
parent32a57958226e369f964a034da2ce7083a1a34297 (diff)
downloadllvm-e27a787760ea7c2899da3287002fe8ba316df0d0.tar.gz
llvm-e27a787760ea7c2899da3287002fe8ba316df0d0.tar.bz2
llvm-e27a787760ea7c2899da3287002fe8ba316df0d0.tar.xz
Add DIContext::getLineInfoForAddressRange() function and test. This function allows a caller to obtain a table of line information for a function using the function's address and size.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173537 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/DebugInfo/DIContext.h4
-rw-r--r--lib/DebugInfo/DWARFContext.cpp58
-rw-r--r--lib/DebugInfo/DWARFContext.h2
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp75
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h4
-rw-r--r--test/DebugInfo/Inputs/test-parameters.obin0 -> 5792 bytes
-rw-r--r--test/DebugInfo/debuglineinfo.test46
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp10
8 files changed, 191 insertions, 8 deletions
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 5cb1a17432..a2c3f03ee8 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -58,6 +58,8 @@ public:
}
};
+typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable;
+
/// DIInliningInfo - a format-neutral container for inlined code description.
class DIInliningInfo {
SmallVector<DILineInfo, 4> Frames;
@@ -126,6 +128,8 @@ public:
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
+ virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
+ uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
};
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 66d299bad2..768427fab0 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -325,6 +325,64 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
Line, Column);
}
+DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
+ uint64_t Size,
+ DILineInfoSpecifier Specifier) {
+ DILineInfoTable Lines;
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return Lines;
+
+ std::string FunctionName = "<invalid>";
+ if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
+ // The address may correspond to instruction in some inlined function,
+ // so we have to build the chain of inlined functions and take the
+ // name of the topmost function in it.
+ const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ FunctionName = Name;
+ }
+ }
+
+ StringRef FuncNameRef = StringRef(FunctionName);
+
+ // If the Specifier says we don't need FileLineInfo, just
+ // return the top-most function at the starting address.
+ if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
+ Lines.push_back(std::make_pair(Address,
+ DILineInfo(StringRef("<invalid>"),
+ FuncNameRef, 0, 0)));
+ return Lines;
+ }
+
+ const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
+ const bool NeedsAbsoluteFilePath =
+ Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
+
+ // Get the index of row we're looking for in the line table.
+ std::vector<uint32_t> RowVector;
+ if (!LineTable->lookupAddressRange(Address, Size, RowVector))
+ return Lines;
+
+ uint32_t NumRows = RowVector.size();
+ for (uint32_t i = 0; i < NumRows; ++i) {
+ uint32_t RowIndex = RowVector[i];
+ // Take file number and line/column from the row.
+ const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
+ std::string FileName = "<invalid>";
+ getFileNameForCompileUnit(CU, LineTable, Row.File,
+ NeedsAbsoluteFilePath, FileName);
+ Lines.push_back(std::make_pair(Row.Address,
+ DILineInfo(StringRef(FileName),
+ FuncNameRef, Row.Line, Row.Column)));
+ }
+
+ return Lines;
+}
+
DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index d6314b87c3..9ff094bd48 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -90,6 +90,8 @@ public:
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier());
+ virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
+ uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier());
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier());
diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index 16ef896ca7..7b32d4fe9e 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/lib/DebugInfo/DWARFDebugLine.cpp
@@ -525,6 +525,81 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
}
bool
+DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
+ uint64_t size,
+ std::vector<uint32_t>& result) const {
+ if (Sequences.empty())
+ return false;
+ uint64_t end_addr = address + size;
+ // First, find an instruction sequence containing the given address.
+ DWARFDebugLine::Sequence sequence;
+ sequence.LowPC = address;
+ SequenceIter first_seq = Sequences.begin();
+ SequenceIter last_seq = Sequences.end();
+ SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
+ DWARFDebugLine::Sequence::orderByLowPC);
+ if (seq_pos == last_seq || seq_pos->LowPC != address) {
+ if (seq_pos == first_seq)
+ return false;
+ seq_pos--;
+ }
+ if (!seq_pos->containsPC(address))
+ return false;
+
+ SequenceIter start_pos = seq_pos;
+
+ // Add the rows from the first sequence to the vector, starting with the
+ // index we just calculated
+
+ while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
+ DWARFDebugLine::Sequence cur_seq = *seq_pos;
+ uint32_t first_row_index;
+ uint32_t last_row_index;
+ if (seq_pos == start_pos) {
+ // For the first sequence, we need to find which row in the sequence is the
+ // first in our range. Rows are stored in a vector, so we may use
+ // arithmetical operations with iterators.
+ DWARFDebugLine::Row row;
+ row.Address = address;
+ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
+ RowIter row_pos = std::upper_bound(first_row, last_row, row,
+ DWARFDebugLine::Row::orderByAddress);
+ // The 'row_pos' iterator references the first row that is greater than
+ // our start address. Unless that's the first row, we want to start at
+ // the row before that.
+ first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row);
+ if (row_pos != first_row)
+ --first_row_index;
+ } else
+ first_row_index = cur_seq.FirstRowIndex;
+
+ // For the last sequence in our range, we need to figure out the last row in
+ // range. For all other sequences we can go to the end of the sequence.
+ if (cur_seq.HighPC > end_addr) {
+ DWARFDebugLine::Row row;
+ row.Address = end_addr;
+ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
+ RowIter row_pos = std::upper_bound(first_row, last_row, row,
+ DWARFDebugLine::Row::orderByAddress);
+ // The 'row_pos' iterator references the first row that is greater than
+ // our end address. The row before that is the last row we want.
+ last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1;
+ } else
+ // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex
+ // isn't a valid index within the current sequence. It's that plus one.
+ last_row_index = cur_seq.LastRowIndex - 1;
+
+ for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
+ result.push_back(i);
+ }
+
+ ++seq_pos;
+ }
+}
+
+bool
DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
bool NeedsAbsoluteFilePath,
std::string &Result) const {
diff --git a/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
index dbaf91d321..2990756bd7 100644
--- a/lib/DebugInfo/DWARFDebugLine.h
+++ b/lib/DebugInfo/DWARFDebugLine.h
@@ -178,6 +178,10 @@ public:
// or -1 if there is no such row.
uint32_t lookupAddress(uint64_t address) const;
+ bool lookupAddressRange(uint64_t address,
+ uint64_t size,
+ std::vector<uint32_t>& result) const;
+
// Extracts filename by its index in filename table in prologue.
// Returns true on success.
bool getFileNameByIndex(uint64_t FileIndex,
diff --git a/test/DebugInfo/Inputs/test-parameters.o b/test/DebugInfo/Inputs/test-parameters.o
new file mode 100644
index 0000000000..7f4b6702df
--- /dev/null
+++ b/test/DebugInfo/Inputs/test-parameters.o
Binary files differ
diff --git a/test/DebugInfo/debuglineinfo.test b/test/DebugInfo/debuglineinfo.test
index 78de390a8b..14d2f82b04 100644
--- a/test/DebugInfo/debuglineinfo.test
+++ b/test/DebugInfo/debuglineinfo.test
@@ -1,15 +1,49 @@
RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
RUN: | FileCheck %s -check-prefix TEST_INLINE
+RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \
+RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
; This test verifies that relocations are correctly applied to the
-; .debug_line section. If relocations are not applied the first two
-; functions will be reported as both starting at address zero in the
-; line number table.
+; .debug_line section and exercises DIContext::getLineInfoForAddressRange().
+; If relocations are not applied the first two functions will be reported as
+; both starting at address zero in the; line number table.
TEST_INLINE: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
-TEST_INLINE-NEXT: Line info:test-inline.cpp, line:33
+TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:33
+TEST_INLINE-NEXT: Line info @ 35: test-inline.cpp, line:34
+TEST_INLINE-NEXT: Line info @ 165: test-inline.cpp, line:35
TEST_INLINE-NEXT: Function: _Z3foov, Size = 3
-TEST_INLINE-NEXT: Line info:test-inline.cpp, line:28
+TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:28
+TEST_INLINE-NEXT: Line info @ 2: test-inline.cpp, line:29
+TEST_INLINE-NEXT: Line info @ 3: test-inline.cpp, line:29
TEST_INLINE-NEXT: Function: main, Size = 146
-TEST_INLINE-NEXT: Line info:test-inline.cpp, line:39
+TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:39
+TEST_INLINE-NEXT: Line info @ 21: test-inline.cpp, line:41
+TEST_INLINE-NEXT: Line info @ 39: test-inline.cpp, line:42
+TEST_INLINE-NEXT: Line info @ 60: test-inline.cpp, line:44
+TEST_INLINE-NEXT: Line info @ 80: test-inline.cpp, line:48
+TEST_INLINE-NEXT: Line info @ 90: test-inline.cpp, line:45
+TEST_INLINE-NEXT: Line info @ 95: test-inline.cpp, line:46
+TEST_INLINE-NEXT: Line info @ 114: test-inline.cpp, line:48
+TEST_INLINE-NEXT: Line info @ 141: test-inline.cpp, line:49
+TEST_INLINE-NEXT: Line info @ 146: test-inline.cpp, line:49
+; This test checks the case where all code is in a single section.
+TEST_PARAMETERS: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
+TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:33
+TEST_PARAMETERS-NEXT: Line info @ 35: test-parameters.cpp, line:34
+TEST_PARAMETERS-NEXT: Line info @ 165: test-parameters.cpp, line:35
+TEST_PARAMETERS-NEXT: Function: _Z3foov, Size = 3
+TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:28
+TEST_PARAMETERS-NEXT: Line info @ 2: test-parameters.cpp, line:29
+TEST_PARAMETERS-NEXT: Function: main, Size = 146
+TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:39
+TEST_PARAMETERS-NEXT: Line info @ 21: test-parameters.cpp, line:41
+TEST_PARAMETERS-NEXT: Line info @ 39: test-parameters.cpp, line:42
+TEST_PARAMETERS-NEXT: Line info @ 60: test-parameters.cpp, line:44
+TEST_PARAMETERS-NEXT: Line info @ 80: test-parameters.cpp, line:48
+TEST_PARAMETERS-NEXT: Line info @ 90: test-parameters.cpp, line:45
+TEST_PARAMETERS-NEXT: Line info @ 95: test-parameters.cpp, line:46
+TEST_PARAMETERS-NEXT: Line info @ 114: test-parameters.cpp, line:48
+TEST_PARAMETERS-NEXT: Line info @ 141: test-parameters.cpp, line:49
+TEST_PARAMETERS-NEXT: Line info @ 146: test-parameters.cpp, line:49
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 8b71a4f364..4d8d345894 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -163,8 +163,14 @@ static int printLineInfoForInput() {
outs() << "Function: " << Name << ", Size = " << Size << "\n";
- DILineInfo Result = Context->getLineInfoForAddress(Addr);
- outs() << " Line info:" << Result.getFileName() << ", line:" << Result.getLine() << "\n";
+ DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
+ DILineInfoTable::iterator Begin = Lines.begin();
+ DILineInfoTable::iterator End = Lines.end();
+ for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
+ outs() << " Line info @ " << It->first - Addr << ": "
+ << It->second.getFileName()
+ << ", line:" << It->second.getLine() << "\n";
+ }
}
}
}