llvm.org GIT mirror llvm / 5eae90d
Add support for fetching inlining context (stack of source code locations) by instruction address from DWARF. Add --inlining flag to llvm-dwarfdump to demonstrate and test this functionality, so that "llvm-dwarfdump --inlining --address=0x..." now works much like "addr2line -i 0x...", provided that the binary has debug info (Clang's -gline-tables-only *is* enough). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163128 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 7 years ago
12 changed file(s) with 361 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
1414 #ifndef LLVM_DEBUGINFO_DICONTEXT_H
1515 #define LLVM_DEBUGINFO_DICONTEXT_H
1616
17 #include "llvm/ADT/SmallVector.h"
1718 #include "llvm/ADT/SmallString.h"
1819 #include "llvm/ADT/StringRef.h"
1920 #include "llvm/Support/DataTypes.h"
5354 }
5455 };
5556
57 /// DIInliningInfo - a format-neutral container for inlined code description.
58 class DIInliningInfo {
59 SmallVector Frames;
60 public:
61 DIInliningInfo() {}
62 DILineInfo getFrame(unsigned Index) const {
63 assert(Index < Frames.size());
64 return Frames[Index];
65 }
66 uint32_t getNumberOfFrames() const {
67 return Frames.size();
68 }
69 void addFrame(const DILineInfo &Frame) {
70 Frames.push_back(Frame);
71 }
72 };
73
5674 /// DILineInfoSpecifier - controls which fields of DILineInfo container
5775 /// should be filled with data.
5876 class DILineInfoSpecifier {
85103
86104 virtual void dump(raw_ostream &OS) = 0;
87105
88 virtual DILineInfo getLineInfoForAddress(uint64_t address,
89 DILineInfoSpecifier specifier = DILineInfoSpecifier()) = 0;
106 virtual DILineInfo getLineInfoForAddress(uint64_t Address,
107 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
108 virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
109 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
90110 };
91111
92112 }
7272 return offset;
7373 }
7474 return 0;
75 }
76
77 bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset,
78 DWARFDebugRangeList &RangeList) const {
79 // Require that compile unit is extracted.
80 assert(DieArray.size() > 0);
81 DataExtractor RangesData(Context.getRangeSection(),
82 Context.isLittleEndian(), AddrSize);
83 return RangeList.extract(RangesData, &RangeListOffset);
7584 }
7685
7786 void DWARFCompileUnit::clear() {
245254 clearDIEs(true);
246255 }
247256
248 const DWARFDebugInfoEntryMinimal*
249 DWARFCompileUnit::getFunctionDIEForAddress(int64_t address) {
257 DWARFDebugInfoEntryMinimal::InlinedChain
258 DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) {
259 // First, find a subprogram that contains the given address (the root
260 // of inlined chain).
250261 extractDIEsIfNeeded(false);
262 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0;
251263 for (size_t i = 0, n = DieArray.size(); i != n; i++) {
252 if (DieArray[i].addressRangeContainsAddress(this, address))
253 return &DieArray[i];
254 }
255 return 0;
256 }
264 if (DieArray[i].isSubprogramDIE() &&
265 DieArray[i].addressRangeContainsAddress(this, Address)) {
266 SubprogramDIE = &DieArray[i];
267 break;
268 }
269 }
270 // Get inlined chain rooted at this subprogram DIE.
271 if (!SubprogramDIE)
272 return DWARFDebugInfoEntryMinimal::InlinedChain();
273 return SubprogramDIE->getInlinedChainForAddress(this, Address);
274 }
1111
1212 #include "DWARFDebugAbbrev.h"
1313 #include "DWARFDebugInfoEntry.h"
14 #include "DWARFDebugRangeList.h"
1415 #include
1516
1617 namespace llvm {
4445 /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
4546 /// hasn't already been done. Returns the number of DIEs parsed at this call.
4647 size_t extractDIEsIfNeeded(bool cu_die_only);
48 /// extractRangeList - extracts the range list referenced by this compile
49 /// unit from .debug_ranges section. Returns true on success.
50 /// Requires that compile unit is already extracted.
51 bool extractRangeList(uint32_t RangeListOffset,
52 DWARFDebugRangeList &RangeList) const;
4753 void clear();
4854 void dump(raw_ostream &OS);
4955 uint32_t getOffset() const { return Offset; }
105111
106112 void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
107113 bool clear_dies_if_already_not_parsed);
108 /// getFunctionDIEForAddress - Returns pointer to parsed subprogram DIE,
109 /// address ranges of which contain the provided address,
110 /// or NULL if there is no such subprogram. The pointer
111 /// is valid until DWARFCompileUnit::clear() or clearDIEs() is called.
112 const DWARFDebugInfoEntryMinimal *getFunctionDIEForAddress(int64_t address);
114
115 /// getInlinedChainForAddress - fetches inlined chain for a given address.
116 /// Returns empty chain if there is no subprogram containing address.
117 DWARFDebugInfoEntryMinimal::InlinedChain getInlinedChainForAddress(
118 uint64_t Address);
113119 };
114120
115121 }
182182 return true;
183183 }
184184
185 bool
186 DWARFContext::getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
187 uint64_t Address,
188 bool NeedsAbsoluteFilePath,
189 std::string &FileName,
190 uint32_t &Line, uint32_t &Column) {
191 // Get the line table for this compile unit.
192 const DWARFDebugLine::LineTable *LineTable = getLineTableForCompileUnit(CU);
193 if (!LineTable)
185 static bool getFileLineInfoForCompileUnit(
186 DWARFCompileUnit *CU, const DWARFDebugLine::LineTable *LineTable,
187 uint64_t Address, bool NeedsAbsoluteFilePath, std::string &FileName,
188 uint32_t &Line, uint32_t &Column) {
189 if (CU == 0 || LineTable == 0)
194190 return false;
195191 // Get the index of row we're looking for in the line table.
196192 uint32_t RowIndex = LineTable->lookupAddress(Address);
216212 uint32_t Line = 0;
217213 uint32_t Column = 0;
218214 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
219 const DWARFDebugInfoEntryMinimal *FunctionDIE =
220 CU->getFunctionDIEForAddress(Address);
221 if (FunctionDIE) {
222 if (const char *Name = FunctionDIE->getSubprogramName(CU))
215 // The address may correspond to instruction in some inlined function,
216 // so we have to build the chain of inlined functions and take the
217 // name of the topmost function in it.
218 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
219 CU->getInlinedChainForAddress(Address);
220 if (InlinedChain.size() > 0) {
221 const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
222 if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
223223 FunctionName = Name;
224224 }
225225 }
226226 if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
227 const DWARFDebugLine::LineTable *LineTable =
228 getLineTableForCompileUnit(CU);
227229 const bool NeedsAbsoluteFilePath =
228230 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
229 getFileLineInfoForCompileUnit(CU, Address, NeedsAbsoluteFilePath,
231 getFileLineInfoForCompileUnit(CU, LineTable, Address,
232 NeedsAbsoluteFilePath,
230233 FileName, Line, Column);
231234 }
232235 return DILineInfo(StringRef(FileName), StringRef(FunctionName),
233236 Line, Column);
234237 }
235238
239 DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
240 DILineInfoSpecifier Specifier) {
241 DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
242 if (!CU)
243 return DIInliningInfo();
244
245 const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
246 CU->getInlinedChainForAddress(Address);
247 if (InlinedChain.size() == 0)
248 return DIInliningInfo();
249
250 DIInliningInfo InliningInfo;
251 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
252 const DWARFDebugLine::LineTable *LineTable = 0;
253 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
254 const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
255 std::string FileName = "";
256 std::string FunctionName = "";
257 uint32_t Line = 0;
258 uint32_t Column = 0;
259 // Get function name if necessary.
260 if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
261 if (const char *Name = FunctionDIE.getSubroutineName(CU))
262 FunctionName = Name;
263 }
264 if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
265 const bool NeedsAbsoluteFilePath =
266 Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
267 if (i == 0) {
268 // For the topmost frame, initialize the line table of this
269 // compile unit and fetch file/line info from it.
270 LineTable = getLineTableForCompileUnit(CU);
271 // For the topmost routine, get file/line info from line table.
272 getFileLineInfoForCompileUnit(CU, LineTable, Address,
273 NeedsAbsoluteFilePath,
274 FileName, Line, Column);
275 } else {
276 // Otherwise, use call file, call line and call column from
277 // previous DIE in inlined chain.
278 getFileNameForCompileUnit(CU, LineTable, CallFile,
279 NeedsAbsoluteFilePath, FileName);
280 Line = CallLine;
281 Column = CallColumn;
282 }
283 // Get call file/line/column of a current DIE.
284 if (i + 1 < n) {
285 FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn);
286 }
287 }
288 DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
289 Line, Column);
290 InliningInfo.addFrame(Frame);
291 }
292 return InliningInfo;
293 }
294
236295 void DWARFContextInMemory::anchor() { }
6565
6666 virtual DILineInfo getLineInfoForAddress(uint64_t Address,
6767 DILineInfoSpecifier Specifier = DILineInfoSpecifier());
68 virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
69 DILineInfoSpecifier Specifier = DILineInfoSpecifier());
6870
6971 bool isLittleEndian() const { return IsLittleEndian; }
7072
8587 /// Return the compile unit which contains instruction with provided
8688 /// address.
8789 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
88
89 /// Fetches filename, line and column number for given address and
90 /// compile unit. Returns true on success.
91 bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
92 uint64_t Address,
93 bool NeedsAbsoluteFilePath,
94 std::string &FileName,
95 uint32_t &Line, uint32_t &Column);
9690 };
9791
9892 /// DWARFContextInMemory is the simplest possible implementation of a
363363 return false;
364364 }
365365
366 bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
367 return getTag() == DW_TAG_subprogram;
368 }
369
370 bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
371 uint32_t Tag = getTag();
372 return Tag == DW_TAG_subprogram ||
373 Tag == DW_TAG_inlined_subroutine;
374 }
375
366376 uint32_t
367377 DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
368378 const uint16_t attr,
445455 return fail_value;
446456 }
447457
458 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU,
459 uint64_t &LowPC, uint64_t &HighPC) const {
460 HighPC = -1ULL;
461 LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL);
462 if (LowPC != -1ULL)
463 HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL);
464 return (HighPC != -1ULL);
465 }
466
448467 void
449 DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
450 DWARFDebugAranges *debug_aranges)
468 DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
469 DWARFDebugAranges *DebugAranges)
451470 const {
452471 if (AbbrevDecl) {
453 uint16_t tag = AbbrevDecl->getTag();
454 if (tag == DW_TAG_subprogram) {
455 uint64_t hi_pc = -1ULL;
456 uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
457 if (lo_pc != -1ULL)
458 hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
459 if (hi_pc != -1ULL)
460 debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
472 if (isSubprogramDIE()) {
473 uint64_t LowPC, HighPC;
474 if (getLowAndHighPC(CU, LowPC, HighPC)) {
475 DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC);
476 }
477 // FIXME: try to append ranges from .debug_ranges section.
461478 }
462479
463480 const DWARFDebugInfoEntryMinimal *child = getFirstChild();
464481 while (child) {
465 child->buildAddressRangeTable(cu, debug_aranges);
482 child->buildAddressRangeTable(CU, DebugAranges);
466483 child = child->getSibling();
467484 }
468485 }
470487
471488 bool
472489 DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
473 const DWARFCompileUnit *cu, const uint64_t address) const {
474 if (!isNULL() && getTag() == DW_TAG_subprogram) {
475 uint64_t hi_pc = -1ULL;
476 uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
477 if (lo_pc != -1ULL)
478 hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
479 if (hi_pc != -1ULL) {
480 return (lo_pc <= address && address < hi_pc);
481 }
490 const DWARFCompileUnit *CU, const uint64_t Address) const {
491 if (isNULL())
492 return false;
493 uint64_t LowPC, HighPC;
494 if (getLowAndHighPC(CU, LowPC, HighPC))
495 return (LowPC <= Address && Address <= HighPC);
496 // Try to get address ranges from .debug_ranges section.
497 uint32_t RangesOffset = getAttributeValueAsReference(CU, DW_AT_ranges, -1U);
498 if (RangesOffset != -1U) {
499 DWARFDebugRangeList RangeList;
500 if (CU->extractRangeList(RangesOffset, RangeList))
501 return RangeList.containsAddress(CU->getBaseAddress(), Address);
482502 }
483503 return false;
484504 }
485505
486506 const char*
487 DWARFDebugInfoEntryMinimal::getSubprogramName(
488 const DWARFCompileUnit *cu) const {
489 if (isNULL() || getTag() != DW_TAG_subprogram)
507 DWARFDebugInfoEntryMinimal::getSubroutineName(
508 const DWARFCompileUnit *CU) const {
509 if (!isSubroutineDIE())
490510 return 0;
491511 // Try to get mangled name if possible.
492512 if (const char *name =
493 getAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, 0))
513 getAttributeValueAsString(CU, DW_AT_MIPS_linkage_name, 0))
494514 return name;
495 if (const char *name = getAttributeValueAsString(cu, DW_AT_linkage_name, 0))
515 if (const char *name = getAttributeValueAsString(CU, DW_AT_linkage_name, 0))
496516 return name;
497 if (const char *name = getAttributeValueAsString(cu, DW_AT_name, 0))
517 if (const char *name = getAttributeValueAsString(CU, DW_AT_name, 0))
498518 return name;
499519 // Try to get name from specification DIE.
500520 uint32_t spec_ref =
501 getAttributeValueAsReference(cu, DW_AT_specification, -1U);
521 getAttributeValueAsReference(CU, DW_AT_specification, -1U);
502522 if (spec_ref != -1U) {
503523 DWARFDebugInfoEntryMinimal spec_die;
504 if (spec_die.extract(cu, &spec_ref)) {
505 if (const char *name = spec_die.getSubprogramName(cu))
524 if (spec_die.extract(CU, &spec_ref)) {
525 if (const char *name = spec_die.getSubroutineName(CU))
506526 return name;
507527 }
508528 }
509529 // Try to get name from abstract origin DIE.
510530 uint32_t abs_origin_ref =
511 getAttributeValueAsReference(cu, DW_AT_abstract_origin, -1U);
531 getAttributeValueAsReference(CU, DW_AT_abstract_origin, -1U);
512532 if (abs_origin_ref != -1U) {
513533 DWARFDebugInfoEntryMinimal abs_origin_die;
514 if (abs_origin_die.extract(cu, &abs_origin_ref)) {
515 if (const char *name = abs_origin_die.getSubprogramName(cu))
534 if (abs_origin_die.extract(CU, &abs_origin_ref)) {
535 if (const char *name = abs_origin_die.getSubroutineName(CU))
516536 return name;
517537 }
518538 }
519539 return 0;
520540 }
541
542 void DWARFDebugInfoEntryMinimal::getCallerFrame(
543 const DWARFCompileUnit *CU, uint32_t &CallFile, uint32_t &CallLine,
544 uint32_t &CallColumn) const {
545 CallFile = getAttributeValueAsUnsigned(CU, DW_AT_call_file, 0);
546 CallLine = getAttributeValueAsUnsigned(CU, DW_AT_call_line, 0);
547 CallColumn = getAttributeValueAsUnsigned(CU, DW_AT_call_column, 0);
548 }
549
550 DWARFDebugInfoEntryMinimal::InlinedChain
551 DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
552 const DWARFCompileUnit *CU, const uint64_t Address) const {
553 DWARFDebugInfoEntryMinimal::InlinedChain InlinedChain;
554 if (isNULL())
555 return InlinedChain;
556 for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
557 // Append current DIE to inlined chain only if it has correct tag
558 // (e.g. it is not a lexical block).
559 if (DIE->isSubroutineDIE()) {
560 InlinedChain.push_back(*DIE);
561 }
562 // Try to get child which also contains provided address.
563 const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
564 while (Child) {
565 if (Child->addressRangeContainsAddress(CU, Address)) {
566 // Assume there is only one such child.
567 break;
568 }
569 Child = Child->getSibling();
570 }
571 DIE = Child;
572 }
573 // Reverse the obtained chain to make the root of inlined chain last.
574 std::reverse(InlinedChain.begin(), InlinedChain.end());
575 return InlinedChain;
576 }
1010 #define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
1111
1212 #include "DWARFAbbreviationDeclaration.h"
13 #include "llvm/ADT/SmallVector.h"
1314 #include "llvm/Support/DataTypes.h"
1415
1516 namespace llvm {
1819 class DWARFCompileUnit;
1920 class DWARFContext;
2021 class DWARFFormValue;
22 class DWARFInlinedSubroutineChain;
2123
2224 /// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
2325 class DWARFDebugInfoEntryMinimal {
5153
5254 uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
5355 bool isNULL() const { return AbbrevDecl == 0; }
56
57 /// Returns true if DIE represents a subprogram (not inlined).
58 bool isSubprogramDIE() const;
59 /// Returns true if DIE represents a subprogram or an inlined
60 /// subroutine.
61 bool isSubroutineDIE() const;
62
5463 uint32_t getOffset() const { return Offset; }
5564 uint32_t getNumAttributes() const {
5665 return !isNULL() ? AbbrevDecl->getNumAttributes() : 0;
125134 const uint16_t attr,
126135 int64_t fail_value) const;
127136
128 void buildAddressRangeTable(const DWARFCompileUnit *cu,
129 DWARFDebugAranges *debug_aranges) const;
137 /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
138 /// Returns true if both attributes are present.
139 bool getLowAndHighPC(const DWARFCompileUnit *CU,
140 uint64_t &LowPC, uint64_t &HighPC) const;
130141
131 bool addressRangeContainsAddress(const DWARFCompileUnit *cu,
132 const uint64_t address) const;
142 void buildAddressRangeTable(const DWARFCompileUnit *CU,
143 DWARFDebugAranges *DebugAranges) const;
133144
134 // If a DIE represents a subprogram, returns its mangled name
135 // (or short name, if mangled is missing). This name may be fetched
136 // from specification or abstract origin for this subprogram.
137 // Returns null if no name is found.
138 const char* getSubprogramName(const DWARFCompileUnit *cu) const;
145 bool addressRangeContainsAddress(const DWARFCompileUnit *CU,
146 const uint64_t Address) const;
147
148 /// If a DIE represents a subprogram (or inlined subroutine),
149 /// returns its mangled name (or short name, if mangled is missing).
150 /// This name may be fetched from specification or abstract origin
151 /// for this subprogram. Returns null if no name is found.
152 const char* getSubroutineName(const DWARFCompileUnit *CU) const;
153
154 /// Retrieves values of DW_AT_call_file, DW_AT_call_line and
155 /// DW_AT_call_column from DIE (or zeroes if they are missing).
156 void getCallerFrame(const DWARFCompileUnit *CU, uint32_t &CallFile,
157 uint32_t &CallLine, uint32_t &CallColumn) const;
158
159 /// InlinedChain - represents a chain of inlined_subroutine
160 /// DIEs, (possibly ending with subprogram DIE), all of which are contained
161 /// in some concrete inlined instance tree. Address range for each DIE
162 /// (except the last DIE) in this chain is contained in address
163 /// range for next DIE in the chain.
164 typedef SmallVector InlinedChain;
165
166 /// Get inlined chain for a given address, rooted at the current DIE.
167 /// Returns empty chain if address is not contained in address range
168 /// of current DIE.
169 InlinedChain getInlinedChainForAddress(const DWARFCompileUnit *CU,
170 const uint64_t Address) const;
139171 };
140172
141173 }
3636 clear();
3737 return false;
3838 }
39 // The end of any given range list is marked by an end of list entry,
40 // which consists of a 0 for the beginning address offset
41 // and a 0 for the ending address offset.
42 if (entry.StartAddress == 0 && entry.EndAddress == 0)
39 if (entry.isEndOfListEntry())
4340 break;
4441 Entries.push_back(entry);
4542 }
5653 }
5754 OS << format("%08x \n", Offset);
5855 }
56
57 bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress,
58 uint64_t Address) const {
59 for (int i = 0, n = Entries.size(); i != n; ++i) {
60 if (Entries[i].isBaseAddressSelectionEntry(AddressSize))
61 BaseAddress = Entries[i].EndAddress;
62 else if (Entries[i].containsAddress(BaseAddress, Address))
63 return true;
64 }
65 return false;
66 }
3030 // address past the end of the address range. The ending address must
3131 // be greater than or equal to the beginning address.
3232 uint64_t EndAddress;
33 // The end of any given range list is marked by an end of list entry,
34 // which consists of a 0 for the beginning address offset
35 // and a 0 for the ending address offset.
36 bool isEndOfListEntry() const {
37 return (StartAddress == 0) && (EndAddress == 0);
38 }
39 // A base address selection entry consists of:
40 // 1. The value of the largest representable address offset
41 // (for example, 0xffffffff when the size of an address is 32 bits).
42 // 2. An address, which defines the appropriate base address for
43 // use in interpreting the beginning and ending address offsets of
44 // subsequent entries of the location list.
45 bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
46 assert(AddressSize == 4 || AddressSize == 8);
47 if (AddressSize == 4)
48 return StartAddress == -1U;
49 else
50 return StartAddress == -1ULL;
51 }
52 bool containsAddress(uint64_t BaseAddress, uint64_t Address) const {
53 return (BaseAddress + StartAddress <= Address) &&
54 (Address < BaseAddress + EndAddress);
55 }
3356 };
3457
3558 private:
4366 void clear();
4467 void dump(raw_ostream &OS) const;
4568 bool extract(DataExtractor data, uint32_t *offset_ptr);
69 /// containsAddress - Returns true if range list contains the given
70 /// address. Has to be passed base address of the compile unit that
71 /// references this range list.
72 bool containsAddress(uint64_t BaseAddress, uint64_t Address) const;
4673 };
4774
4875 } // namespace llvm
0 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-x86-64 --address=0x613 \
1 RUN: --inlining --functions | FileCheck %s -check-prefix DEEP_STACK
2 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-x86-64 --address=0x6de \
3 RUN: --inlining | FileCheck %s -check-prefix SHORTER_STACK
4 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-x86-64 --address=0x685 \
5 RUN: --inlining | FileCheck %s -check-prefix SHORT_STACK
6 RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-x86-64 --address=0x640 \
7 RUN: --functions | FileCheck %s -check-prefix INL_FUNC_NAME
8
9 DEEP_STACK: inlined_h
10 DEEP_STACK-NEXT: header.h:2:21
11 DEEP_STACK-NEXT: inlined_g
12 DEEP_STACK-NEXT: header.h:7
13 DEEP_STACK-NEXT: inlined_f
14 DEEP_STACK-NEXT: main.cc:3
15 DEEP_STACK-NEXT: main
16 DEEP_STACK-NEXT: main.cc:8
17
18 SHORTER_STACK: header.h:7:20
19 SHORTER_STACK-NEXT: main.cc:3
20 SHORTER_STACK-NEXT: main.cc:8
21
22 SHORT_STACK: main.cc:3:20
23 SHORT_STACK-NEXT: main.cc:8
24
25 INL_FUNC_NAME: inlined_g
26 INL_FUNC_NAME-NEXT: header.h:7:20
27
4242 PrintFunctions("functions", cl::init(false),
4343 cl::desc("Print function names as well as line information "
4444 "for a given address"));
45
46 static cl::opt
47 PrintInlining("inlining", cl::init(false),
48 cl::desc("Print all inlined frames for a given address"));
49
50 static void PrintDILineInfo(DILineInfo dli) {
51 if (PrintFunctions)
52 outs() << (dli.getFunctionName() ? dli.getFunctionName() : "")
53 << "\n";
54 outs() << (dli.getFileName() ? dli.getFileName() : "") << ':'
55 << dli.getLine() << ':' << dli.getColumn() << '\n';
56 }
4557
4658 static void DumpInput(const StringRef &Filename) {
4759 OwningPtr Buff;
100112 dictx->dump(outs());
101113 } else {
102114 // Print line info for the specified address.
103 int spec_flags = DILineInfoSpecifier::FileLineInfo |
104 DILineInfoSpecifier::AbsoluteFilePath;
115 int SpecFlags = DILineInfoSpecifier::FileLineInfo |
116 DILineInfoSpecifier::AbsoluteFilePath;
105117 if (PrintFunctions)
106 spec_flags |= DILineInfoSpecifier::FunctionName;
107 DILineInfo dli = dictx->getLineInfoForAddress(Address, spec_flags);
108 if (PrintFunctions)
109 outs() << (dli.getFunctionName() ? dli.getFunctionName() : "")
110 << "\n";
111 outs() << (dli.getFileName() ? dli.getFileName() : "") << ':'
112 << dli.getLine() << ':' << dli.getColumn() << '\n';
118 SpecFlags |= DILineInfoSpecifier::FunctionName;
119 if (PrintInlining) {
120 DIInliningInfo InliningInfo = dictx->getInliningInfoForAddress(
121 Address, SpecFlags);
122 uint32_t n = InliningInfo.getNumberOfFrames();
123 if (n == 0) {
124 // Print one empty debug line info in any case.
125 PrintDILineInfo(DILineInfo());
126 } else {
127 for (uint32_t i = 0; i < n; i++) {
128 DILineInfo dli = InliningInfo.getFrame(i);
129 PrintDILineInfo(dli);
130 }
131 }
132 } else {
133 DILineInfo dli = dictx->getLineInfoForAddress(Address, SpecFlags);
134 PrintDILineInfo(dli);
135 }
113136 }
114137 }
115138