1 //===-- CommandObjectDisassemble.cpp --------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectDisassemble.h" 10 #include "lldb/Core/AddressRange.h" 11 #include "lldb/Core/Disassembler.h" 12 #include "lldb/Core/Module.h" 13 #include "lldb/Host/OptionParser.h" 14 #include "lldb/Interpreter/CommandInterpreter.h" 15 #include "lldb/Interpreter/CommandOptionArgumentTable.h" 16 #include "lldb/Interpreter/CommandReturnObject.h" 17 #include "lldb/Interpreter/OptionArgParser.h" 18 #include "lldb/Interpreter/Options.h" 19 #include "lldb/Symbol/Function.h" 20 #include "lldb/Symbol/Symbol.h" 21 #include "lldb/Target/SectionLoadList.h" 22 #include "lldb/Target/StackFrame.h" 23 #include "lldb/Target/Target.h" 24 25 static constexpr unsigned default_disasm_byte_size = 32; 26 static constexpr unsigned default_disasm_num_ins = 4; 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 #define LLDB_OPTIONS_disassemble 32 #include "CommandOptions.inc" 33 34 CommandObjectDisassemble::CommandOptions::CommandOptions() { 35 OptionParsingStarting(nullptr); 36 } 37 38 CommandObjectDisassemble::CommandOptions::~CommandOptions() = default; 39 40 Status CommandObjectDisassemble::CommandOptions::SetOptionValue( 41 uint32_t option_idx, llvm::StringRef option_arg, 42 ExecutionContext *execution_context) { 43 Status error; 44 45 const int short_option = m_getopt_table[option_idx].val; 46 47 switch (short_option) { 48 case 'm': 49 show_mixed = true; 50 break; 51 52 case 'C': 53 if (option_arg.getAsInteger(0, num_lines_context)) 54 error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"", 55 option_arg.str().c_str()); 56 break; 57 58 case 'c': 59 if (option_arg.getAsInteger(0, num_instructions)) 60 error.SetErrorStringWithFormat( 61 "invalid num of instructions string: \"%s\"", 62 option_arg.str().c_str()); 63 break; 64 65 case 'b': 66 show_bytes = true; 67 break; 68 69 case 'k': 70 show_control_flow_kind = true; 71 break; 72 73 case 's': { 74 start_addr = OptionArgParser::ToAddress(execution_context, option_arg, 75 LLDB_INVALID_ADDRESS, &error); 76 if (start_addr != LLDB_INVALID_ADDRESS) 77 some_location_specified = true; 78 } break; 79 case 'e': { 80 end_addr = OptionArgParser::ToAddress(execution_context, option_arg, 81 LLDB_INVALID_ADDRESS, &error); 82 if (end_addr != LLDB_INVALID_ADDRESS) 83 some_location_specified = true; 84 } break; 85 86 case 'n': 87 func_name.assign(std::string(option_arg)); 88 some_location_specified = true; 89 break; 90 91 case 'p': 92 at_pc = true; 93 some_location_specified = true; 94 break; 95 96 case 'l': 97 frame_line = true; 98 // Disassemble the current source line kind of implies showing mixed source 99 // code context. 100 show_mixed = true; 101 some_location_specified = true; 102 break; 103 104 case 'P': 105 plugin_name.assign(std::string(option_arg)); 106 break; 107 108 case 'F': { 109 TargetSP target_sp = 110 execution_context ? execution_context->GetTargetSP() : TargetSP(); 111 if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() == 112 llvm::Triple::x86 || 113 target_sp->GetArchitecture().GetTriple().getArch() == 114 llvm::Triple::x86_64)) { 115 flavor_string.assign(std::string(option_arg)); 116 } else 117 error.SetErrorStringWithFormat("Disassembler flavors are currently only " 118 "supported for x86 and x86_64 targets."); 119 break; 120 } 121 122 case 'r': 123 raw = true; 124 break; 125 126 case 'f': 127 current_function = true; 128 some_location_specified = true; 129 break; 130 131 case 'A': 132 if (execution_context) { 133 const auto &target_sp = execution_context->GetTargetSP(); 134 auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr; 135 arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg); 136 } 137 break; 138 139 case 'a': { 140 symbol_containing_addr = OptionArgParser::ToAddress( 141 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 142 if (symbol_containing_addr != LLDB_INVALID_ADDRESS) { 143 some_location_specified = true; 144 } 145 } break; 146 147 case '\x01': 148 force = true; 149 break; 150 151 default: 152 llvm_unreachable("Unimplemented option"); 153 } 154 155 return error; 156 } 157 158 void CommandObjectDisassemble::CommandOptions::OptionParsingStarting( 159 ExecutionContext *execution_context) { 160 show_mixed = false; 161 show_bytes = false; 162 show_control_flow_kind = false; 163 num_lines_context = 0; 164 num_instructions = 0; 165 func_name.clear(); 166 current_function = false; 167 at_pc = false; 168 frame_line = false; 169 start_addr = LLDB_INVALID_ADDRESS; 170 end_addr = LLDB_INVALID_ADDRESS; 171 symbol_containing_addr = LLDB_INVALID_ADDRESS; 172 raw = false; 173 plugin_name.clear(); 174 175 Target *target = 176 execution_context ? execution_context->GetTargetPtr() : nullptr; 177 178 // This is a hack till we get the ability to specify features based on 179 // architecture. For now GetDisassemblyFlavor is really only valid for x86 180 // (and for the llvm assembler plugin, but I'm papering over that since that 181 // is the only disassembler plugin we have... 182 if (target) { 183 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 || 184 target->GetArchitecture().GetTriple().getArch() == 185 llvm::Triple::x86_64) { 186 flavor_string.assign(target->GetDisassemblyFlavor()); 187 } else 188 flavor_string.assign("default"); 189 190 } else 191 flavor_string.assign("default"); 192 193 arch.Clear(); 194 some_location_specified = false; 195 force = false; 196 } 197 198 Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished( 199 ExecutionContext *execution_context) { 200 if (!some_location_specified) 201 current_function = true; 202 return Status(); 203 } 204 205 llvm::ArrayRef<OptionDefinition> 206 CommandObjectDisassemble::CommandOptions::GetDefinitions() { 207 return llvm::makeArrayRef(g_disassemble_options); 208 } 209 210 // CommandObjectDisassemble 211 212 CommandObjectDisassemble::CommandObjectDisassemble( 213 CommandInterpreter &interpreter) 214 : CommandObjectParsed( 215 interpreter, "disassemble", 216 "Disassemble specified instructions in the current target. " 217 "Defaults to the current function for the current thread and " 218 "stack frame.", 219 "disassemble [<cmd-options>]", eCommandRequiresTarget), 220 m_options() {} 221 222 CommandObjectDisassemble::~CommandObjectDisassemble() = default; 223 224 llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range, 225 llvm::StringRef what) { 226 if (m_options.num_instructions > 0 || m_options.force || 227 range.GetByteSize() < GetDebugger().GetStopDisassemblyMaxSize()) 228 return llvm::Error::success(); 229 StreamString msg; 230 msg << "Not disassembling " << what << " because it is very large "; 231 range.Dump(&msg, &GetSelectedTarget(), Address::DumpStyleLoadAddress, 232 Address::DumpStyleFileAddress); 233 msg << ". To disassemble specify an instruction count limit, start/stop " 234 "addresses or use the --force option."; 235 return llvm::createStringError(llvm::inconvertibleErrorCode(), 236 msg.GetString()); 237 } 238 239 llvm::Expected<std::vector<AddressRange>> 240 CommandObjectDisassemble::GetContainingAddressRanges() { 241 std::vector<AddressRange> ranges; 242 const auto &get_range = [&](Address addr) { 243 ModuleSP module_sp(addr.GetModule()); 244 SymbolContext sc; 245 bool resolve_tail_call_address = true; 246 addr.GetModule()->ResolveSymbolContextForAddress( 247 addr, eSymbolContextEverything, sc, resolve_tail_call_address); 248 if (sc.function || sc.symbol) { 249 AddressRange range; 250 sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, 251 false, range); 252 ranges.push_back(range); 253 } 254 }; 255 256 Target &target = GetSelectedTarget(); 257 if (!target.GetSectionLoadList().IsEmpty()) { 258 Address symbol_containing_address; 259 if (target.GetSectionLoadList().ResolveLoadAddress( 260 m_options.symbol_containing_addr, symbol_containing_address)) { 261 get_range(symbol_containing_address); 262 } 263 } else { 264 for (lldb::ModuleSP module_sp : target.GetImages().Modules()) { 265 Address file_address; 266 if (module_sp->ResolveFileAddress(m_options.symbol_containing_addr, 267 file_address)) { 268 get_range(file_address); 269 } 270 } 271 } 272 273 if (ranges.empty()) { 274 return llvm::createStringError( 275 llvm::inconvertibleErrorCode(), 276 "Could not find function bounds for address 0x%" PRIx64, 277 m_options.symbol_containing_addr); 278 } 279 280 if (llvm::Error err = CheckRangeSize(ranges[0], "the function")) 281 return std::move(err); 282 return ranges; 283 } 284 285 llvm::Expected<std::vector<AddressRange>> 286 CommandObjectDisassemble::GetCurrentFunctionRanges() { 287 Process *process = m_exe_ctx.GetProcessPtr(); 288 StackFrame *frame = m_exe_ctx.GetFramePtr(); 289 if (!frame) { 290 if (process) { 291 return llvm::createStringError( 292 llvm::inconvertibleErrorCode(), 293 "Cannot disassemble around the current " 294 "function without the process being stopped.\n"); 295 } else { 296 return llvm::createStringError(llvm::inconvertibleErrorCode(), 297 "Cannot disassemble around the current " 298 "function without a selected frame: " 299 "no currently running process.\n"); 300 } 301 } 302 SymbolContext sc( 303 frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 304 AddressRange range; 305 if (sc.function) 306 range = sc.function->GetAddressRange(); 307 else if (sc.symbol && sc.symbol->ValueIsAddress()) { 308 range = {sc.symbol->GetAddress(), sc.symbol->GetByteSize()}; 309 } else 310 range = {frame->GetFrameCodeAddress(), default_disasm_byte_size}; 311 312 if (llvm::Error err = CheckRangeSize(range, "the current function")) 313 return std::move(err); 314 return std::vector<AddressRange>{range}; 315 } 316 317 llvm::Expected<std::vector<AddressRange>> 318 CommandObjectDisassemble::GetCurrentLineRanges() { 319 Process *process = m_exe_ctx.GetProcessPtr(); 320 StackFrame *frame = m_exe_ctx.GetFramePtr(); 321 if (!frame) { 322 if (process) { 323 return llvm::createStringError( 324 llvm::inconvertibleErrorCode(), 325 "Cannot disassemble around the current " 326 "function without the process being stopped.\n"); 327 } else { 328 return llvm::createStringError(llvm::inconvertibleErrorCode(), 329 "Cannot disassemble around the current " 330 "line without a selected frame: " 331 "no currently running process.\n"); 332 } 333 } 334 335 LineEntry pc_line_entry( 336 frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); 337 if (pc_line_entry.IsValid()) 338 return std::vector<AddressRange>{pc_line_entry.range}; 339 340 // No line entry, so just disassemble around the current pc 341 m_options.show_mixed = false; 342 return GetPCRanges(); 343 } 344 345 llvm::Expected<std::vector<AddressRange>> 346 CommandObjectDisassemble::GetNameRanges(CommandReturnObject &result) { 347 ConstString name(m_options.func_name.c_str()); 348 349 ModuleFunctionSearchOptions function_options; 350 function_options.include_symbols = true; 351 function_options.include_inlines = true; 352 353 // Find functions matching the given name. 354 SymbolContextList sc_list; 355 GetSelectedTarget().GetImages().FindFunctions(name, eFunctionNameTypeAuto, 356 function_options, sc_list); 357 358 std::vector<AddressRange> ranges; 359 llvm::Error range_errs = llvm::Error::success(); 360 AddressRange range; 361 const uint32_t scope = 362 eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 363 const bool use_inline_block_range = true; 364 for (SymbolContext sc : sc_list.SymbolContexts()) { 365 for (uint32_t range_idx = 0; 366 sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); 367 ++range_idx) { 368 if (llvm::Error err = CheckRangeSize(range, "a range")) 369 range_errs = joinErrors(std::move(range_errs), std::move(err)); 370 else 371 ranges.push_back(range); 372 } 373 } 374 if (ranges.empty()) { 375 if (range_errs) 376 return std::move(range_errs); 377 return llvm::createStringError(llvm::inconvertibleErrorCode(), 378 "Unable to find symbol with name '%s'.\n", 379 name.GetCString()); 380 } 381 if (range_errs) 382 result.AppendWarning(toString(std::move(range_errs))); 383 return ranges; 384 } 385 386 llvm::Expected<std::vector<AddressRange>> 387 CommandObjectDisassemble::GetPCRanges() { 388 Process *process = m_exe_ctx.GetProcessPtr(); 389 StackFrame *frame = m_exe_ctx.GetFramePtr(); 390 if (!frame) { 391 if (process) { 392 return llvm::createStringError( 393 llvm::inconvertibleErrorCode(), 394 "Cannot disassemble around the current " 395 "function without the process being stopped.\n"); 396 } else { 397 return llvm::createStringError(llvm::inconvertibleErrorCode(), 398 "Cannot disassemble around the current " 399 "PC without a selected frame: " 400 "no currently running process.\n"); 401 } 402 } 403 404 if (m_options.num_instructions == 0) { 405 // Disassembling at the PC always disassembles some number of 406 // instructions (not the whole function). 407 m_options.num_instructions = default_disasm_num_ins; 408 } 409 return std::vector<AddressRange>{{frame->GetFrameCodeAddress(), 0}}; 410 } 411 412 llvm::Expected<std::vector<AddressRange>> 413 CommandObjectDisassemble::GetStartEndAddressRanges() { 414 addr_t size = 0; 415 if (m_options.end_addr != LLDB_INVALID_ADDRESS) { 416 if (m_options.end_addr <= m_options.start_addr) { 417 return llvm::createStringError(llvm::inconvertibleErrorCode(), 418 "End address before start address."); 419 } 420 size = m_options.end_addr - m_options.start_addr; 421 } 422 return std::vector<AddressRange>{{Address(m_options.start_addr), size}}; 423 } 424 425 llvm::Expected<std::vector<AddressRange>> 426 CommandObjectDisassemble::GetRangesForSelectedMode( 427 CommandReturnObject &result) { 428 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) 429 return CommandObjectDisassemble::GetContainingAddressRanges(); 430 if (m_options.current_function) 431 return CommandObjectDisassemble::GetCurrentFunctionRanges(); 432 if (m_options.frame_line) 433 return CommandObjectDisassemble::GetCurrentLineRanges(); 434 if (!m_options.func_name.empty()) 435 return CommandObjectDisassemble::GetNameRanges(result); 436 if (m_options.start_addr != LLDB_INVALID_ADDRESS) 437 return CommandObjectDisassemble::GetStartEndAddressRanges(); 438 return CommandObjectDisassemble::GetPCRanges(); 439 } 440 441 bool CommandObjectDisassemble::DoExecute(Args &command, 442 CommandReturnObject &result) { 443 Target *target = &GetSelectedTarget(); 444 445 if (!m_options.arch.IsValid()) 446 m_options.arch = target->GetArchitecture(); 447 448 if (!m_options.arch.IsValid()) { 449 result.AppendError( 450 "use the --arch option or set the target architecture to disassemble"); 451 return false; 452 } 453 454 const char *plugin_name = m_options.GetPluginName(); 455 const char *flavor_string = m_options.GetFlavorString(); 456 457 DisassemblerSP disassembler = 458 Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); 459 460 if (!disassembler) { 461 if (plugin_name) { 462 result.AppendErrorWithFormat( 463 "Unable to find Disassembler plug-in named '%s' that supports the " 464 "'%s' architecture.\n", 465 plugin_name, m_options.arch.GetArchitectureName()); 466 } else 467 result.AppendErrorWithFormat( 468 "Unable to find Disassembler plug-in for the '%s' architecture.\n", 469 m_options.arch.GetArchitectureName()); 470 return false; 471 } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec( 472 m_options.arch, flavor_string)) 473 result.AppendWarningWithFormat( 474 "invalid disassembler flavor \"%s\", using default.\n", flavor_string); 475 476 result.SetStatus(eReturnStatusSuccessFinishResult); 477 478 if (!command.empty()) { 479 result.AppendErrorWithFormat( 480 "\"disassemble\" arguments are specified as options.\n"); 481 const int terminal_width = 482 GetCommandInterpreter().GetDebugger().GetTerminalWidth(); 483 GetOptions()->GenerateOptionUsage(result.GetErrorStream(), *this, 484 terminal_width); 485 return false; 486 } 487 488 if (m_options.show_mixed && m_options.num_lines_context == 0) 489 m_options.num_lines_context = 2; 490 491 // Always show the PC in the disassembly 492 uint32_t options = Disassembler::eOptionMarkPCAddress; 493 494 // Mark the source line for the current PC only if we are doing mixed source 495 // and assembly 496 if (m_options.show_mixed) 497 options |= Disassembler::eOptionMarkPCSourceLine; 498 499 if (m_options.show_bytes) 500 options |= Disassembler::eOptionShowBytes; 501 502 if (m_options.show_control_flow_kind) 503 options |= Disassembler::eOptionShowControlFlowKind; 504 505 if (m_options.raw) 506 options |= Disassembler::eOptionRawOuput; 507 508 llvm::Expected<std::vector<AddressRange>> ranges = 509 GetRangesForSelectedMode(result); 510 if (!ranges) { 511 result.AppendError(toString(ranges.takeError())); 512 return result.Succeeded(); 513 } 514 515 bool print_sc_header = ranges->size() > 1; 516 for (AddressRange cur_range : *ranges) { 517 Disassembler::Limit limit; 518 if (m_options.num_instructions == 0) { 519 limit = {Disassembler::Limit::Bytes, cur_range.GetByteSize()}; 520 if (limit.value == 0) 521 limit.value = default_disasm_byte_size; 522 } else { 523 limit = {Disassembler::Limit::Instructions, m_options.num_instructions}; 524 } 525 if (Disassembler::Disassemble( 526 GetDebugger(), m_options.arch, plugin_name, flavor_string, 527 m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed, 528 m_options.show_mixed ? m_options.num_lines_context : 0, options, 529 result.GetOutputStream())) { 530 result.SetStatus(eReturnStatusSuccessFinishResult); 531 } else { 532 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) { 533 result.AppendErrorWithFormat( 534 "Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", 535 m_options.symbol_containing_addr); 536 } else { 537 result.AppendErrorWithFormat( 538 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", 539 cur_range.GetBaseAddress().GetLoadAddress(target)); 540 } 541 } 542 if (print_sc_header) 543 result.GetOutputStream() << "\n"; 544 } 545 546 return result.Succeeded(); 547 } 548