1254721Semaste//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "CommandObjectDisassemble.h" 13254721Semaste 14254721Semaste// C Includes 15254721Semaste// C++ Includes 16254721Semaste// Other libraries and framework includes 17254721Semaste// Project includes 18254721Semaste#include "lldb/Core/AddressRange.h" 19254721Semaste#include "lldb/Core/Disassembler.h" 20254721Semaste#include "lldb/Core/Module.h" 21254721Semaste#include "lldb/Core/SourceManager.h" 22254721Semaste#include "lldb/Interpreter/Args.h" 23254721Semaste#include "lldb/Interpreter/CommandCompletions.h" 24254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 25254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 26254721Semaste#include "lldb/Interpreter/Options.h" 27254721Semaste#include "lldb/Symbol/Function.h" 28254721Semaste#include "lldb/Symbol/Symbol.h" 29254721Semaste#include "lldb/Target/Process.h" 30269024Semaste#include "lldb/Target/SectionLoadList.h" 31254721Semaste#include "lldb/Target/StackFrame.h" 32254721Semaste#include "lldb/Target/Target.h" 33254721Semaste 34254721Semaste#define DEFAULT_DISASM_BYTE_SIZE 32 35254721Semaste#define DEFAULT_DISASM_NUM_INS 4 36254721Semaste 37254721Semasteusing namespace lldb; 38254721Semasteusing namespace lldb_private; 39254721Semaste 40254721SemasteCommandObjectDisassemble::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : 41254721Semaste Options(interpreter), 42254721Semaste num_lines_context(0), 43254721Semaste num_instructions (0), 44254721Semaste func_name(), 45254721Semaste current_function (false), 46254721Semaste start_addr(), 47254721Semaste end_addr (), 48254721Semaste at_pc (false), 49254721Semaste frame_line (false), 50254721Semaste plugin_name (), 51254721Semaste flavor_string(), 52254721Semaste arch(), 53254721Semaste some_location_specified (false), 54254721Semaste symbol_containing_addr () 55254721Semaste{ 56254721Semaste OptionParsingStarting(); 57254721Semaste} 58254721Semaste 59254721SemasteCommandObjectDisassemble::CommandOptions::~CommandOptions () 60254721Semaste{ 61254721Semaste} 62254721Semaste 63254721SemasteError 64254721SemasteCommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 65254721Semaste{ 66254721Semaste Error error; 67254721Semaste 68254721Semaste const int short_option = m_getopt_table[option_idx].val; 69254721Semaste 70254721Semaste bool success; 71254721Semaste 72254721Semaste switch (short_option) 73254721Semaste { 74254721Semaste case 'm': 75254721Semaste show_mixed = true; 76254721Semaste break; 77254721Semaste 78254721Semaste case 'C': 79254721Semaste num_lines_context = Args::StringToUInt32(option_arg, 0, 0, &success); 80254721Semaste if (!success) 81254721Semaste error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg); 82254721Semaste break; 83254721Semaste 84254721Semaste case 'c': 85254721Semaste num_instructions = Args::StringToUInt32(option_arg, 0, 0, &success); 86254721Semaste if (!success) 87254721Semaste error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg); 88254721Semaste break; 89254721Semaste 90254721Semaste case 'b': 91254721Semaste show_bytes = true; 92254721Semaste break; 93254721Semaste 94254721Semaste case 's': 95254721Semaste { 96254721Semaste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 97254721Semaste start_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 98254721Semaste if (start_addr != LLDB_INVALID_ADDRESS) 99254721Semaste some_location_specified = true; 100254721Semaste } 101254721Semaste break; 102254721Semaste case 'e': 103254721Semaste { 104254721Semaste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 105254721Semaste end_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 106254721Semaste if (end_addr != LLDB_INVALID_ADDRESS) 107254721Semaste some_location_specified = true; 108254721Semaste } 109254721Semaste break; 110254721Semaste case 'n': 111254721Semaste func_name.assign (option_arg); 112254721Semaste some_location_specified = true; 113254721Semaste break; 114254721Semaste 115254721Semaste case 'p': 116254721Semaste at_pc = true; 117254721Semaste some_location_specified = true; 118254721Semaste break; 119254721Semaste 120254721Semaste case 'l': 121254721Semaste frame_line = true; 122254721Semaste // Disassemble the current source line kind of implies showing mixed 123254721Semaste // source code context. 124254721Semaste show_mixed = true; 125254721Semaste some_location_specified = true; 126254721Semaste break; 127254721Semaste 128254721Semaste case 'P': 129254721Semaste plugin_name.assign (option_arg); 130254721Semaste break; 131254721Semaste 132254721Semaste case 'F': 133254721Semaste { 134254721Semaste Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 135254721Semaste if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 136254721Semaste || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) 137254721Semaste { 138254721Semaste flavor_string.assign (option_arg); 139254721Semaste } 140254721Semaste else 141254721Semaste error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets."); 142254721Semaste break; 143254721Semaste } 144254721Semaste case 'r': 145254721Semaste raw = true; 146254721Semaste break; 147254721Semaste 148254721Semaste case 'f': 149254721Semaste current_function = true; 150254721Semaste some_location_specified = true; 151254721Semaste break; 152254721Semaste 153254721Semaste case 'A': 154254721Semaste if (!arch.SetTriple (option_arg, m_interpreter.GetPlatform (true).get())) 155254721Semaste arch.SetTriple (option_arg); 156254721Semaste break; 157254721Semaste 158254721Semaste case 'a': 159254721Semaste { 160254721Semaste ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 161254721Semaste symbol_containing_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 162254721Semaste if (symbol_containing_addr != LLDB_INVALID_ADDRESS) 163254721Semaste { 164254721Semaste some_location_specified = true; 165254721Semaste } 166254721Semaste } 167254721Semaste break; 168254721Semaste 169254721Semaste default: 170254721Semaste error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 171254721Semaste break; 172254721Semaste } 173254721Semaste 174254721Semaste return error; 175254721Semaste} 176254721Semaste 177254721Semastevoid 178254721SemasteCommandObjectDisassemble::CommandOptions::OptionParsingStarting () 179254721Semaste{ 180254721Semaste show_mixed = false; 181254721Semaste show_bytes = false; 182254721Semaste num_lines_context = 0; 183254721Semaste num_instructions = 0; 184254721Semaste func_name.clear(); 185254721Semaste current_function = false; 186254721Semaste at_pc = false; 187254721Semaste frame_line = false; 188254721Semaste start_addr = LLDB_INVALID_ADDRESS; 189254721Semaste end_addr = LLDB_INVALID_ADDRESS; 190254721Semaste symbol_containing_addr = LLDB_INVALID_ADDRESS; 191254721Semaste raw = false; 192254721Semaste plugin_name.clear(); 193254721Semaste 194254721Semaste Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 195254721Semaste 196254721Semaste // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor 197254721Semaste // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the 198254721Semaste // only disassembler plugin we have... 199254721Semaste if (target) 200254721Semaste { 201254721Semaste if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 202254721Semaste || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) 203254721Semaste { 204254721Semaste flavor_string.assign(target->GetDisassemblyFlavor()); 205254721Semaste } 206254721Semaste else 207254721Semaste flavor_string.assign ("default"); 208254721Semaste 209254721Semaste } 210254721Semaste else 211254721Semaste flavor_string.assign("default"); 212254721Semaste 213254721Semaste arch.Clear(); 214254721Semaste some_location_specified = false; 215254721Semaste} 216254721Semaste 217254721SemasteError 218254721SemasteCommandObjectDisassemble::CommandOptions::OptionParsingFinished () 219254721Semaste{ 220254721Semaste if (!some_location_specified) 221254721Semaste current_function = true; 222254721Semaste return Error(); 223254721Semaste 224254721Semaste} 225254721Semaste 226254721Semasteconst OptionDefinition* 227254721SemasteCommandObjectDisassemble::CommandOptions::GetDefinitions () 228254721Semaste{ 229254721Semaste return g_option_table; 230254721Semaste} 231254721Semaste 232254721SemasteOptionDefinition 233254721SemasteCommandObjectDisassemble::CommandOptions::g_option_table[] = 234254721Semaste{ 235263363Semaste{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, 236263363Semaste{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."}, 237263363Semaste{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."}, 238263363Semaste{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, 239263363Semaste{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, 240263363Semaste{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " 241254721Semaste "Currently the only valid options are default, and for Intel" 242254721Semaste " architectures, att and intel."}, 243263363Semaste{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, 244254721Semaste{ LLDB_OPT_SET_1 | 245263363Semaste LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, 246263363Semaste{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."}, 247254721Semaste{ LLDB_OPT_SET_2 | 248254721Semaste LLDB_OPT_SET_3 | 249254721Semaste LLDB_OPT_SET_4 | 250263363Semaste LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."}, 251263363Semaste{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 252254721Semaste "Disassemble entire contents of the given function name."}, 253263363Semaste{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, 254263363Semaste{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."}, 255263363Semaste{ LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."}, 256263363Semaste{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, 257254721Semaste{ 0 , false, NULL , 0, 0 , NULL, 0, eArgTypeNone, NULL } 258254721Semaste}; 259254721Semaste 260254721Semaste 261254721Semaste 262254721Semaste//------------------------------------------------------------------------- 263254721Semaste// CommandObjectDisassemble 264254721Semaste//------------------------------------------------------------------------- 265254721Semaste 266254721SemasteCommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) : 267254721Semaste CommandObjectParsed (interpreter, 268254721Semaste "disassemble", 269254721Semaste "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.", 270254721Semaste "disassemble [<cmd-options>]"), 271254721Semaste m_options (interpreter) 272254721Semaste{ 273254721Semaste} 274254721Semaste 275254721SemasteCommandObjectDisassemble::~CommandObjectDisassemble() 276254721Semaste{ 277254721Semaste} 278254721Semaste 279254721Semastebool 280254721SemasteCommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) 281254721Semaste{ 282254721Semaste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 283254721Semaste if (target == NULL) 284254721Semaste { 285254721Semaste result.AppendError ("invalid target, create a debug target using the 'target create' command"); 286254721Semaste result.SetStatus (eReturnStatusFailed); 287254721Semaste return false; 288254721Semaste } 289254721Semaste if (!m_options.arch.IsValid()) 290254721Semaste m_options.arch = target->GetArchitecture(); 291254721Semaste 292254721Semaste if (!m_options.arch.IsValid()) 293254721Semaste { 294254721Semaste result.AppendError ("use the --arch option or set the target architecure to disassemble"); 295254721Semaste result.SetStatus (eReturnStatusFailed); 296254721Semaste return false; 297254721Semaste } 298254721Semaste 299254721Semaste const char *plugin_name = m_options.GetPluginName (); 300254721Semaste const char *flavor_string = m_options.GetFlavorString(); 301254721Semaste 302254721Semaste DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); 303254721Semaste 304254721Semaste if (!disassembler) 305254721Semaste { 306254721Semaste if (plugin_name) 307254721Semaste { 308254721Semaste result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", 309254721Semaste plugin_name, 310254721Semaste m_options.arch.GetArchitectureName()); 311254721Semaste } 312254721Semaste else 313254721Semaste result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", 314254721Semaste m_options.arch.GetArchitectureName()); 315254721Semaste result.SetStatus (eReturnStatusFailed); 316254721Semaste return false; 317254721Semaste } 318254721Semaste else if (flavor_string != NULL && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) 319254721Semaste result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); 320254721Semaste 321254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 322254721Semaste 323254721Semaste if (command.GetArgumentCount() != 0) 324254721Semaste { 325254721Semaste result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); 326254721Semaste GetOptions()->GenerateOptionUsage (result.GetErrorStream(), this); 327254721Semaste result.SetStatus (eReturnStatusFailed); 328254721Semaste return false; 329254721Semaste } 330254721Semaste 331254721Semaste if (m_options.show_mixed && m_options.num_lines_context == 0) 332254721Semaste m_options.num_lines_context = 1; 333254721Semaste 334254721Semaste // Always show the PC in the disassembly 335254721Semaste uint32_t options = Disassembler::eOptionMarkPCAddress; 336254721Semaste 337254721Semaste // Mark the source line for the current PC only if we are doing mixed source and assembly 338254721Semaste if (m_options.show_mixed) 339254721Semaste options |= Disassembler::eOptionMarkPCSourceLine; 340254721Semaste 341254721Semaste if (m_options.show_bytes) 342254721Semaste options |= Disassembler::eOptionShowBytes; 343254721Semaste 344254721Semaste if (m_options.raw) 345254721Semaste options |= Disassembler::eOptionRawOuput; 346254721Semaste 347254721Semaste if (!m_options.func_name.empty()) 348254721Semaste { 349254721Semaste ConstString name(m_options.func_name.c_str()); 350254721Semaste 351254721Semaste if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 352254721Semaste m_options.arch, 353254721Semaste plugin_name, 354254721Semaste flavor_string, 355254721Semaste m_exe_ctx, 356254721Semaste name, 357254721Semaste NULL, // Module * 358254721Semaste m_options.num_instructions, 359254721Semaste m_options.show_mixed ? m_options.num_lines_context : 0, 360254721Semaste options, 361254721Semaste result.GetOutputStream())) 362254721Semaste { 363254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 364254721Semaste } 365254721Semaste else 366254721Semaste { 367254721Semaste result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); 368254721Semaste result.SetStatus (eReturnStatusFailed); 369254721Semaste } 370254721Semaste } 371254721Semaste else 372254721Semaste { 373254721Semaste AddressRange range; 374254721Semaste StackFrame *frame = m_exe_ctx.GetFramePtr(); 375254721Semaste if (m_options.frame_line) 376254721Semaste { 377254721Semaste if (frame == NULL) 378254721Semaste { 379254721Semaste result.AppendError ("Cannot disassemble around the current line without a selected frame.\n"); 380254721Semaste result.SetStatus (eReturnStatusFailed); 381254721Semaste return false; 382254721Semaste } 383254721Semaste LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); 384254721Semaste if (pc_line_entry.IsValid()) 385254721Semaste { 386254721Semaste range = pc_line_entry.range; 387254721Semaste } 388254721Semaste else 389254721Semaste { 390254721Semaste m_options.at_pc = true; // No line entry, so just disassemble around the current pc 391254721Semaste m_options.show_mixed = false; 392254721Semaste } 393254721Semaste } 394254721Semaste else if (m_options.current_function) 395254721Semaste { 396254721Semaste if (frame == NULL) 397254721Semaste { 398254721Semaste result.AppendError ("Cannot disassemble around the current function without a selected frame.\n"); 399254721Semaste result.SetStatus (eReturnStatusFailed); 400254721Semaste return false; 401254721Semaste } 402254721Semaste Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 403254721Semaste if (symbol) 404254721Semaste { 405254721Semaste range.GetBaseAddress() = symbol->GetAddress(); 406254721Semaste range.SetByteSize(symbol->GetByteSize()); 407254721Semaste } 408254721Semaste } 409254721Semaste 410254721Semaste // Did the "m_options.frame_line" find a valid range already? If so 411254721Semaste // skip the rest... 412254721Semaste if (range.GetByteSize() == 0) 413254721Semaste { 414254721Semaste if (m_options.at_pc) 415254721Semaste { 416254721Semaste if (frame == NULL) 417254721Semaste { 418254721Semaste result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); 419254721Semaste result.SetStatus (eReturnStatusFailed); 420254721Semaste return false; 421254721Semaste } 422254721Semaste range.GetBaseAddress() = frame->GetFrameCodeAddress(); 423254721Semaste if (m_options.num_instructions == 0) 424254721Semaste { 425254721Semaste // Disassembling at the PC always disassembles some number of instructions (not the whole function). 426254721Semaste m_options.num_instructions = DEFAULT_DISASM_NUM_INS; 427254721Semaste } 428254721Semaste } 429254721Semaste else 430254721Semaste { 431254721Semaste range.GetBaseAddress().SetOffset (m_options.start_addr); 432254721Semaste if (range.GetBaseAddress().IsValid()) 433254721Semaste { 434254721Semaste if (m_options.end_addr != LLDB_INVALID_ADDRESS) 435254721Semaste { 436254721Semaste if (m_options.end_addr <= m_options.start_addr) 437254721Semaste { 438254721Semaste result.AppendErrorWithFormat ("End address before start address.\n"); 439254721Semaste result.SetStatus (eReturnStatusFailed); 440254721Semaste return false; 441254721Semaste } 442254721Semaste range.SetByteSize (m_options.end_addr - m_options.start_addr); 443254721Semaste } 444254721Semaste } 445254721Semaste else 446254721Semaste { 447254721Semaste if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS 448254721Semaste && target 449254721Semaste && !target->GetSectionLoadList().IsEmpty()) 450254721Semaste { 451254721Semaste bool failed = false; 452254721Semaste Address symbol_containing_address; 453254721Semaste if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address)) 454254721Semaste { 455254721Semaste ModuleSP module_sp (symbol_containing_address.GetModule()); 456254721Semaste SymbolContext sc; 457263363Semaste bool resolve_tail_call_address = true; // PC can be one past the address range of the function. 458263363Semaste module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc, 459263363Semaste resolve_tail_call_address); 460254721Semaste if (sc.function || sc.symbol) 461254721Semaste { 462254721Semaste sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); 463254721Semaste } 464254721Semaste else 465254721Semaste { 466254721Semaste failed = true; 467254721Semaste } 468254721Semaste } 469254721Semaste else 470254721Semaste { 471254721Semaste failed = true; 472254721Semaste } 473254721Semaste if (failed) 474254721Semaste { 475254721Semaste result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr); 476254721Semaste result.SetStatus (eReturnStatusFailed); 477254721Semaste return false; 478254721Semaste } 479254721Semaste } 480254721Semaste } 481254721Semaste } 482254721Semaste } 483254721Semaste 484254721Semaste if (m_options.num_instructions != 0) 485254721Semaste { 486254721Semaste if (!range.GetBaseAddress().IsValid()) 487254721Semaste { 488254721Semaste // The default action is to disassemble the current frame function. 489254721Semaste if (frame) 490254721Semaste { 491254721Semaste SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 492254721Semaste if (sc.function) 493254721Semaste range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); 494254721Semaste else if (sc.symbol && sc.symbol->ValueIsAddress()) 495254721Semaste range.GetBaseAddress() = sc.symbol->GetAddress(); 496254721Semaste else 497254721Semaste range.GetBaseAddress() = frame->GetFrameCodeAddress(); 498254721Semaste } 499254721Semaste 500254721Semaste if (!range.GetBaseAddress().IsValid()) 501254721Semaste { 502254721Semaste result.AppendError ("invalid frame"); 503254721Semaste result.SetStatus (eReturnStatusFailed); 504254721Semaste return false; 505254721Semaste } 506254721Semaste } 507254721Semaste 508254721Semaste if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 509254721Semaste m_options.arch, 510254721Semaste plugin_name, 511254721Semaste flavor_string, 512254721Semaste m_exe_ctx, 513254721Semaste range.GetBaseAddress(), 514254721Semaste m_options.num_instructions, 515254721Semaste m_options.show_mixed ? m_options.num_lines_context : 0, 516254721Semaste options, 517254721Semaste result.GetOutputStream())) 518254721Semaste { 519254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 520254721Semaste } 521254721Semaste else 522254721Semaste { 523254721Semaste result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); 524254721Semaste result.SetStatus (eReturnStatusFailed); 525254721Semaste } 526254721Semaste } 527254721Semaste else 528254721Semaste { 529254721Semaste if (!range.GetBaseAddress().IsValid()) 530254721Semaste { 531254721Semaste // The default action is to disassemble the current frame function. 532254721Semaste if (frame) 533254721Semaste { 534254721Semaste SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 535254721Semaste if (sc.function) 536254721Semaste range = sc.function->GetAddressRange(); 537254721Semaste else if (sc.symbol && sc.symbol->ValueIsAddress()) 538254721Semaste { 539254721Semaste range.GetBaseAddress() = sc.symbol->GetAddress(); 540254721Semaste range.SetByteSize (sc.symbol->GetByteSize()); 541254721Semaste } 542254721Semaste else 543254721Semaste range.GetBaseAddress() = frame->GetFrameCodeAddress(); 544254721Semaste } 545254721Semaste else 546254721Semaste { 547254721Semaste result.AppendError ("invalid frame"); 548254721Semaste result.SetStatus (eReturnStatusFailed); 549254721Semaste return false; 550254721Semaste } 551254721Semaste } 552254721Semaste if (range.GetByteSize() == 0) 553254721Semaste range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 554254721Semaste 555254721Semaste if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 556254721Semaste m_options.arch, 557254721Semaste plugin_name, 558254721Semaste flavor_string, 559254721Semaste m_exe_ctx, 560254721Semaste range, 561254721Semaste m_options.num_instructions, 562254721Semaste m_options.show_mixed ? m_options.num_lines_context : 0, 563254721Semaste options, 564254721Semaste result.GetOutputStream())) 565254721Semaste { 566254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 567254721Semaste } 568254721Semaste else 569254721Semaste { 570254721Semaste result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); 571254721Semaste result.SetStatus (eReturnStatusFailed); 572254721Semaste } 573254721Semaste } 574254721Semaste } 575254721Semaste 576254721Semaste return result.Succeeded(); 577254721Semaste} 578