diff options
Diffstat (limited to 'lldb/source/Core/Debugger.cpp')
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 177 |
1 files changed, 162 insertions, 15 deletions
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 5fb60cfd0b6..5a910a9040a 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -45,6 +45,8 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -122,12 +124,14 @@ g_language_enumerators[] = FILE_AND_LINE\ "\\n" +#define DEFAULT_DISASSEMBLY_FORMAT "${addr-file-or-load} <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>: " static PropertyDefinition g_properties[] = { { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, +{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, { "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, @@ -148,6 +152,7 @@ g_properties[] = enum { ePropertyAutoConfirm = 0, + ePropertyDisassemblyFormat, ePropertyFrameFormat, ePropertyNotiftVoid, ePropertyPrompt, @@ -231,6 +236,13 @@ Debugger::GetAutoConfirm () const } const char * +Debugger::GetDisassemblyFormat() const +{ + const uint32_t idx = ePropertyDisassemblyFormat; + return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); +} + +const char * Debugger::GetFrameFormat() const { const uint32_t idx = ePropertyFrameFormat; @@ -1128,6 +1140,8 @@ TestPromptFormats (StackFrame *frame) StreamString s; const char *prompt_format = "{addr = '${addr}'\n}" + "{addr-file-or-load = '${addr-file-or-load}'\n}" + "{current-pc-arrow = '${current-pc-arrow}'\n}" "{process.id = '${process.id}'\n}" "{process.name = '${process.name}'\n}" "{process.file.basename = '${process.file.basename}'\n}" @@ -1155,9 +1169,13 @@ TestPromptFormats (StackFrame *frame) "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" "{frame.reg.carp = '${frame.reg.carp}'\n}" "{function.id = '${function.id}'\n}" + "{function.changed = '${function.changed}'\n}" + "{function.initial-function = '${function.initial-function}'\n}" "{function.name = '${function.name}'\n}" + "{function.name-without-args = '${function.name-without-args}'\n}" "{function.name-with-args = '${function.name-with-args}'\n}" "{function.addr-offset = '${function.addr-offset}'\n}" + "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}" "{function.line-offset = '${function.line-offset}'\n}" "{function.pc-offset = '${function.pc-offset}'\n}" "{line.file.basename = '${line.file.basename}'\n}" @@ -1555,7 +1573,9 @@ FormatPromptRecurse const Address *addr, Stream &s, const char **end, - ValueObject* valobj + ValueObject* valobj, + bool function_changed, + bool initial_function ) { ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers @@ -1597,7 +1617,7 @@ FormatPromptRecurse ++p; // Skip the '{' - if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) + if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) { // The stream had all it needed s.Write(sub_strm.GetData(), sub_strm.GetSize()); @@ -1631,6 +1651,12 @@ FormatPromptRecurse const char *cstr = NULL; std::string token_format; Address format_addr; + + // normally "addr" means print a raw address but + // "file-addr-or-load-addr" means print a module + file addr if there's no load addr + bool print_file_addr_or_load_addr = false; + bool addr_offset_concrete_func_only = false; + bool addr_offset_print_with_no_padding = false; bool calculate_format_addr_function_offset = false; // Set reg_kind and reg_num to invalid values RegisterKind reg_kind = kNumRegisterKinds; @@ -1941,7 +1967,7 @@ FormatPromptRecurse if (!special_directions) var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); else - var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item); + var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); if (--max_num_children == 0) { @@ -1957,7 +1983,12 @@ FormatPromptRecurse } break; case 'a': - if (IsToken (var_name_begin, "addr}")) + if (IsToken (var_name_begin, "addr-file-or-load}")) + { + print_file_addr_or_load_addr = true; + } + if (IsToken (var_name_begin, "addr}") + || IsToken (var_name_begin, "addr-file-or-load}")) { if (addr && addr->IsValid()) { @@ -2159,8 +2190,7 @@ FormatPromptRecurse } } break; - - + case 'm': if (IsToken (var_name_begin, "module.")) { @@ -2288,6 +2318,14 @@ FormatPromptRecurse var_success = true; } + if (IsToken (var_name_begin, "changed}") && function_changed) + { + var_success = true; + } + if (IsToken (var_name_begin, "initial-function}") && initial_function) + { + var_success = true; + } else if (IsToken (var_name_begin, "name}")) { if (sc->function) @@ -2314,6 +2352,19 @@ FormatPromptRecurse var_success = true; } } + else if (IsToken (var_name_begin, "name-without-args}")) + { + ConstString name; + if (sc->function) + name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + else if (sc->symbol) + name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + if (name) + { + s.PutCString(name.GetCString()); + var_success = true; + } + } else if (IsToken (var_name_begin, "name-with-args}")) { // Print the function name with arguments in it @@ -2457,8 +2508,14 @@ FormatPromptRecurse } } } - else if (IsToken (var_name_begin, "addr-offset}")) + else if (IsToken (var_name_begin, "addr-offset}") + || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) { + if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) + { + addr_offset_print_with_no_padding = true; + addr_offset_concrete_func_only = true; + } var_success = addr != NULL; if (var_success) { @@ -2529,6 +2586,34 @@ FormatPromptRecurse } } break; + case 'c': + if (IsToken (var_name_begin, "current-pc-arrow")) + { + if (addr && exe_ctx && exe_ctx->GetFramePtr()) + { + RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); + if (reg_ctx.get()) + { + addr_t pc_loadaddr = reg_ctx->GetPC(); + if (pc_loadaddr != LLDB_INVALID_ADDRESS) + { + Address pc; + pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); + if (pc == *addr) + { + s.Printf ("->"); + var_success = true; + } + else + { + s.Printf(" "); + var_success = true; + } + } + } + } + } + break; } if (var_success) @@ -2586,7 +2671,7 @@ FormatPromptRecurse if (sc->function) { func_addr = sc->function->GetAddressRange().GetBaseAddress(); - if (sc->block) + if (sc->block && addr_offset_concrete_func_only == false) { // Check to make sure we aren't in an inline // function. If we are, use the inline block @@ -2604,14 +2689,19 @@ FormatPromptRecurse if (func_addr.IsValid()) { + const char *addr_offset_padding = " "; + if (addr_offset_print_with_no_padding) + { + addr_offset_padding = ""; + } if (func_addr.GetSection() == format_addr.GetSection()) { addr_t func_file_addr = func_addr.GetFileAddress(); addr_t addr_file_addr = format_addr.GetFileAddress(); if (addr_file_addr > func_file_addr) - s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); else if (addr_file_addr < func_file_addr) - s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); var_success = true; } else @@ -2622,9 +2712,9 @@ FormatPromptRecurse addr_t func_load_addr = func_addr.GetLoadAddress (target); addr_t addr_load_addr = format_addr.GetLoadAddress (target); if (addr_load_addr > func_load_addr) - s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); else if (addr_load_addr < func_load_addr) - s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); var_success = true; } } @@ -2641,10 +2731,21 @@ FormatPromptRecurse if (vaddr != LLDB_INVALID_ADDRESS) { - int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; + int addr_width = 0; + if (exe_ctx && target) + { + target->GetArchitecture().GetAddressByteSize() * 2; + } if (addr_width == 0) addr_width = 16; - s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + if (print_file_addr_or_load_addr) + { + format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); + } + else + { + s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + } var_success = true; } } @@ -2758,9 +2859,55 @@ Debugger::FormatPrompt std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); if (format_str.length()) format = format_str.c_str(); - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj); + return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); +} + +bool +Debugger::FormatDisassemblerAddress (const char *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, + Stream &s) +{ + if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) + { + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + } + bool function_changed = false; + bool initial_function = false; + if (prev_sc && (prev_sc->function || prev_sc->symbol)) + { + if (sc && (sc->function || sc->symbol)) + { + if (prev_sc->symbol && sc->symbol) + { + if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) + { + function_changed = true; + } + } + else if (prev_sc->function && sc->function) + { + if (prev_sc->function->GetMangled() != sc->function->GetMangled()) + { + function_changed = true; + } + } + } + } + // The first context on a list of instructions will have a prev_sc that + // has no Function or Symbol -- if SymbolContext had an IsValid() method, it + // would return false. But we do get a prev_sc pointer. + if ((sc && (sc->function || sc->symbol)) + && prev_sc && (prev_sc->function == NULL && prev_sc->symbol == NULL)) + { + initial_function = true; + } + return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); } + void Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) { |