llvm.org GIT mirror llvm / 4ee57e2
Get function start line number from DWARF info DWARF info contains info about the line number at which a function starts (DW_AT_decl_line). This patch creates a function to look up the start line number for a function, and returns it in DILineInfo when looking up debug info for a particular address. Patch by Simon Que! Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D27962 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294231 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 3 years ago
6 changed file(s) with 53 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
3333 std::string FunctionName;
3434 uint32_t Line;
3535 uint32_t Column;
36 uint32_t StartLine;
3637
3738 // DWARF-specific.
3839 uint32_t Discriminator;
3940
4041 DILineInfo()
4142 : FileName(""), FunctionName(""), Line(0), Column(0),
42 Discriminator(0) {}
43 StartLine(0), Discriminator(0) {}
4344
4445 bool operator==(const DILineInfo &RHS) const {
4546 return Line == RHS.Line && Column == RHS.Column &&
46 FileName == RHS.FileName && FunctionName == RHS.FunctionName;
47 FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
48 StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
4749 }
4850 bool operator!=(const DILineInfo &RHS) const {
4951 return !(*this == RHS);
5052 }
5153 bool operator<(const DILineInfo &RHS) const {
52 return std::tie(FileName, FunctionName, Line, Column) <
53 std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column);
54 return std::tie(FileName, FunctionName, Line, Column, StartLine,
55 Discriminator) <
56 std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
57 RHS.StartLine, RHS.Discriminator);
5458 }
5559 };
5660
232232 /// references if necessary. Returns null if no name is found.
233233 const char *getName(DINameKind Kind) const;
234234
235 /// Returns the declaration line (start line) for a DIE, assuming it specifies
236 /// a subprogram. This may be fetched from specification or abstract origin
237 /// for this subprogram by resolving DW_AT_sepcification or
238 /// DW_AT_abstract_origin references if necessary.
239 uint64_t getDeclLine() const;
240
235241 /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
236242 /// from DIE (or zeroes if they are missing). This function looks for
237243 /// DW_AT_call attributes in this DIE only, it will not resolve the attribute
438438 return getCompileUnitForOffset(CUOffset);
439439 }
440440
441 static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
442 FunctionNameKind Kind,
443 std::string &FunctionName) {
444 if (Kind == FunctionNameKind::None)
445 return false;
441 static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
442 uint64_t Address,
443 FunctionNameKind Kind,
444 std::string &FunctionName,
445 uint32_t &StartLine) {
446446 // The address may correspond to instruction in some inlined function,
447447 // so we have to build the chain of inlined functions and take the
448 // name of the topmost function in it.SmallVectorImpl &InlinedChain
448 // name of the topmost function in it.
449449 SmallVector InlinedChain;
450450 CU->getInlinedChainForAddress(Address, InlinedChain);
451 if (InlinedChain.size() == 0)
451 if (InlinedChain.empty())
452452 return false;
453 if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) {
453
454 const DWARFDie &DIE = InlinedChain[0];
455 bool FoundResult = false;
456 const char *Name = nullptr;
457 if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
454458 FunctionName = Name;
455 return true;
456 }
457 return false;
459 FoundResult = true;
460 }
461 if (auto DeclLineResult = DIE.getDeclLine()) {
462 StartLine = DeclLineResult;
463 FoundResult = true;
464 }
465
466 return FoundResult;
458467 }
459468
460469 DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
464473 DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
465474 if (!CU)
466475 return Result;
467 getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
476 getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
477 Result.FunctionName,
478 Result.StartLine);
468479 if (Spec.FLIKind != FileLineInfoKind::None) {
469480 if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
470481 LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
482493 return Lines;
483494
484495 std::string FunctionName = "";
485 getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
496 uint32_t StartLine = 0;
497 getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName,
498 StartLine);
486499
487500 // If the Specifier says we don't need FileLineInfo, just
488501 // return the top-most function at the starting address.
489502 if (Spec.FLIKind == FileLineInfoKind::None) {
490503 DILineInfo Result;
491504 Result.FunctionName = FunctionName;
505 Result.StartLine = StartLine;
492506 Lines.push_back(std::make_pair(Address, Result));
493507 return Lines;
494508 }
509523 Result.FunctionName = FunctionName;
510524 Result.Line = Row.Line;
511525 Result.Column = Row.Column;
526 Result.StartLine = StartLine;
512527 Lines.push_back(std::make_pair(Row.Address, Result));
513528 }
514529
548563 // Get function name if necessary.
549564 if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
550565 Frame.FunctionName = Name;
566 if (auto DeclLineResult = FunctionDIE.getDeclLine())
567 Frame.StartLine = DeclLineResult;
551568 if (Spec.FLIKind != FileLineInfoKind::None) {
552569 if (i == 0) {
553570 // For the topmost frame, initialize the line table of this
288288 if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
289289 return Name;
290290 return nullptr;
291 }
292
293 uint64_t DWARFDie::getDeclLine() const {
294 return toUnsigned(findRecursively(DW_AT_decl_line), 0);
291295 }
292296
293297 void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
8383 return;
8484 }
8585 OS << " Filename: " << Filename << "\n";
86 if (Info.StartLine)
87 OS << "Function start line: " << Info.StartLine << "\n";
8688 OS << " Line: " << Info.Line << "\n";
8789 OS << " Column: " << Info.Column << "\n";
8890 if (Info.Discriminator)
1414 #CHECK: 0x4004f2
1515 #CHECK-NEXT: main
1616 #CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
17 #CHECK-NEXT: Function start line: 4
1718 #CHECK-NEXT: Line: 6
1819 #CHECK-NEXT: Column: 7
1920 #CHECK-NOT: Discriminator: 0
2122 #CHECK: 0x400509
2223 #CHECK-NEXT: main
2324 #CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
25 #CHECK-NEXT: Function start line: 4
2426 #CHECK-NEXT: Line: 7
2527 #CHECK-NEXT: Column: 3
2628 #CHECK-NEXT: Discriminator: 1
2830 #CHECK: 0x40050d
2931 #CHECK-NEXT: main
3032 #CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
33 #CHECK-NEXT: Function start line: 4
3134 #CHECK-NEXT: Line: 7
3235 #CHECK-NEXT: Column: 3
3336 #CHECK-NEXT: Discriminator: 2