summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/Disassembler.h99
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp7
-rw-r--r--lldb/source/Core/Disassembler.cpp301
-rw-r--r--lldb/source/Target/StackFrame.cpp18
4 files changed, 367 insertions, 58 deletions
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h
index 55c4c04d957..c90e3ea8180 100644
--- a/lldb/include/lldb/Core/Disassembler.h
+++ b/lldb/include/lldb/Core/Disassembler.h
@@ -22,7 +22,9 @@
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Opcode.h"
#include "lldb/Core/PluginInterface.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Interpreter/OptionValue.h"
+#include "lldb/Symbol/LineEntry.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -314,6 +316,7 @@ public:
const char *plugin_name, const char *flavor,
const ExecutionContext &exe_ctx,
const AddressRange &range, uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines, uint32_t options,
Stream &strm);
@@ -321,6 +324,7 @@ public:
const char *plugin_name, const char *flavor,
const ExecutionContext &exe_ctx, const Address &start,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines, uint32_t options,
Stream &strm);
@@ -328,22 +332,21 @@ public:
Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
const char *flavor, const ExecutionContext &exe_ctx,
SymbolContextList &sc_list, uint32_t num_instructions,
- uint32_t num_mixed_context_lines, uint32_t options, Stream &strm);
+ bool mixed_source_and_assembly, uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm);
- static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
- const char *plugin_name, const char *flavor,
- const ExecutionContext &exe_ctx,
- const ConstString &name, Module *module,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines, uint32_t options,
- Stream &strm);
+ static bool
+ Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
+ const char *flavor, const ExecutionContext &exe_ctx,
+ const ConstString &name, Module *module,
+ uint32_t num_instructions, bool mixed_source_and_assembly,
+ uint32_t num_mixed_context_lines, uint32_t options, Stream &strm);
- static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
- const char *plugin_name, const char *flavor,
- const ExecutionContext &exe_ctx,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines, uint32_t options,
- Stream &strm);
+ static bool
+ Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
+ const char *flavor, const ExecutionContext &exe_ctx,
+ uint32_t num_instructions, bool mixed_source_and_assembly,
+ uint32_t num_mixed_context_lines, uint32_t options, Stream &strm);
//------------------------------------------------------------------
// Constructors and Destructors
@@ -359,6 +362,7 @@ public:
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm);
@@ -388,6 +392,73 @@ public:
const char *flavor) = 0;
protected:
+ // SourceLine and SourceLinesToDisplay structures are only used in
+ // the mixed source and assembly display methods internal to this class.
+
+ struct SourceLine {
+ FileSpec file;
+ uint32_t line;
+
+ SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER) {}
+
+ bool operator==(const SourceLine &rhs) const {
+ return file == rhs.file && line == rhs.line;
+ }
+
+ bool operator!=(const SourceLine &rhs) const {
+ return file != rhs.file || line != rhs.line;
+ }
+
+ bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; }
+ };
+
+ struct SourceLinesToDisplay {
+ std::vector<SourceLine> lines;
+
+ // index of the "current" source line, if we want to highlight that
+ // when displaying the source lines. (as opposed to the surrounding
+ // source lines provided to give context)
+ size_t current_source_line;
+
+ // Whether to print a blank line at the end of the source lines.
+ bool print_source_context_end_eol;
+
+ SourceLinesToDisplay()
+ : lines(), current_source_line(-1), print_source_context_end_eol(true) {
+ }
+ };
+
+ // Get the function's declaration line number, hopefully a line number earlier
+ // than the opening curly brace at the start of the function body.
+ static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc);
+
+ // Add the provided SourceLine to the map of filenames-to-source-lines-seen.
+ static void AddLineToSourceLineTables(
+ SourceLine &line,
+ std::map<FileSpec, std::set<uint32_t>> &source_lines_seen);
+
+ // Given a source line, determine if we should print it when we're doing
+ // mixed source & assembly output.
+ // We're currently using the target.process.thread.step-avoid-regexp setting
+ // (which is used for stepping over inlined STL functions by default) to
+ // determine what source lines to avoid showing.
+ //
+ // Returns true if this source line should be elided (if the source line
+ // should
+ // not be displayed).
+ static bool
+ ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
+ const SymbolContext &sc, SourceLine &line);
+
+ static bool
+ ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
+ const SymbolContext &sc, LineEntry &line) {
+ SourceLine sl;
+ sl.file = line.file;
+ sl.line = line.line;
+ return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl);
+ };
+
//------------------------------------------------------------------
// Classes that inherit from Disassembler can see and modify these
//------------------------------------------------------------------
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index 7a1291b84a1..8dbcc3ef0af 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -313,7 +313,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
}
if (m_options.show_mixed && m_options.num_lines_context == 0)
- m_options.num_lines_context = 1;
+ m_options.num_lines_context = 2;
// Always show the PC in the disassembly
uint32_t options = Disassembler::eOptionMarkPCAddress;
@@ -336,7 +336,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
m_interpreter.GetDebugger(), m_options.arch, plugin_name,
flavor_string, m_exe_ctx, name,
nullptr, // Module *
- m_options.num_instructions,
+ m_options.num_instructions, m_options.show_mixed,
m_options.show_mixed ? m_options.num_lines_context : 0, options,
result.GetOutputStream())) {
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -499,7 +499,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
if (Disassembler::Disassemble(
m_interpreter.GetDebugger(), m_options.arch, plugin_name,
flavor_string, m_exe_ctx, cur_range.GetBaseAddress(),
- m_options.num_instructions,
+ m_options.num_instructions, m_options.show_mixed,
m_options.show_mixed ? m_options.num_lines_context : 0, options,
result.GetOutputStream())) {
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -547,6 +547,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
if (Disassembler::Disassemble(
m_interpreter.GetDebugger(), m_options.arch, plugin_name,
flavor_string, m_exe_ctx, cur_range, m_options.num_instructions,
+ m_options.show_mixed,
m_options.show_mixed ? m_options.num_lines_context : 0, options,
result.GetOutputStream())) {
result.SetStatus(eReturnStatusSuccessFinishResult);
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index ba60bb969fc..0a399cfa864 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -29,6 +29,7 @@
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueArray.h"
#include "lldb/Interpreter/OptionValueDictionary.h"
+#include "lldb/Interpreter/OptionValueRegex.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Symbol/Function.h"
@@ -120,6 +121,7 @@ size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const ExecutionContext &exe_ctx,
SymbolContextList &sc_list,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
size_t success_count = 0;
@@ -136,8 +138,8 @@ size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
sc.GetAddressRange(scope, range_idx, use_inline_block_range, range);
++range_idx) {
if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
- num_instructions, num_mixed_context_lines, options,
- strm)) {
+ num_instructions, mixed_source_and_assembly,
+ num_mixed_context_lines, options, strm)) {
++success_count;
strm.EOL();
}
@@ -151,6 +153,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const ConstString &name, Module *module,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
SymbolContextList sc_list;
@@ -169,8 +172,8 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
if (sc_list.GetSize()) {
return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list,
- num_instructions, num_mixed_context_lines, options,
- strm);
+ num_instructions, mixed_source_and_assembly,
+ num_mixed_context_lines, options, strm);
}
return false;
}
@@ -221,6 +224,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const AddressRange &disasm_range,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
if (disasm_range.GetByteSize()) {
@@ -239,8 +243,8 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
return false;
return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
- num_instructions, num_mixed_context_lines,
- options, strm);
+ num_instructions, mixed_source_and_assembly,
+ num_mixed_context_lines, options, strm);
}
}
return false;
@@ -251,6 +255,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_address,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
if (num_instructions > 0) {
@@ -265,17 +270,95 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
if (bytes_disassembled == 0)
return false;
return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
- num_instructions, num_mixed_context_lines,
- options, strm);
+ num_instructions, mixed_source_and_assembly,
+ num_mixed_context_lines, options, strm);
}
}
return false;
}
+Disassembler::SourceLine
+Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
+ SourceLine decl_line;
+ if (sc.function && sc.line_entry.IsValid()) {
+ LineEntry prologue_end_line = sc.line_entry;
+ FileSpec func_decl_file;
+ uint32_t func_decl_line;
+ sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
+ if (func_decl_file == prologue_end_line.file ||
+ func_decl_file == prologue_end_line.original_file) {
+ decl_line.file = func_decl_file;
+ decl_line.line = func_decl_line;
+ }
+ }
+ return decl_line;
+}
+
+void Disassembler::AddLineToSourceLineTables(
+ SourceLine &line,
+ std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
+ if (line.IsValid()) {
+ auto source_lines_seen_pos = source_lines_seen.find(line.file);
+ if (source_lines_seen_pos == source_lines_seen.end()) {
+ std::set<uint32_t> lines;
+ lines.insert(line.line);
+ source_lines_seen.emplace(line.file, lines);
+ } else {
+ source_lines_seen_pos->second.insert(line.line);
+ }
+ }
+}
+
+bool Disassembler::ElideMixedSourceAndDisassemblyLine(
+ const ExecutionContext &exe_ctx, const SymbolContext &sc,
+ SourceLine &line) {
+
+ // TODO: should we also check target.process.thread.step-avoid-libraries ?
+
+ const RegularExpression *avoid_regex = nullptr;
+
+ // Skip any line #0 entries - they are implementation details
+ if (line.line == 0)
+ return false;
+
+ ThreadSP thread_sp = exe_ctx.GetThreadSP();
+ if (thread_sp) {
+ avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
+ } else {
+ TargetSP target_sp = exe_ctx.GetTargetSP();
+ if (target_sp) {
+ Error error;
+ OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
+ &exe_ctx, "target.process.thread.step-avoid-regexp", false, error);
+ if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
+ OptionValueRegex *re = value_sp->GetAsRegex();
+ if (re) {
+ avoid_regex = re->GetCurrentValue();
+ }
+ }
+ }
+ }
+ if (avoid_regex && sc.symbol != nullptr) {
+ const char *function_name =
+ sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
+ .GetCString();
+ if (function_name) {
+ RegularExpression::Match regex_match(1);
+ if (avoid_regex->Execute(function_name, &regex_match)) {
+ // skip this source line
+ return true;
+ }
+ }
+ }
+ // don't skip this source line
+ return false;
+}
+
bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
Debugger &debugger, const ArchSpec &arch,
const ExecutionContext &exe_ctx,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
// We got some things disassembled...
@@ -289,7 +372,7 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
uint32_t offset = 0;
SymbolContext sc;
SymbolContext prev_sc;
- AddressRange sc_range;
+ AddressRange current_source_line_range;
const Address *pc_addr_ptr = nullptr;
StackFrame *frame = exe_ctx.GetFramePtr();
@@ -317,6 +400,16 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
// First pass: step through the list of instructions,
// find how long the initial addresses strings are, insert padding
// in the second pass so the opcodes all line up nicely.
+
+ // Also build up the source line mapping if this is mixed source & assembly
+ // mode.
+ // Calculate the source line for each assembly instruction (eliding inlined
+ // functions
+ // which the user wants to skip).
+
+ std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
+ Symbol *previous_symbol = nullptr;
+
size_t address_text_size = 0;
for (size_t i = 0; i < num_instructions_found; ++i) {
Instruction *inst =
@@ -325,8 +418,9 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
const Address &addr = inst->GetAddress();
ModuleSP module_sp(addr.GetModule());
if (module_sp) {
- const uint32_t resolve_mask =
- eSymbolContextFunction | eSymbolContextSymbol;
+ const uint32_t resolve_mask = eSymbolContextFunction |
+ eSymbolContextSymbol |
+ eSymbolContextLineEntry;
uint32_t resolved_mask =
module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
if (resolved_mask) {
@@ -336,18 +430,46 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
size_t cur_line = strmstr.GetSizeOfLastLine();
if (cur_line > address_text_size)
address_text_size = cur_line;
+
+ // Add entries to our "source_lines_seen" map+set which list which
+ // sources lines occur in this disassembly session. We will print
+ // lines of context around a source line, but we don't want to print
+ // a source line that has a line table entry of its own - we'll leave
+ // that source line to be printed when it actually occurs in the
+ // disassembly.
+
+ if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
+ if (sc.symbol != previous_symbol) {
+ SourceLine decl_line = GetFunctionDeclLineEntry(sc);
+ if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) ==
+ false)
+ AddLineToSourceLineTables(decl_line, source_lines_seen);
+ }
+ if (sc.line_entry.IsValid()) {
+ SourceLine this_line;
+ this_line.file = sc.line_entry.file;
+ this_line.line = sc.line_entry.line;
+ if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) ==
+ false)
+ AddLineToSourceLineTables(this_line, source_lines_seen);
+ }
+ }
}
sc.Clear(false);
}
}
}
+ previous_symbol = nullptr;
+ SourceLine previous_line;
for (size_t i = 0; i < num_instructions_found; ++i) {
Instruction *inst =
disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
+
if (inst) {
const Address &addr = inst->GetAddress();
const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
+ SourceLinesToDisplay source_lines_to_display;
prev_sc = sc;
@@ -356,26 +478,121 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
addr, eSymbolContextEverything, sc);
if (resolved_mask) {
- if (num_mixed_context_lines) {
- if (!sc_range.ContainsFileAddress(addr)) {
- sc.GetAddressRange(scope, 0, use_inline_block_range, sc_range);
-
- if (sc != prev_sc) {
- if (offset != 0)
- strm.EOL();
-
- sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false,
- true, false, false, true);
- strm.EOL();
-
- if (sc.comp_unit && sc.line_entry.IsValid()) {
- source_manager.DisplaySourceLinesWithLineNumbers(
- sc.line_entry.file, sc.line_entry.line,
- num_mixed_context_lines, num_mixed_context_lines,
- ((inst_is_at_pc && (options & eOptionMarkPCSourceLine))
- ? "->"
- : ""),
- &strm);
+ if (mixed_source_and_assembly) {
+
+ // If we've started a new function (non-inlined), print all of the
+ // source lines from the
+ // function declaration until the first line table entry - typically
+ // the opening curly brace of
+ // the function.
+ if (previous_symbol != sc.symbol) {
+ // The default disassembly format puts an extra blank line between
+ // functions - so
+ // when we're displaying the source context for a function, we
+ // don't want to add
+ // a blank line after the source context or we'll end up with two
+ // of them.
+ if (previous_symbol != nullptr)
+ source_lines_to_display.print_source_context_end_eol = false;
+
+ previous_symbol = sc.symbol;
+ if (sc.function && sc.line_entry.IsValid()) {
+ LineEntry prologue_end_line = sc.line_entry;
+ if (ElideMixedSourceAndDisassemblyLine(
+ exe_ctx, sc, prologue_end_line) == false) {
+ FileSpec func_decl_file;
+ uint32_t func_decl_line;
+ sc.function->GetStartLineSourceInfo(func_decl_file,
+ func_decl_line);
+ if (func_decl_file == prologue_end_line.file ||
+ func_decl_file == prologue_end_line.original_file) {
+ // Add all the lines between the function declaration
+ // and the first non-prologue source line to the list
+ // of lines to print.
+ for (uint32_t lineno = func_decl_line;
+ lineno <= prologue_end_line.line; lineno++) {
+ SourceLine this_line;
+ this_line.file = func_decl_file;
+ this_line.line = lineno;
+ source_lines_to_display.lines.push_back(this_line);
+ }
+ // Mark the last line as the "current" one. Usually
+ // this is the open curly brace.
+ if (source_lines_to_display.lines.size() > 0)
+ source_lines_to_display.current_source_line =
+ source_lines_to_display.lines.size() - 1;
+ }
+ }
+ }
+ sc.GetAddressRange(scope, 0, use_inline_block_range,
+ current_source_line_range);
+ }
+
+ // If we've left a previous source line's address range, print a new
+ // source line
+ if (!current_source_line_range.ContainsFileAddress(addr)) {
+ sc.GetAddressRange(scope, 0, use_inline_block_range,
+ current_source_line_range);
+
+ if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
+ SourceLine this_line;
+ this_line.file = sc.line_entry.file;
+ this_line.line = sc.line_entry.line;
+
+ if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
+ this_line) == false) {
+ // Only print this source line if it is different from the
+ // last source line we printed. There may have been inlined
+ // functions between these lines that we elided, resulting in
+ // the same line being printed twice in a row for a contiguous
+ // block of assembly instructions.
+ if (this_line != previous_line) {
+
+ std::vector<uint32_t> previous_lines;
+ for (int i = 0;
+ i < num_mixed_context_lines &&
+ (this_line.line - num_mixed_context_lines) > 0;
+ i++) {
+ uint32_t line =
+ this_line.line - num_mixed_context_lines + i;
+ auto pos = source_lines_seen.find(this_line.file);
+ if (pos != source_lines_seen.end()) {
+ if (pos->second.count(line) == 1) {
+ previous_lines.clear();
+ } else {
+ previous_lines.push_back(line);
+ }
+ }
+ }
+ for (size_t i = 0; i < previous_lines.size(); i++) {
+ SourceLine previous_line;
+ previous_line.file = this_line.file;
+ previous_line.line = previous_lines[i];
+ auto pos = source_lines_seen.find(previous_line.file);
+ if (pos != source_lines_seen.end()) {
+ pos->second.insert(previous_line.line);
+ }
+ source_lines_to_display.lines.push_back(previous_line);
+ }
+
+ source_lines_to_display.lines.push_back(this_line);
+ source_lines_to_display.current_source_line =
+ source_lines_to_display.lines.size() - 1;
+
+ for (int i = 0; i < num_mixed_context_lines; i++) {
+ SourceLine next_line;
+ next_line.file = this_line.file;
+ next_line.line = this_line.line + i + 1;
+ auto pos = source_lines_seen.find(next_line.file);
+ if (pos != source_lines_seen.end()) {
+ if (pos->second.count(next_line.line) == 1)
+ break;
+ pos->second.insert(next_line.line);
+ }
+ source_lines_to_display.lines.push_back(next_line);
+ }
+ }
+ previous_line = this_line;
}
}
}
@@ -385,6 +602,24 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
}
}
+ if (source_lines_to_display.lines.size() > 0) {
+ strm.EOL();
+ for (size_t idx = 0; idx < source_lines_to_display.lines.size();
+ idx++) {
+ SourceLine ln = source_lines_to_display.lines[idx];
+ const char *line_highlight = "";
+ if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
+ line_highlight = "->";
+ } else if (idx == source_lines_to_display.current_source_line) {
+ line_highlight = "**";
+ }
+ source_manager.DisplaySourceLinesWithLineNumbers(
+ ln.file, ln.line, 0, 0, line_highlight, &strm);
+ }
+ if (source_lines_to_display.print_source_context_end_eol)
+ strm.EOL();
+ }
+
const bool show_bytes = (options & eOptionShowBytes) != 0;
inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc,
&prev_sc, nullptr, address_text_size);
@@ -401,6 +636,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const char *plugin_name, const char *flavor,
const ExecutionContext &exe_ctx,
uint32_t num_instructions,
+ bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines,
uint32_t options, Stream &strm) {
AddressRange range;
@@ -422,7 +658,8 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
}
return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
- num_instructions, num_mixed_context_lines, options, strm);
+ num_instructions, mixed_source_and_assembly,
+ num_mixed_context_lines, options, strm);
}
Instruction::Instruction(const Address &address, AddressClass addr_class)
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index e491c594a1f..66c672e0772 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -229,7 +229,7 @@ const char *StackFrame::Disassemble() {
const char *flavor = nullptr;
Disassembler::Disassemble(target->GetDebugger(),
target->GetArchitecture(), plugin_name, flavor,
- exe_ctx, 0, 0, 0, m_disassembly);
+ exe_ctx, 0, false, 0, 0, m_disassembly);
}
if (m_disassembly.GetSize() == 0)
return nullptr;
@@ -853,10 +853,9 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
} else {
ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
if (no_synth_child /* synthetic is forbidden */ ||
- !synthetic /* no synthetic */
- ||
- synthetic == valobj_sp) /* synthetic is the same as the
- original object */
+ !synthetic /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the
+ original object */
{
valobj_sp->GetExpressionPath(var_expr_path_strm, false);
error.SetErrorStringWithFormat(
@@ -1906,10 +1905,11 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
target_arch.GetMaximumOpcodeByteSize());
const char *plugin_name = nullptr;
const char *flavor = nullptr;
- Disassembler::Disassemble(target->GetDebugger(), target_arch,
- plugin_name, flavor, exe_ctx, pc_range,
- disasm_lines, 0,
- Disassembler::eOptionMarkPCAddress, strm);
+ const bool mixed_source_and_assembly = false;
+ Disassembler::Disassemble(
+ target->GetDebugger(), target_arch, plugin_name, flavor,
+ exe_ctx, pc_range, disasm_lines, mixed_source_and_assembly, 0,
+ Disassembler::eOptionMarkPCAddress, strm);
}
}
break;
OpenPOWER on IntegriCloud