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 lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits