Skip to content

Commit 69da27c

Browse files
committed
llvm-symbolizer: Add optional "start file" to match "start line"
Since a function might have portions of its code coming from multiple different files, "start line" is ambiguous (it can't just be resolved relative to the file/line specified). Add start file to disambiguate it.
1 parent b1e68f8 commit 69da27c

File tree

7 files changed

+59
-15
lines changed

7 files changed

+59
-15
lines changed

llvm/include/llvm/DebugInfo/DIContext.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct DILineInfo {
3535
static constexpr const char *const Addr2LineBadString = "??";
3636
std::string FileName;
3737
std::string FunctionName;
38+
std::string StartFileName;
3839
Optional<StringRef> Source;
3940
uint32_t Line = 0;
4041
uint32_t Column = 0;
@@ -43,23 +44,26 @@ struct DILineInfo {
4344
// DWARF-specific.
4445
uint32_t Discriminator = 0;
4546

46-
DILineInfo() : FileName(BadString), FunctionName(BadString) {}
47+
DILineInfo()
48+
: FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
49+
}
4750

4851
bool operator==(const DILineInfo &RHS) const {
4952
return Line == RHS.Line && Column == RHS.Column &&
5053
FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
51-
StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
54+
StartFileName == RHS.StartFileName && StartLine == RHS.StartLine &&
55+
Discriminator == RHS.Discriminator;
5256
}
5357

5458
bool operator!=(const DILineInfo &RHS) const {
5559
return !(*this == RHS);
5660
}
5761

5862
bool operator<(const DILineInfo &RHS) const {
59-
return std::tie(FileName, FunctionName, Line, Column, StartLine,
60-
Discriminator) <
61-
std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
62-
RHS.StartLine, RHS.Discriminator);
63+
return std::tie(FileName, FunctionName, StartFileName, Line, Column,
64+
StartLine, Discriminator) <
65+
std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line,
66+
RHS.Column, RHS.StartLine, RHS.Discriminator);
6367
}
6468

6569
explicit operator bool() const { return *this != DILineInfo(); }
@@ -72,6 +76,8 @@ struct DILineInfo {
7276
OS << "function '" << FunctionName << "', ";
7377
OS << "line " << Line << ", ";
7478
OS << "column " << Column << ", ";
79+
if (StartFileName != BadString)
80+
OS << "start file '" << StartFileName << "', ";
7581
OS << "start line " << StartLine << '\n';
7682
}
7783
};

llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ class DWARFDie {
262262
/// for this subprogram by resolving DW_AT_sepcification or
263263
/// DW_AT_abstract_origin references if necessary.
264264
uint64_t getDeclLine() const;
265+
std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const;
265266

266267
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
267268
/// from DIE (or zeroes if they are missing). This function looks for

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,9 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
10361036
static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
10371037
uint64_t Address,
10381038
FunctionNameKind Kind,
1039+
DILineInfoSpecifier::FileLineInfoKind FileNameKind,
10391040
std::string &FunctionName,
1041+
std::string &StartFile,
10401042
uint32_t &StartLine) {
10411043
// The address may correspond to instruction in some inlined function,
10421044
// so we have to build the chain of inlined functions and take the
@@ -1053,6 +1055,11 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
10531055
FunctionName = Name;
10541056
FoundResult = true;
10551057
}
1058+
std::string DeclFile = DIE.getDeclFile(FileNameKind);
1059+
if (!DeclFile.empty()) {
1060+
StartFile = DeclFile;
1061+
FoundResult = true;
1062+
}
10561063
if (auto DeclLineResult = DIE.getDeclLine()) {
10571064
StartLine = DeclLineResult;
10581065
FoundResult = true;
@@ -1224,8 +1231,9 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
12241231
if (!CU)
12251232
return Result;
12261233

1227-
getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
1228-
Result.FunctionName, Result.StartLine);
1234+
getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind,
1235+
Result.FunctionName,
1236+
Result.StartFileName, Result.StartLine);
12291237
if (Spec.FLIKind != FileLineInfoKind::None) {
12301238
if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
12311239
LineTable->getFileLineInfoForAddress(
@@ -1244,15 +1252,17 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(
12441252
return Lines;
12451253

12461254
uint32_t StartLine = 0;
1255+
std::string StartFileName;
12471256
std::string FunctionName(DILineInfo::BadString);
1248-
getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
1249-
FunctionName, StartLine);
1257+
getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind,
1258+
FunctionName, StartFileName, StartLine);
12501259

12511260
// If the Specifier says we don't need FileLineInfo, just
12521261
// return the top-most function at the starting address.
12531262
if (Spec.FLIKind == FileLineInfoKind::None) {
12541263
DILineInfo Result;
12551264
Result.FunctionName = FunctionName;
1265+
Result.StartFileName = StartFileName;
12561266
Result.StartLine = StartLine;
12571267
Lines.push_back(std::make_pair(Address.Address, Result));
12581268
return Lines;
@@ -1276,6 +1286,7 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(
12761286
Result.FunctionName = FunctionName;
12771287
Result.Line = Row.Line;
12781288
Result.Column = Row.Column;
1289+
Result.StartFileName = StartFileName;
12791290
Result.StartLine = StartLine;
12801291
Lines.push_back(std::make_pair(Row.Address.Address, Result));
12811292
}
@@ -1318,6 +1329,7 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
13181329
Frame.FunctionName = Name;
13191330
if (auto DeclLineResult = FunctionDIE.getDeclLine())
13201331
Frame.StartLine = DeclLineResult;
1332+
Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
13211333
if (Spec.FLIKind != FileLineInfoKind::None) {
13221334
if (i == 0) {
13231335
// For the topmost frame, initialize the line table of this

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,17 @@ uint64_t DWARFDie::getDeclLine() const {
557557
return toUnsigned(findRecursively(DW_AT_decl_line), 0);
558558
}
559559

560+
std::string
561+
DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
562+
std::string FileName;
563+
if (auto DeclFile = toUnsigned(findRecursively(DW_AT_decl_file))) {
564+
if (const auto *LT = U->getContext().getLineTableForUnit(U)) {
565+
LT->getFileNameByIndex(*DeclFile, U->getCompilationDir(), Kind, FileName);
566+
}
567+
}
568+
return FileName;
569+
}
570+
560571
void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
561572
uint32_t &CallColumn,
562573
uint32_t &CallDiscriminator) const {

llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
8484
return;
8585
}
8686
OS << " Filename: " << Filename << "\n";
87-
if (Info.StartLine)
88-
OS << "Function start line: " << Info.StartLine << "\n";
87+
if (Info.StartLine) {
88+
OS << " Function start filename: " << Info.StartFileName << "\n";
89+
OS << " Function start line: " << Info.StartLine << "\n";
90+
}
8991
OS << " Line: " << Info.Line << "\n";
9092
OS << " Column: " << Info.Column << "\n";
9193
if (Info.Discriminator)

llvm/test/tools/llvm-dwarfdump/X86/lookup.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
# LEX: DW_AT_low_pc (0x0000000000000004)
3838
# LEX: DW_AT_high_pc (0x0000000000000014)
3939

40-
# A: Line info: file 'foo.c', line 3, column 9, start line 1
41-
# B: Line info: file 'foo.c', line 4, column 6, start line 1
42-
# C: Line info: file 'foo.c', line 6, column 1, start line 1
40+
# A: Line info: file 'foo.c', line 3, column 9, start file 'foo.c', start line 1
41+
# B: Line info: file 'foo.c', line 4, column 6, start file 'foo.c', start line 1
42+
# C: Line info: file 'foo.c', line 6, column 1, start file 'foo.c', start line 1
4343

4444
.section __TEXT,__text,regular,pure_instructions
4545
.macosx_version_min 10, 13

llvm/test/tools/llvm-symbolizer/sym-verbose.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,49 +18,57 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
1818
#CHECK: 0x400590
1919
#CHECK-NEXT: foo
2020
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
21+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
2122
#CHECK-NEXT: Function start line: 4
2223
#CHECK-NEXT: Line: 5
2324
#CHECK-NEXT: Column: 7
2425
#CHECK-NEXT: main
2526
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
27+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
2628
#CHECK-NEXT: Function start line: 9
2729
#CHECK-NEXT: Line: 10
2830
#CHECK-NEXT: Column: 0
2931

3032
#CHECK: 0x4005a5
3133
#CHECK-NEXT: foo
3234
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
35+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
3336
#CHECK-NEXT: Function start line: 4
3437
#CHECK-NEXT: Line: 5
3538
#CHECK-NEXT: Column: 17
3639
#CHECK-NEXT: Discriminator: 2
3740
#CHECK-NEXT: main
3841
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
42+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
3943
#CHECK-NEXT: Function start line: 9
4044
#CHECK-NEXT: Line: 10
4145
#CHECK-NEXT: Column: 0
4246

4347
#CHECK: 0x4005ad
4448
#CHECK-NEXT: foo
4549
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
50+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
4651
#CHECK-NEXT: Function start line: 4
4752
#CHECK-NEXT: Line: 0
4853
#CHECK-NEXT: Column: 30
4954
#CHECK-NEXT: Discriminator: 4
5055
#CHECK-NEXT: main
5156
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
57+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
5258
#CHECK-NEXT: Function start line: 9
5359
#CHECK-NEXT: Line: 10
5460
#CHECK-NEXT: Column: 0
5561

5662
#CHECK: 0x4005b9
5763
#CHECK-NEXT: foo
5864
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
65+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
5966
#CHECK-NEXT: Function start line: 4
6067
#CHECK-NEXT: Line: 5
6168
#CHECK-NEXT: Column: 7
6269
#CHECK-NEXT: main
6370
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
71+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
6472
#CHECK-NEXT: Function start line: 9
6573
#CHECK-NEXT: Line: 10
6674
#CHECK-NEXT: Column: 0
@@ -69,12 +77,14 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
6977
#CHECK: 0x4005ce
7078
#CHECK-NEXT: foo
7179
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
80+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
7281
#CHECK-NEXT: Function start line: 4
7382
#CHECK-NEXT: Line: 5
7483
#CHECK-NEXT: Column: 17
7584
#CHECK-NEXT: Discriminator: 2
7685
#CHECK-NEXT: main
7786
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
87+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
7888
#CHECK-NEXT: Function start line: 9
7989
#CHECK-NEXT: Line: 10
8090
#CHECK-NEXT: Column: 0
@@ -83,12 +93,14 @@ RUN: llvm-symbolizer -verbose -print-address -obj=%p/Inputs/discrim < %p/Inputs/
8393
#CHECK: 0x4005d4
8494
#CHECK-NEXT: foo
8595
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
96+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
8697
#CHECK-NEXT: Function start line: 4
8798
#CHECK-NEXT: Line: 5
8899
#CHECK-NEXT: Column: 30
89100
#CHECK-NEXT: Discriminator: 4
90101
#CHECK-NEXT: main
91102
#CHECK-NEXT: Filename: /tmp{{[\\/]}}discrim.c
103+
#CHECK-NEXT: Function start filename: /tmp{{[\\/]}}discrim.c
92104
#CHECK-NEXT: Function start line: 9
93105
#CHECK-NEXT: Line: 10
94106
#CHECK-NEXT: Column: 0

0 commit comments

Comments
 (0)