mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
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
This commit is contained in:
parent
32a5795822
commit
e27a787760
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
||||
|
@ -524,6 +524,81 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
|
||||
return index;
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
|
||||
uint64_t size,
|
||||
std::vector<uint32_t>& result) const {
|
||||
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,
|
||||
|
@ -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,
|
||||
|
BIN
test/DebugInfo/Inputs/test-parameters.o
Normal file
BIN
test/DebugInfo/Inputs/test-parameters.o
Normal file
Binary file not shown.
@ -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
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user