CommandObjectDisassemble.cpp revision 889fbd0581c24523642e0a04d659cc8f3dcdb4ed
1//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "CommandObjectDisassemble.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/AddressRange.h" 17#include "lldb/Interpreter/Args.h" 18#include "lldb/Interpreter/CommandCompletions.h" 19#include "lldb/Interpreter/CommandInterpreter.h" 20#include "lldb/Interpreter/CommandReturnObject.h" 21#include "lldb/Core/Disassembler.h" 22#include "lldb/Interpreter/Options.h" 23#include "lldb/Core/SourceManager.h" 24#include "lldb/Target/StackFrame.h" 25#include "lldb/Symbol/Symbol.h" 26#include "lldb/Target/Process.h" 27#include "lldb/Target/Target.h" 28 29#define DEFAULT_DISASM_BYTE_SIZE 32 30#define DEFAULT_DISASM_NUM_INS 4 31 32using namespace lldb; 33using namespace lldb_private; 34 35CommandObjectDisassemble::CommandOptions::CommandOptions () : 36 Options(), 37 num_lines_context(0), 38 num_instructions (0), 39 m_func_name(), 40 m_start_addr(), 41 m_end_addr (), 42 m_at_pc (false), 43 m_plugin_name (), 44 m_arch() 45{ 46 ResetOptionValues(); 47} 48 49CommandObjectDisassemble::CommandOptions::~CommandOptions () 50{ 51} 52 53Error 54CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) 55{ 56 Error error; 57 58 char short_option = (char) m_getopt_table[option_idx].val; 59 60 bool success; 61 62 switch (short_option) 63 { 64 case 'm': 65 show_mixed = true; 66 break; 67 68 case 'C': 69 num_lines_context = Args::StringToUInt32(option_arg, 0, 0, &success); 70 if (!success) 71 error.SetErrorStringWithFormat ("Invalid num context lines string: \"%s\".\n", option_arg); 72 break; 73 74 case 'c': 75 num_instructions = Args::StringToUInt32(option_arg, 0, 0, &success); 76 if (!success) 77 error.SetErrorStringWithFormat ("Invalid num of instructions string: \"%s\".\n", option_arg); 78 break; 79 80 case 'b': 81 show_bytes = true; 82 break; 83 84 case 's': 85 m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0); 86 if (m_start_addr == LLDB_INVALID_ADDRESS) 87 m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16); 88 89 if (m_start_addr == LLDB_INVALID_ADDRESS) 90 error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", option_arg); 91 break; 92 case 'e': 93 m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0); 94 if (m_end_addr == LLDB_INVALID_ADDRESS) 95 m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16); 96 97 if (m_end_addr == LLDB_INVALID_ADDRESS) 98 error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", option_arg); 99 break; 100 101 case 'n': 102 m_func_name.assign (option_arg); 103 break; 104 105 case 'p': 106 m_at_pc = true; 107 break; 108 109 case 'P': 110 m_plugin_name.assign (option_arg); 111 break; 112 113 case 'r': 114 raw = true; 115 break; 116 117 case 'f': 118 // The default action is to disassemble the function for the current frame. 119 // There's no need to set any flag. 120 break; 121 122 case 'a': 123 m_arch.SetTriple (option_arg); 124 break; 125 126 default: 127 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option); 128 break; 129 } 130 131 return error; 132} 133 134void 135CommandObjectDisassemble::CommandOptions::ResetOptionValues () 136{ 137 Options::ResetOptionValues(); 138 show_mixed = false; 139 show_bytes = false; 140 num_lines_context = 0; 141 num_instructions = 0; 142 m_func_name.clear(); 143 m_at_pc = false; 144 m_start_addr = LLDB_INVALID_ADDRESS; 145 m_end_addr = LLDB_INVALID_ADDRESS; 146 raw = false; 147 m_plugin_name.clear(); 148 m_arch.Clear(); 149} 150 151const OptionDefinition* 152CommandObjectDisassemble::CommandOptions::GetDefinitions () 153{ 154 return g_option_table; 155} 156 157OptionDefinition 158CommandObjectDisassemble::CommandOptions::g_option_table[] = 159{ 160{ LLDB_OPT_SET_ALL , false , "bytes", 'b', no_argument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, 161{ LLDB_OPT_SET_ALL , false , "context", 'C', required_argument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."}, 162{ LLDB_OPT_SET_ALL , false , "mixed", 'm', no_argument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."}, 163{ LLDB_OPT_SET_ALL , false , "raw", 'r', no_argument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, 164{ LLDB_OPT_SET_ALL , false , "plugin", 'P', required_argument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, 165{ LLDB_OPT_SET_ALL , false , "arch", 'a', required_argument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, 166{ LLDB_OPT_SET_1 | 167 LLDB_OPT_SET_2 , true , "start-address" , 's', required_argument , NULL, 0, eArgTypeStartAddress,"Address at which to start disassembling."}, 168{ LLDB_OPT_SET_1 , false , "end-address" , 'e', required_argument , NULL, 0, eArgTypeEndAddress, "Address at which to end disassembling."}, 169{ LLDB_OPT_SET_2 | 170 LLDB_OPT_SET_3 | 171 LLDB_OPT_SET_4 | 172 LLDB_OPT_SET_5 , false , "count", 'c', required_argument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."}, 173{ LLDB_OPT_SET_3 , true , "name", 'n', required_argument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."}, 174{ LLDB_OPT_SET_4 , true , "frame", 'f', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, 175{ LLDB_OPT_SET_5 , true , "pc", 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the current pc."}, 176{ 0 , false , NULL, 0, 0 , NULL, 0, eArgTypeNone, NULL } 177}; 178 179 180 181//------------------------------------------------------------------------- 182// CommandObjectDisassemble 183//------------------------------------------------------------------------- 184 185CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) : 186 CommandObject (interpreter, 187 "disassemble", 188 "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.", 189 "disassemble [<cmd-options>]") 190{ 191} 192 193CommandObjectDisassemble::~CommandObjectDisassemble() 194{ 195} 196 197bool 198CommandObjectDisassemble::Execute 199( 200 Args& command, 201 CommandReturnObject &result 202) 203{ 204 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 205 if (target == NULL) 206 { 207 result.AppendError ("invalid target, set executable file using 'file' command"); 208 result.SetStatus (eReturnStatusFailed); 209 return false; 210 } 211 if (!m_options.m_arch.IsValid()) 212 m_options.m_arch = target->GetArchitecture(); 213 214 if (!m_options.m_arch.IsValid()) 215 { 216 result.AppendError ("use the --arch option or set the target architecure to disassemble"); 217 result.SetStatus (eReturnStatusFailed); 218 return false; 219 } 220 221 const char *plugin_name = m_options.GetPluginName (); 222 Disassembler *disassembler = Disassembler::FindPlugin(m_options.m_arch, plugin_name); 223 224 if (disassembler == NULL) 225 { 226 if (plugin_name) 227 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", 228 plugin_name, 229 m_options.m_arch.GetArchitectureName()); 230 else 231 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", 232 m_options.m_arch.GetArchitectureName()); 233 result.SetStatus (eReturnStatusFailed); 234 return false; 235 } 236 237 result.SetStatus (eReturnStatusSuccessFinishResult); 238 239 if (command.GetArgumentCount() != 0) 240 { 241 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); 242 GetOptions()->GenerateOptionUsage (m_interpreter, 243 result.GetErrorStream(), 244 this); 245 246 result.SetStatus (eReturnStatusFailed); 247 return false; 248 } 249 250 if (m_options.show_mixed && m_options.num_lines_context == 0) 251 m_options.num_lines_context = 1; 252 253 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 254 255 if (!m_options.m_func_name.empty()) 256 { 257 ConstString name(m_options.m_func_name.c_str()); 258 259 if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 260 m_options.m_arch, 261 plugin_name, 262 exe_ctx, 263 name, 264 NULL, // Module * 265 m_options.num_instructions, 266 m_options.show_mixed ? m_options.num_lines_context : 0, 267 m_options.show_bytes, 268 m_options.raw, 269 result.GetOutputStream())) 270 { 271 result.SetStatus (eReturnStatusSuccessFinishResult); 272 } 273 else 274 { 275 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); 276 result.SetStatus (eReturnStatusFailed); 277 } 278 } 279 else 280 { 281 Address start_addr; 282 lldb::addr_t range_byte_size = DEFAULT_DISASM_BYTE_SIZE; 283 284 if (m_options.m_at_pc) 285 { 286 if (exe_ctx.frame == NULL) 287 { 288 result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); 289 result.SetStatus (eReturnStatusFailed); 290 return false; 291 } 292 start_addr = exe_ctx.frame->GetFrameCodeAddress(); 293 if (m_options.num_instructions == 0) 294 { 295 // Disassembling at the PC always disassembles some number of instructions (not the whole function). 296 m_options.num_instructions = DEFAULT_DISASM_NUM_INS; 297 } 298 } 299 else 300 { 301 start_addr.SetOffset (m_options.m_start_addr); 302 if (start_addr.IsValid()) 303 { 304 if (m_options.m_end_addr != LLDB_INVALID_ADDRESS) 305 { 306 if (m_options.m_end_addr < m_options.m_start_addr) 307 { 308 result.AppendErrorWithFormat ("End address before start address.\n"); 309 result.SetStatus (eReturnStatusFailed); 310 return false; 311 } 312 range_byte_size = m_options.m_end_addr - m_options.m_start_addr; 313 } 314 } 315 } 316 317 if (m_options.num_instructions != 0) 318 { 319 if (!start_addr.IsValid()) 320 { 321 // The default action is to disassemble the current frame function. 322 if (exe_ctx.frame) 323 { 324 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 325 if (sc.function) 326 start_addr = sc.function->GetAddressRange().GetBaseAddress(); 327 else if (sc.symbol && sc.symbol->GetAddressRangePtr()) 328 start_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); 329 else 330 start_addr = exe_ctx.frame->GetFrameCodeAddress(); 331 } 332 333 if (!start_addr.IsValid()) 334 { 335 result.AppendError ("invalid frame"); 336 result.SetStatus (eReturnStatusFailed); 337 return false; 338 } 339 } 340 341 if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 342 m_options.m_arch, 343 plugin_name, 344 exe_ctx, 345 start_addr, 346 m_options.num_instructions, 347 m_options.show_mixed ? m_options.num_lines_context : 0, 348 m_options.show_bytes, 349 m_options.raw, 350 result.GetOutputStream())) 351 { 352 result.SetStatus (eReturnStatusSuccessFinishResult); 353 } 354 else 355 { 356 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); 357 result.SetStatus (eReturnStatusFailed); 358 } 359 } 360 else 361 { 362 AddressRange range; 363 if (start_addr.IsValid()) 364 { 365 range.GetBaseAddress() = start_addr; 366 range.SetByteSize (range_byte_size); 367 } 368 else 369 { 370 // The default action is to disassemble the current frame function. 371 if (exe_ctx.frame) 372 { 373 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 374 if (sc.function) 375 range = sc.function->GetAddressRange(); 376 else if (sc.symbol && sc.symbol->GetAddressRangePtr()) 377 range = *sc.symbol->GetAddressRangePtr(); 378 else 379 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); 380 } 381 else 382 { 383 result.AppendError ("invalid frame"); 384 result.SetStatus (eReturnStatusFailed); 385 return false; 386 } 387 } 388 if (range.GetByteSize() == 0) 389 range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 390 391 if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 392 m_options.m_arch, 393 plugin_name, 394 exe_ctx, 395 range, 396 m_options.num_instructions, 397 m_options.show_mixed ? m_options.num_lines_context : 0, 398 m_options.show_bytes, 399 m_options.raw, 400 result.GetOutputStream())) 401 { 402 result.SetStatus (eReturnStatusSuccessFinishResult); 403 } 404 else 405 { 406 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); 407 result.SetStatus (eReturnStatusFailed); 408 } 409 } 410 } 411 412 return result.Succeeded(); 413} 414