aprantl created this revision.
aprantl added reviewers: jingham, clayborg.
aprantl added a subscriber: lldb-commits.
aprantl set the repository for this revision to rL LLVM.
Here's a fun little idea plus a preliminary patch implementing it.
When I'm debugging programs I often wonder what exactly will happen when I
step-in. This is particularly a problem with code that has lots of control flow
happening on a single line, such as a C++ for loop with iterators, a function
call with a lambda or block definition, or plain old nested function calls.
For example, let's say I'm stopped inside lldb in SourceManager.cpp:93 — I
would really like to know which function I'll be stepping into next. Will the
next "step" take me into get(), new, File(), or reset()?
```
90 // If file_sp is no good or it points to a non-existent file, reset
it.
91 if (!file_sp || !file_sp->GetFileSpec().Exists())
92 {
-> 93 file_sp.reset (new File (file_spec, target_sp.get()));
94
95 if (debugger_sp)
96 debugger_sp->GetSourceFileCache().AddSourceFile(file_sp);
(lldb) step
```
Of course a debugger cannot predict the future, but what it can do is tell me
exactly where I am stopped now!
Compilers like clang already include column information in the debug info by
default. The attached patch makes use of this by adding an underline attribute
to the character on the current column to indicate the exact breakpoint on the
current line (here simulated with a caret):
```
90 // If file_sp is no good or it points to a non-existent file, reset
it.
91 if (!file_sp || !file_sp->GetFileSpec().Exists())
92 {
-> 93 file_sp.reset (new File (file_spec, target_sp.get()));
^
94
95 if (debugger_sp)
96 debugger_sp->GetSourceFileCache().AddSourceFile(file_sp);
(lldb) step
```
With this markup I may now assume that "step" will take me into the File()
constructor. Just what I wanted to know.
This is of course just scratching the surface of what we could do with column
information, but probably a good starting point. Having a more fine-grained
visualization, for example, it might be interesting to have "next" take me to
the next "is_stmt" in the line table instead of always to the next line, and so
on.
Let me know what you think!
Repository:
rL LLVM
http://reviews.llvm.org/D20835
Files:
include/lldb/API/SBSourceManager.h
include/lldb/Core/SourceManager.h
scripts/interface/SBSourceManager.i
scripts/interface/SBStream.i
source/API/SBSourceManager.cpp
source/Commands/CommandObjectSource.cpp
source/Core/Disassembler.cpp
source/Core/SourceManager.cpp
source/Target/StackFrame.cpp
Index: source/Target/StackFrame.cpp
===================================================================
--- source/Target/StackFrame.cpp
+++ source/Target/StackFrame.cpp
@@ -1579,6 +1579,7 @@
{
size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
m_sc.line_entry.line,
+ m_sc.line_entry.column,
source_lines_before,
source_lines_after,
"->",
Index: source/Core/SourceManager.cpp
===================================================================
--- source/Core/SourceManager.cpp
+++ source/Core/SourceManager.cpp
@@ -22,6 +22,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/AnsiTerminal.h"
using namespace lldb;
using namespace lldb_private;
@@ -101,6 +102,7 @@
SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line,
uint32_t count,
uint32_t curr_line,
+ uint32_t curr_column,
const char* current_line_cstr,
Stream *s,
const SymbolContextList *bp_locs)
@@ -152,7 +154,8 @@
prefix,
line == curr_line ? current_line_cstr : "",
line);
- size_t this_line_size = m_last_file_sp->DisplaySourceLines (line, 0, 0, s);
+ size_t this_line_size =
+ m_last_file_sp->DisplaySourceLines(line, line == curr_line ? curr_column : 0, s);
if (this_line_size == 0)
{
m_last_line = UINT32_MAX;
@@ -170,6 +173,7 @@
(
const FileSpec &file_spec,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char* current_line_cstr,
@@ -192,7 +196,7 @@
m_last_line = 0;
m_last_file_sp = file_sp;
}
- return DisplaySourceLinesWithLineNumbersUsingLastFile (start_line, count, line, current_line_cstr, s, bp_locs);
+ return DisplaySourceLinesWithLineNumbersUsingLastFile (start_line, count, line, column, current_line_cstr, s, bp_locs);
}
size_t
@@ -240,7 +244,7 @@
else
m_last_line = 1;
- return DisplaySourceLinesWithLineNumbersUsingLastFile (m_last_line, m_last_count, UINT32_MAX, "", s, bp_locs);
+ return DisplaySourceLinesWithLineNumbersUsingLastFile (m_last_line, m_last_count, UINT32_MAX, UINT32_MAX, "", s, bp_locs);
}
return 0;
}
@@ -548,17 +552,17 @@
}
size_t
-SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
+SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t column, Stream *s)
{
// Sanity check m_data_sp before proceeding.
if (!m_data_sp)
return 0;
- const uint32_t start_line = line <= context_before ? 1 : line - context_before;
+ const uint32_t start_line = line <= 0 ? 1 : line;
const uint32_t start_line_offset = GetLineOffset (start_line);
if (start_line_offset != UINT32_MAX)
{
- const uint32_t end_line = line + context_after;
+ const uint32_t end_line = line;
uint32_t end_line_offset = GetLineOffset (end_line + 1);
if (end_line_offset == UINT32_MAX)
end_line_offset = m_data_sp->GetByteSize();
@@ -569,7 +573,20 @@
{
size_t count = end_line_offset - start_line_offset;
const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
- bytes_written = s->Write(cstr, count);
+ if (column && column < count)
+ {
+ // Mark the current column with an underline.
+ std::string ctl;
+ bytes_written = s->Write(cstr, column-1);
+ ctl = lldb_utility::ansi::FormatAnsiTerminalCodes("${ansi.underline}");
+ bytes_written += s->Write(ctl.c_str(), ctl.length());
+ bytes_written += s->Write(cstr+column-1, 1);
+ ctl = lldb_utility::ansi::FormatAnsiTerminalCodes("${ansi.normal}");
+ bytes_written += s->Write(ctl.c_str(), ctl.length());
+ bytes_written += s->Write(cstr+column, count-column);
+ } else
+ bytes_written = s->Write(cstr, count);
+
if (!is_newline_char(cstr[count-1]))
bytes_written += s->EOL();
}
Index: source/Core/Disassembler.cpp
===================================================================
--- source/Core/Disassembler.cpp
+++ source/Core/Disassembler.cpp
@@ -475,6 +475,7 @@
{
source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
sc.line_entry.line,
+ sc.line_entry.column,
num_mixed_context_lines,
num_mixed_context_lines,
((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
Index: source/Commands/CommandObjectSource.cpp
===================================================================
--- source/Commands/CommandObjectSource.cpp
+++ source/Commands/CommandObjectSource.cpp
@@ -999,6 +999,7 @@
result.AppendMessageWithFormat("File: %s\n", start_file.GetPath().c_str());
return target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
line_no,
+ UINT32_MAX,
0,
m_options.num_lines,
"",
@@ -1279,6 +1280,7 @@
target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
sc.line_entry.line,
+ sc.line_entry.column,
lines_to_back_up,
m_options.num_lines - lines_to_back_up,
"->",
@@ -1327,6 +1329,7 @@
m_options.start_line, // Line to display
m_options.num_lines, // Lines after line to
UINT32_MAX, // Don't mark "line"
+ UINT32_MAX, // Don't mark "column"
"", // Don't mark "line"
&result.GetOutputStream(),
GetBreakpointLocations ()))
@@ -1477,6 +1480,7 @@
target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file ? sc.line_entry.file : sc.comp_unit,
m_options.start_line,
+ UINT32_MAX,
0,
m_options.num_lines,
"",
Index: source/API/SBSourceManager.cpp
===================================================================
--- source/API/SBSourceManager.cpp
+++ source/API/SBSourceManager.cpp
@@ -48,6 +48,7 @@
size_t
DisplaySourceLinesWithLineNumbers (const lldb_private::FileSpec &file,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char *current_line_cstr,
@@ -61,6 +62,7 @@
{
return target_sp->GetSourceManager().DisplaySourceLinesWithLineNumbers (file,
line,
+ column,
context_before,
context_after,
current_line_cstr,
@@ -73,6 +75,7 @@
{
return debugger_sp->GetSourceManager().DisplaySourceLinesWithLineNumbers (file,
line,
+ column,
context_before,
context_after,
current_line_cstr,
@@ -126,6 +129,7 @@
(
const SBFileSpec &file,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char *current_line_cstr,
@@ -137,6 +141,7 @@
return m_opaque_ap->DisplaySourceLinesWithLineNumbers (file.ref(),
line,
+ column,
context_before,
context_after,
current_line_cstr,
Index: scripts/interface/SBStream.i
===================================================================
--- scripts/interface/SBStream.i
+++ scripts/interface/SBStream.i
@@ -24,6 +24,7 @@
stream = lldb.SBStream()
source_mgr.DisplaySourceLinesWithLineNumbers(filespec,
self.line,
+ self.column,
2, # context before
2, # context after
'=>', # prefix for current line
Index: scripts/interface/SBSourceManager.i
===================================================================
--- scripts/interface/SBSourceManager.i
+++ scripts/interface/SBSourceManager.i
@@ -21,6 +21,7 @@
stream = lldb.SBStream()
source_mgr.DisplaySourceLinesWithLineNumbers(filespec,
self.line,
+ self.column,
2, # context before
2, # context after
'=>', # prefix for current line
@@ -45,6 +46,7 @@
size_t
DisplaySourceLinesWithLineNumbers (const lldb::SBFileSpec &file,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char* current_line_cstr,
Index: include/lldb/Core/SourceManager.h
===================================================================
--- include/lldb/Core/SourceManager.h
+++ include/lldb/Core/SourceManager.h
@@ -40,8 +40,7 @@
size_t
DisplaySourceLines (uint32_t line,
- uint32_t context_before,
- uint32_t context_after,
+ uint32_t column,
Stream *s);
void
FindLinesMatchingRegex (RegularExpression& regex,
@@ -135,6 +134,7 @@
size_t
DisplaySourceLinesWithLineNumbers(const FileSpec &file,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char* current_line_cstr,
@@ -146,6 +146,7 @@
DisplaySourceLinesWithLineNumbersUsingLastFile(uint32_t start_line,
uint32_t count,
uint32_t curr_line,
+ uint32_t curr_column,
const char* current_line_cstr,
Stream *s,
const SymbolContextList *bp_locs = nullptr);
Index: include/lldb/API/SBSourceManager.h
===================================================================
--- include/lldb/API/SBSourceManager.h
+++ include/lldb/API/SBSourceManager.h
@@ -31,6 +31,7 @@
size_t
DisplaySourceLinesWithLineNumbers (const lldb::SBFileSpec &file,
uint32_t line,
+ uint32_t column,
uint32_t context_before,
uint32_t context_after,
const char* current_line_cstr,
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits