Skip to content

Commit 39b2979

Browse files
authored
[lldb] Fix source display for artificial locations (#115876)
When retrieving the location of the function declaration, we were dropping the file component on the floor, which resulted in an amusingly confusing situation were we displayed the file containing the implementation of the function, but used the line number of the declaration. This patch fixes that. It required a small refactor Function::GetStartLineSourceLineInfo to return a SupportFile (instead of just the file spec), which in turn necessitated changes in a couple of other places as well.
1 parent 12dcaa2 commit 39b2979

File tree

10 files changed

+63
-38
lines changed

10 files changed

+63
-38
lines changed

Diff for: lldb/include/lldb/Symbol/Function.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ class Function : public UserID, public SymbolContextScope {
457457
///
458458
/// \param[out] line_no
459459
/// The line number.
460-
void GetStartLineSourceInfo(FileSpec &source_file, uint32_t &line_no);
460+
void GetStartLineSourceInfo(lldb::SupportFileSP &source_file_sp,
461+
uint32_t &line_no);
461462

462463
/// Find the file and line number of the source location of the end of the
463464
/// function.

Diff for: lldb/source/Breakpoint/BreakpointResolverFileLine.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -139,21 +139,23 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) {
139139
if (!sc.block)
140140
continue;
141141

142-
FileSpec file;
142+
SupportFileSP file_sp;
143143
uint32_t line;
144144
const Block *inline_block = sc.block->GetContainingInlinedBlock();
145145
if (inline_block) {
146146
const Declaration &inline_declaration = inline_block->GetInlinedFunctionInfo()->GetDeclaration();
147147
if (!inline_declaration.IsValid())
148148
continue;
149-
file = inline_declaration.GetFile();
149+
file_sp = std::make_shared<SupportFile>(inline_declaration.GetFile());
150150
line = inline_declaration.GetLine();
151151
} else if (sc.function)
152-
sc.function->GetStartLineSourceInfo(file, line);
152+
sc.function->GetStartLineSourceInfo(file_sp, line);
153153
else
154154
continue;
155155

156-
if (file != sc.line_entry.GetFile()) {
156+
if (!file_sp ||
157+
!file_sp->Equal(*sc.line_entry.file_sp,
158+
SupportFile::eEqualFileSpecAndChecksumIfSet)) {
157159
LLDB_LOG(log, "unexpected symbol context file {0}",
158160
sc.line_entry.GetFile());
159161
continue;
@@ -190,7 +192,8 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) {
190192
const int decl_line_is_too_late_fudge = 1;
191193
if (line &&
192194
m_location_spec.GetLine() < line - decl_line_is_too_late_fudge) {
193-
LLDB_LOG(log, "removing symbol context at {0}:{1}", file, line);
195+
LLDB_LOG(log, "removing symbol context at {0}:{1}",
196+
file_sp->GetSpecOnly(), line);
194197
sc_list.RemoveContextAtIndex(i);
195198
--i;
196199
}

Diff for: lldb/source/Commands/CommandObjectSource.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,7 @@ class CommandObjectSourceList : public CommandObjectParsed {
784784

785785
if (sc.block == nullptr) {
786786
// Not an inlined function
787-
FileSpec function_file_spec;
788-
sc.function->GetStartLineSourceInfo(function_file_spec, start_line);
789-
start_file = std::make_shared<SupportFile>(function_file_spec);
787+
sc.function->GetStartLineSourceInfo(start_file, start_line);
790788
if (start_line == 0) {
791789
result.AppendErrorWithFormat("Could not find line information for "
792790
"start of function: \"%s\".\n",

Diff for: lldb/source/Core/Disassembler.cpp

+19-11
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,20 @@ Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
205205
return {};
206206

207207
LineEntry prologue_end_line = sc.line_entry;
208-
FileSpec func_decl_file;
208+
SupportFileSP func_decl_file_sp;
209209
uint32_t func_decl_line;
210-
sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
210+
sc.function->GetStartLineSourceInfo(func_decl_file_sp, func_decl_line);
211211

212-
if (func_decl_file != prologue_end_line.GetFile() &&
213-
func_decl_file != prologue_end_line.original_file_sp->GetSpecOnly())
212+
if (!func_decl_file_sp)
213+
return {};
214+
if (!func_decl_file_sp->Equal(*prologue_end_line.file_sp,
215+
SupportFile::eEqualFileSpecAndChecksumIfSet) &&
216+
!func_decl_file_sp->Equal(*prologue_end_line.original_file_sp,
217+
SupportFile::eEqualFileSpecAndChecksumIfSet))
214218
return {};
215219

216220
SourceLine decl_line;
217-
decl_line.file = func_decl_file;
221+
decl_line.file = func_decl_file_sp->GetSpecOnly();
218222
decl_line.line = func_decl_line;
219223
// TODO: Do we care about column on these entries? If so, we need to plumb
220224
// that through GetStartLineSourceInfo.
@@ -410,20 +414,24 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch,
410414
LineEntry prologue_end_line = sc.line_entry;
411415
if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
412416
prologue_end_line)) {
413-
FileSpec func_decl_file;
417+
SupportFileSP func_decl_file_sp;
414418
uint32_t func_decl_line;
415-
sc.function->GetStartLineSourceInfo(func_decl_file,
419+
sc.function->GetStartLineSourceInfo(func_decl_file_sp,
416420
func_decl_line);
417-
if (func_decl_file == prologue_end_line.GetFile() ||
418-
func_decl_file ==
419-
prologue_end_line.original_file_sp->GetSpecOnly()) {
421+
if (func_decl_file_sp &&
422+
(func_decl_file_sp->Equal(
423+
*prologue_end_line.file_sp,
424+
SupportFile::eEqualFileSpecAndChecksumIfSet) ||
425+
func_decl_file_sp->Equal(
426+
*prologue_end_line.original_file_sp,
427+
SupportFile::eEqualFileSpecAndChecksumIfSet))) {
420428
// Add all the lines between the function declaration and
421429
// the first non-prologue source line to the list of lines
422430
// to print.
423431
for (uint32_t lineno = func_decl_line;
424432
lineno <= prologue_end_line.line; lineno++) {
425433
SourceLine this_line;
426-
this_line.file = func_decl_file;
434+
this_line.file = func_decl_file_sp->GetSpecOnly();
427435
this_line.line = lineno;
428436
source_lines_to_display.lines.push_back(this_line);
429437
}

Diff for: lldb/source/Symbol/Function.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,10 @@ Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
287287

288288
Function::~Function() = default;
289289

290-
void Function::GetStartLineSourceInfo(FileSpec &source_file,
290+
void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp,
291291
uint32_t &line_no) {
292292
line_no = 0;
293-
source_file.Clear();
293+
source_file_sp.reset();
294294

295295
if (m_comp_unit == nullptr)
296296
return;
@@ -299,7 +299,8 @@ void Function::GetStartLineSourceInfo(FileSpec &source_file,
299299
GetType();
300300

301301
if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) {
302-
source_file = m_type->GetDeclaration().GetFile();
302+
source_file_sp =
303+
std::make_shared<SupportFile>(m_type->GetDeclaration().GetFile());
303304
line_no = m_type->GetDeclaration().GetLine();
304305
} else {
305306
LineTable *line_table = m_comp_unit->GetLineTable();
@@ -310,7 +311,7 @@ void Function::GetStartLineSourceInfo(FileSpec &source_file,
310311
if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(),
311312
line_entry, nullptr)) {
312313
line_no = line_entry.line;
313-
source_file = line_entry.GetFile();
314+
source_file_sp = line_entry.file_sp;
314315
}
315316
}
316317
}

Diff for: lldb/source/Target/StackFrame.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1918,15 +1918,15 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
19181918
if (m_sc.comp_unit && m_sc.line_entry.IsValid()) {
19191919
have_debuginfo = true;
19201920
if (source_lines_before > 0 || source_lines_after > 0) {
1921+
SupportFileSP source_file_sp = m_sc.line_entry.file_sp;
19211922
uint32_t start_line = m_sc.line_entry.line;
19221923
if (!start_line && m_sc.function) {
1923-
FileSpec source_file;
1924-
m_sc.function->GetStartLineSourceInfo(source_file, start_line);
1924+
m_sc.function->GetStartLineSourceInfo(source_file_sp, start_line);
19251925
}
19261926

19271927
size_t num_lines =
19281928
target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
1929-
m_sc.line_entry.file_sp, start_line, m_sc.line_entry.column,
1929+
source_file_sp, start_line, m_sc.line_entry.column,
19301930
source_lines_before, source_lines_after, "->", &strm);
19311931
if (num_lines != 0)
19321932
have_source = true;

Diff for: lldb/test/API/source-manager/TestSourceManager.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -314,19 +314,28 @@ def test_set_breakpoint_with_absolute_path(self):
314314
)
315315

316316
def test_artificial_source_location(self):
317-
src_file = "artificial_location.c"
318-
d = {"C_SOURCES": src_file}
317+
src_file = "artificial_location.cpp"
318+
d = {"C_SOURCES": "", "CXX_SOURCES": src_file}
319319
self.build(dictionary=d)
320320

321-
lldbutil.run_to_source_breakpoint(
322-
self, "main", lldb.SBFileSpec(src_file, False)
323-
)
321+
target = lldbutil.run_to_breakpoint_make_target(self)
322+
323+
# Find the instruction with line=0 and put a breakpoint there.
324+
sc_list = target.FindFunctions("A::foo")
325+
self.assertEqual(len(sc_list), 1)
326+
insns = sc_list[0].function.GetInstructions(target)
327+
insn0 = next(filter(lambda insn: insn.addr.line_entry.line == 0, insns))
328+
bkpt = target.BreakpointCreateBySBAddress(insn0.addr)
329+
self.assertGreater(bkpt.GetNumLocations(), 0)
330+
331+
lldbutil.run_to_breakpoint_do_run(self, target, bkpt)
324332

325333
self.expect(
326334
"process status",
327335
substrs=[
328336
"stop reason = breakpoint",
329337
f"{src_file}:0",
338+
"static int foo();",
330339
"Note: this address is compiler-generated code in function",
331340
"that has no source code associated with it.",
332341
],

Diff for: lldb/test/API/source-manager/artificial_location.c

-6
This file was deleted.

Diff for: lldb/test/API/source-manager/artificial_location.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include "artificial_location.h"
2+
3+
int A::foo() {
4+
#line 0
5+
return 42;
6+
}
7+
8+
int main() { return A::foo(); }

Diff for: lldb/test/API/source-manager/artificial_location.h

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
struct A {
2+
static int foo();
3+
};

0 commit comments

Comments
 (0)