llvm.org GIT mirror llvm / e27a787
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 Andrew Kaylor 7 years ago
8 changed file(s) with 191 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
5656 return !(*this == RHS);
5757 }
5858 };
59
60 typedef SmallVector, 16> DILineInfoTable;
5961
6062 /// DIInliningInfo - a format-neutral container for inlined code description.
6163 class DIInliningInfo {
125127
126128 virtual DILineInfo getLineInfoForAddress(uint64_t Address,
127129 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
130 virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
131 uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
128132 virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
129133 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
130134 };
322322 }
323323 return DILineInfo(StringRef(FileName), StringRef(FunctionName),
324324 Line, Column);
325 }
326
327 DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
328 uint64_t Size,
329 DILineInfoSpecifier Specifier) {
330 DILineInfoTable Lines;
331 DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
332 if (!CU)
333 return Lines;
334
335 std::string FunctionName = "";
336 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
337 // The address may correspond to instruction in some inlined function,
338 // so we have to build the chain of inlined functions and take the
339 // name of the topmost function in it.
340 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
341 CU->getInlinedChainForAddress(Address);
342 if (InlinedChain.size() > 0) {
343 const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
344 if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
345 FunctionName = Name;
346 }
347 }
348
349 StringRef FuncNameRef = StringRef(FunctionName);
350
351 // If the Specifier says we don't need FileLineInfo, just
352 // return the top-most function at the starting address.
353 if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
354 Lines.push_back(std::make_pair(Address,
355 DILineInfo(StringRef(""),
356 FuncNameRef, 0, 0)));
357 return Lines;
358 }
359
360 const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
361 const bool NeedsAbsoluteFilePath =
362 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
363
364 // Get the index of row we're looking for in the line table.
365 std::vector RowVector;
366 if (!LineTable->lookupAddressRange(Address, Size, RowVector))
367 return Lines;
368
369 uint32_t NumRows = RowVector.size();
370 for (uint32_t i = 0; i < NumRows; ++i) {
371 uint32_t RowIndex = RowVector[i];
372 // Take file number and line/column from the row.
373 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
374 std::string FileName = "";
375 getFileNameForCompileUnit(CU, LineTable, Row.File,
376 NeedsAbsoluteFilePath, FileName);
377 Lines.push_back(std::make_pair(Row.Address,
378 DILineInfo(StringRef(FileName),
379 FuncNameRef, Row.Line, Row.Column)));
380 }
381
382 return Lines;
325383 }
326384
327385 DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
8989
9090 virtual DILineInfo getLineInfoForAddress(uint64_t Address,
9191 DILineInfoSpecifier Specifier = DILineInfoSpecifier());
92 virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
93 uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier());
9294 virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
9395 DILineInfoSpecifier Specifier = DILineInfoSpecifier());
9496
524524 }
525525
526526 bool
527 DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
528 uint64_t size,
529 std::vector& result) const {
530 if (Sequences.empty())
531 return false;
532 uint64_t end_addr = address + size;
533 // First, find an instruction sequence containing the given address.
534 DWARFDebugLine::Sequence sequence;
535 sequence.LowPC = address;
536 SequenceIter first_seq = Sequences.begin();
537 SequenceIter last_seq = Sequences.end();
538 SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
539 DWARFDebugLine::Sequence::orderByLowPC);
540 if (seq_pos == last_seq || seq_pos->LowPC != address) {
541 if (seq_pos == first_seq)
542 return false;
543 seq_pos--;
544 }
545 if (!seq_pos->containsPC(address))
546 return false;
547
548 SequenceIter start_pos = seq_pos;
549
550 // Add the rows from the first sequence to the vector, starting with the
551 // index we just calculated
552
553 while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
554 DWARFDebugLine::Sequence cur_seq = *seq_pos;
555 uint32_t first_row_index;
556 uint32_t last_row_index;
557 if (seq_pos == start_pos) {
558 // For the first sequence, we need to find which row in the sequence is the
559 // first in our range. Rows are stored in a vector, so we may use
560 // arithmetical operations with iterators.
561 DWARFDebugLine::Row row;
562 row.Address = address;
563 RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
564 RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
565 RowIter row_pos = std::upper_bound(first_row, last_row, row,
566 DWARFDebugLine::Row::orderByAddress);
567 // The 'row_pos' iterator references the first row that is greater than
568 // our start address. Unless that's the first row, we want to start at
569 // the row before that.
570 first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row);
571 if (row_pos != first_row)
572 --first_row_index;
573 } else
574 first_row_index = cur_seq.FirstRowIndex;
575
576 // For the last sequence in our range, we need to figure out the last row in
577 // range. For all other sequences we can go to the end of the sequence.
578 if (cur_seq.HighPC > end_addr) {
579 DWARFDebugLine::Row row;
580 row.Address = end_addr;
581 RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
582 RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
583 RowIter row_pos = std::upper_bound(first_row, last_row, row,
584 DWARFDebugLine::Row::orderByAddress);
585 // The 'row_pos' iterator references the first row that is greater than
586 // our end address. The row before that is the last row we want.
587 last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1;
588 } else
589 // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex
590 // isn't a valid index within the current sequence. It's that plus one.
591 last_row_index = cur_seq.LastRowIndex - 1;
592
593 for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
594 result.push_back(i);
595 }
596
597 ++seq_pos;
598 }
599 }
600
601 bool
527602 DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
528603 bool NeedsAbsoluteFilePath,
529604 std::string &Result) const {
177177 // or -1 if there is no such row.
178178 uint32_t lookupAddress(uint64_t address) const;
179179
180 bool lookupAddressRange(uint64_t address,
181 uint64_t size,
182 std::vector& result) const;
183
180184 // Extracts filename by its index in filename table in prologue.
181185 // Returns true on success.
182186 bool getFileNameByIndex(uint64_t FileIndex,
0 RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
11 RUN: | FileCheck %s -check-prefix TEST_INLINE
2 RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \
3 RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
24
35 ; This test verifies that relocations are correctly applied to the
4 ; .debug_line section. If relocations are not applied the first two
5 ; functions will be reported as both starting at address zero in the
6 ; line number table.
6 ; .debug_line section and exercises DIContext::getLineInfoForAddressRange().
7 ; If relocations are not applied the first two functions will be reported as
8 ; both starting at address zero in the; line number table.
79 TEST_INLINE: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
8 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:33
10 TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:33
11 TEST_INLINE-NEXT: Line info @ 35: test-inline.cpp, line:34
12 TEST_INLINE-NEXT: Line info @ 165: test-inline.cpp, line:35
913 TEST_INLINE-NEXT: Function: _Z3foov, Size = 3
10 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:28
14 TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:28
15 TEST_INLINE-NEXT: Line info @ 2: test-inline.cpp, line:29
16 TEST_INLINE-NEXT: Line info @ 3: test-inline.cpp, line:29
1117 TEST_INLINE-NEXT: Function: main, Size = 146
12 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:39
18 TEST_INLINE-NEXT: Line info @ 0: test-inline.cpp, line:39
19 TEST_INLINE-NEXT: Line info @ 21: test-inline.cpp, line:41
20 TEST_INLINE-NEXT: Line info @ 39: test-inline.cpp, line:42
21 TEST_INLINE-NEXT: Line info @ 60: test-inline.cpp, line:44
22 TEST_INLINE-NEXT: Line info @ 80: test-inline.cpp, line:48
23 TEST_INLINE-NEXT: Line info @ 90: test-inline.cpp, line:45
24 TEST_INLINE-NEXT: Line info @ 95: test-inline.cpp, line:46
25 TEST_INLINE-NEXT: Line info @ 114: test-inline.cpp, line:48
26 TEST_INLINE-NEXT: Line info @ 141: test-inline.cpp, line:49
27 TEST_INLINE-NEXT: Line info @ 146: test-inline.cpp, line:49
1328
29 ; This test checks the case where all code is in a single section.
30 TEST_PARAMETERS: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
31 TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:33
32 TEST_PARAMETERS-NEXT: Line info @ 35: test-parameters.cpp, line:34
33 TEST_PARAMETERS-NEXT: Line info @ 165: test-parameters.cpp, line:35
34 TEST_PARAMETERS-NEXT: Function: _Z3foov, Size = 3
35 TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:28
36 TEST_PARAMETERS-NEXT: Line info @ 2: test-parameters.cpp, line:29
37 TEST_PARAMETERS-NEXT: Function: main, Size = 146
38 TEST_PARAMETERS-NEXT: Line info @ 0: test-parameters.cpp, line:39
39 TEST_PARAMETERS-NEXT: Line info @ 21: test-parameters.cpp, line:41
40 TEST_PARAMETERS-NEXT: Line info @ 39: test-parameters.cpp, line:42
41 TEST_PARAMETERS-NEXT: Line info @ 60: test-parameters.cpp, line:44
42 TEST_PARAMETERS-NEXT: Line info @ 80: test-parameters.cpp, line:48
43 TEST_PARAMETERS-NEXT: Line info @ 90: test-parameters.cpp, line:45
44 TEST_PARAMETERS-NEXT: Line info @ 95: test-parameters.cpp, line:46
45 TEST_PARAMETERS-NEXT: Line info @ 114: test-parameters.cpp, line:48
46 TEST_PARAMETERS-NEXT: Line info @ 141: test-parameters.cpp, line:49
47 TEST_PARAMETERS-NEXT: Line info @ 146: test-parameters.cpp, line:49
1448
162162
163163 outs() << "Function: " << Name << ", Size = " << Size << "\n";
164164
165 DILineInfo Result = Context->getLineInfoForAddress(Addr);
166 outs() << " Line info:" << Result.getFileName() << ", line:" << Result.getLine() << "\n";
165 DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
166 DILineInfoTable::iterator Begin = Lines.begin();
167 DILineInfoTable::iterator End = Lines.end();
168 for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
169 outs() << " Line info @ " << It->first - Addr << ": "
170 << It->second.getFileName()
171 << ", line:" << It->second.getLine() << "\n";
172 }
167173 }
168174 }
169175 }