1 //===-- Disassembler.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 "lldb/Core/Disassembler.h" 11 12 #include "lldb/Core/AddressRange.h" // for AddressRange 13 #include "lldb/Core/Debugger.h" 14 #include "lldb/Core/EmulateInstruction.h" 15 #include "lldb/Core/Mangled.h" // for Mangled, Mangled... 16 #include "lldb/Core/Module.h" 17 #include "lldb/Core/ModuleList.h" // for ModuleList 18 #include "lldb/Core/PluginManager.h" 19 #include "lldb/Core/SourceManager.h" // for SourceManager 20 #include "lldb/Host/FileSystem.h" 21 #include "lldb/Interpreter/OptionValue.h" 22 #include "lldb/Interpreter/OptionValueArray.h" 23 #include "lldb/Interpreter/OptionValueDictionary.h" 24 #include "lldb/Interpreter/OptionValueRegex.h" 25 #include "lldb/Interpreter/OptionValueString.h" 26 #include "lldb/Interpreter/OptionValueUInt64.h" 27 #include "lldb/Symbol/Function.h" 28 #include "lldb/Symbol/Symbol.h" // for Symbol 29 #include "lldb/Symbol/SymbolContext.h" // for SymbolContext 30 #include "lldb/Target/ExecutionContext.h" 31 #include "lldb/Target/SectionLoadList.h" 32 #include "lldb/Target/StackFrame.h" 33 #include "lldb/Target/Target.h" 34 #include "lldb/Target/Thread.h" // for Thread 35 #include "lldb/Utility/DataBufferHeap.h" 36 #include "lldb/Utility/DataExtractor.h" 37 #include "lldb/Utility/RegularExpression.h" 38 #include "lldb/Utility/Status.h" 39 #include "lldb/Utility/Stream.h" // for Stream 40 #include "lldb/Utility/StreamString.h" // for StreamString 41 #include "lldb/Utility/Timer.h" 42 #include "lldb/lldb-private-enumerations.h" // for InstructionType:... 43 #include "lldb/lldb-private-interfaces.h" // for DisassemblerCrea... 44 #include "lldb/lldb-private-types.h" // for RegisterInfo 45 #include "llvm/ADT/Triple.h" // for Triple, Triple::... 46 #include "llvm/Support/Compiler.h" // for LLVM_PRETTY_FUNC... 47 48 #include <cstdint> // for uint32_t, UINT32... 49 #include <cstring> 50 #include <utility> // for pair 51 52 #include <assert.h> // for assert 53 54 #define DEFAULT_DISASM_BYTE_SIZE 32 55 56 using namespace lldb; 57 using namespace lldb_private; 58 59 DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, 60 const char *flavor, 61 const char *plugin_name) { 62 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 63 Timer scoped_timer(func_cat, 64 "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 65 arch.GetArchitectureName(), plugin_name); 66 67 DisassemblerCreateInstance create_callback = nullptr; 68 69 if (plugin_name) { 70 ConstString const_plugin_name(plugin_name); 71 create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName( 72 const_plugin_name); 73 if (create_callback) { 74 DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 75 76 if (disassembler_sp) 77 return disassembler_sp; 78 } 79 } else { 80 for (uint32_t idx = 0; 81 (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( 82 idx)) != nullptr; 83 ++idx) { 84 DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 85 86 if (disassembler_sp) 87 return disassembler_sp; 88 } 89 } 90 return DisassemblerSP(); 91 } 92 93 DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp, 94 const ArchSpec &arch, 95 const char *flavor, 96 const char *plugin_name) { 97 if (target_sp && flavor == nullptr) { 98 // FIXME - we don't have the mechanism in place to do per-architecture 99 // settings. But since we know that for now we only support flavors on x86 100 // & x86_64, 101 if (arch.GetTriple().getArch() == llvm::Triple::x86 || 102 arch.GetTriple().getArch() == llvm::Triple::x86_64) 103 flavor = target_sp->GetDisassemblyFlavor(); 104 } 105 return FindPlugin(arch, flavor, plugin_name); 106 } 107 108 static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr, 109 Address &resolved_addr) { 110 if (!addr.IsSectionOffset()) { 111 // If we weren't passed in a section offset address range, try and resolve 112 // it to something 113 Target *target = exe_ctx.GetTargetPtr(); 114 if (target) { 115 bool is_resolved = 116 target->GetSectionLoadList().IsEmpty() ? 117 target->GetImages().ResolveFileAddress(addr.GetOffset(), 118 resolved_addr) : 119 target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(), 120 resolved_addr); 121 122 // We weren't able to resolve the address, just treat it as a raw address 123 if (is_resolved && resolved_addr.IsValid()) 124 return; 125 } 126 } 127 resolved_addr = addr; 128 } 129 130 size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 131 const char *plugin_name, const char *flavor, 132 const ExecutionContext &exe_ctx, 133 SymbolContextList &sc_list, 134 uint32_t num_instructions, 135 bool mixed_source_and_assembly, 136 uint32_t num_mixed_context_lines, 137 uint32_t options, Stream &strm) { 138 size_t success_count = 0; 139 const size_t count = sc_list.GetSize(); 140 SymbolContext sc; 141 AddressRange range; 142 const uint32_t scope = 143 eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 144 const bool use_inline_block_range = true; 145 for (size_t i = 0; i < count; ++i) { 146 if (!sc_list.GetContextAtIndex(i, sc)) 147 break; 148 for (uint32_t range_idx = 0; 149 sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); 150 ++range_idx) { 151 if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 152 num_instructions, mixed_source_and_assembly, 153 num_mixed_context_lines, options, strm)) { 154 ++success_count; 155 strm.EOL(); 156 } 157 } 158 } 159 return success_count; 160 } 161 162 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 163 const char *plugin_name, const char *flavor, 164 const ExecutionContext &exe_ctx, 165 const ConstString &name, Module *module, 166 uint32_t num_instructions, 167 bool mixed_source_and_assembly, 168 uint32_t num_mixed_context_lines, 169 uint32_t options, Stream &strm) { 170 SymbolContextList sc_list; 171 if (name) { 172 const bool include_symbols = true; 173 const bool include_inlines = true; 174 if (module) { 175 module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, 176 include_symbols, include_inlines, true, sc_list); 177 } else if (exe_ctx.GetTargetPtr()) { 178 exe_ctx.GetTargetPtr()->GetImages().FindFunctions( 179 name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, 180 sc_list); 181 } 182 } 183 184 if (sc_list.GetSize()) { 185 return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, 186 num_instructions, mixed_source_and_assembly, 187 num_mixed_context_lines, options, strm); 188 } 189 return false; 190 } 191 192 lldb::DisassemblerSP Disassembler::DisassembleRange( 193 const ArchSpec &arch, const char *plugin_name, const char *flavor, 194 const ExecutionContext &exe_ctx, const AddressRange &range, 195 bool prefer_file_cache) { 196 lldb::DisassemblerSP disasm_sp; 197 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { 198 disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, 199 flavor, plugin_name); 200 201 if (disasm_sp) { 202 size_t bytes_disassembled = disasm_sp->ParseInstructions( 203 &exe_ctx, range, nullptr, prefer_file_cache); 204 if (bytes_disassembled == 0) 205 disasm_sp.reset(); 206 } 207 } 208 return disasm_sp; 209 } 210 211 lldb::DisassemblerSP 212 Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 213 const char *flavor, const Address &start, 214 const void *src, size_t src_len, 215 uint32_t num_instructions, bool data_from_file) { 216 lldb::DisassemblerSP disasm_sp; 217 218 if (src) { 219 disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); 220 221 if (disasm_sp) { 222 DataExtractor data(src, src_len, arch.GetByteOrder(), 223 arch.GetAddressByteSize()); 224 225 (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, 226 false, data_from_file); 227 } 228 } 229 230 return disasm_sp; 231 } 232 233 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 234 const char *plugin_name, const char *flavor, 235 const ExecutionContext &exe_ctx, 236 const AddressRange &disasm_range, 237 uint32_t num_instructions, 238 bool mixed_source_and_assembly, 239 uint32_t num_mixed_context_lines, 240 uint32_t options, Stream &strm) { 241 if (disasm_range.GetByteSize()) { 242 lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 243 exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 244 245 if (disasm_sp) { 246 AddressRange range; 247 ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), 248 range.GetBaseAddress()); 249 range.SetByteSize(disasm_range.GetByteSize()); 250 const bool prefer_file_cache = false; 251 size_t bytes_disassembled = disasm_sp->ParseInstructions( 252 &exe_ctx, range, &strm, prefer_file_cache); 253 if (bytes_disassembled == 0) 254 return false; 255 256 return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 257 num_instructions, mixed_source_and_assembly, 258 num_mixed_context_lines, options, strm); 259 } 260 } 261 return false; 262 } 263 264 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 265 const char *plugin_name, const char *flavor, 266 const ExecutionContext &exe_ctx, 267 const Address &start_address, 268 uint32_t num_instructions, 269 bool mixed_source_and_assembly, 270 uint32_t num_mixed_context_lines, 271 uint32_t options, Stream &strm) { 272 if (num_instructions > 0) { 273 lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 274 exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 275 if (disasm_sp) { 276 Address addr; 277 ResolveAddress(exe_ctx, start_address, addr); 278 const bool prefer_file_cache = false; 279 size_t bytes_disassembled = disasm_sp->ParseInstructions( 280 &exe_ctx, addr, num_instructions, prefer_file_cache); 281 if (bytes_disassembled == 0) 282 return false; 283 return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 284 num_instructions, mixed_source_and_assembly, 285 num_mixed_context_lines, options, strm); 286 } 287 } 288 return false; 289 } 290 291 Disassembler::SourceLine 292 Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 293 SourceLine decl_line; 294 if (sc.function && sc.line_entry.IsValid()) { 295 LineEntry prologue_end_line = sc.line_entry; 296 FileSpec func_decl_file; 297 uint32_t func_decl_line; 298 sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 299 if (func_decl_file == prologue_end_line.file || 300 func_decl_file == prologue_end_line.original_file) { 301 decl_line.file = func_decl_file; 302 decl_line.line = func_decl_line; 303 // TODO do we care about column on these entries? If so, we need to 304 // plumb that through GetStartLineSourceInfo. 305 decl_line.column = 0; 306 } 307 } 308 return decl_line; 309 } 310 311 void Disassembler::AddLineToSourceLineTables( 312 SourceLine &line, 313 std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 314 if (line.IsValid()) { 315 auto source_lines_seen_pos = source_lines_seen.find(line.file); 316 if (source_lines_seen_pos == source_lines_seen.end()) { 317 std::set<uint32_t> lines; 318 lines.insert(line.line); 319 source_lines_seen.emplace(line.file, lines); 320 } else { 321 source_lines_seen_pos->second.insert(line.line); 322 } 323 } 324 } 325 326 bool Disassembler::ElideMixedSourceAndDisassemblyLine( 327 const ExecutionContext &exe_ctx, const SymbolContext &sc, 328 SourceLine &line) { 329 330 // TODO: should we also check target.process.thread.step-avoid-libraries ? 331 332 const RegularExpression *avoid_regex = nullptr; 333 334 // Skip any line #0 entries - they are implementation details 335 if (line.line == 0) 336 return false; 337 338 ThreadSP thread_sp = exe_ctx.GetThreadSP(); 339 if (thread_sp) { 340 avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 341 } else { 342 TargetSP target_sp = exe_ctx.GetTargetSP(); 343 if (target_sp) { 344 Status error; 345 OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 346 &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 347 if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 348 OptionValueRegex *re = value_sp->GetAsRegex(); 349 if (re) { 350 avoid_regex = re->GetCurrentValue(); 351 } 352 } 353 } 354 } 355 if (avoid_regex && sc.symbol != nullptr) { 356 const char *function_name = 357 sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 358 .GetCString(); 359 if (function_name) { 360 RegularExpression::Match regex_match(1); 361 if (avoid_regex->Execute(function_name, ®ex_match)) { 362 // skip this source line 363 return true; 364 } 365 } 366 } 367 // don't skip this source line 368 return false; 369 } 370 371 bool Disassembler::PrintInstructions(Disassembler *disasm_ptr, 372 Debugger &debugger, const ArchSpec &arch, 373 const ExecutionContext &exe_ctx, 374 uint32_t num_instructions, 375 bool mixed_source_and_assembly, 376 uint32_t num_mixed_context_lines, 377 uint32_t options, Stream &strm) { 378 // We got some things disassembled... 379 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); 380 381 if (num_instructions > 0 && num_instructions < num_instructions_found) 382 num_instructions_found = num_instructions; 383 384 const uint32_t max_opcode_byte_size = 385 disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize(); 386 SymbolContext sc; 387 SymbolContext prev_sc; 388 AddressRange current_source_line_range; 389 const Address *pc_addr_ptr = nullptr; 390 StackFrame *frame = exe_ctx.GetFramePtr(); 391 392 TargetSP target_sp(exe_ctx.GetTargetSP()); 393 SourceManager &source_manager = 394 target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 395 396 if (frame) { 397 pc_addr_ptr = &frame->GetFrameCodeAddress(); 398 } 399 const uint32_t scope = 400 eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 401 const bool use_inline_block_range = false; 402 403 const FormatEntity::Entry *disassembly_format = nullptr; 404 FormatEntity::Entry format; 405 if (exe_ctx.HasTargetScope()) { 406 disassembly_format = 407 exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 408 } else { 409 FormatEntity::Parse("${addr}: ", format); 410 disassembly_format = &format; 411 } 412 413 // First pass: step through the list of instructions, find how long the 414 // initial addresses strings are, insert padding in the second pass so the 415 // opcodes all line up nicely. 416 417 // Also build up the source line mapping if this is mixed source & assembly 418 // mode. Calculate the source line for each assembly instruction (eliding 419 // inlined functions which the user wants to skip). 420 421 std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 422 Symbol *previous_symbol = nullptr; 423 424 size_t address_text_size = 0; 425 for (size_t i = 0; i < num_instructions_found; ++i) { 426 Instruction *inst = 427 disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 428 if (inst) { 429 const Address &addr = inst->GetAddress(); 430 ModuleSP module_sp(addr.GetModule()); 431 if (module_sp) { 432 const uint32_t resolve_mask = eSymbolContextFunction | 433 eSymbolContextSymbol | 434 eSymbolContextLineEntry; 435 uint32_t resolved_mask = 436 module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 437 if (resolved_mask) { 438 StreamString strmstr; 439 Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 440 &exe_ctx, &addr, strmstr); 441 size_t cur_line = strmstr.GetSizeOfLastLine(); 442 if (cur_line > address_text_size) 443 address_text_size = cur_line; 444 445 // Add entries to our "source_lines_seen" map+set which list which 446 // sources lines occur in this disassembly session. We will print 447 // lines of context around a source line, but we don't want to print 448 // a source line that has a line table entry of its own - we'll leave 449 // that source line to be printed when it actually occurs in the 450 // disassembly. 451 452 if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 453 if (sc.symbol != previous_symbol) { 454 SourceLine decl_line = GetFunctionDeclLineEntry(sc); 455 if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) == 456 false) 457 AddLineToSourceLineTables(decl_line, source_lines_seen); 458 } 459 if (sc.line_entry.IsValid()) { 460 SourceLine this_line; 461 this_line.file = sc.line_entry.file; 462 this_line.line = sc.line_entry.line; 463 this_line.column = sc.line_entry.column; 464 if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) == 465 false) 466 AddLineToSourceLineTables(this_line, source_lines_seen); 467 } 468 } 469 } 470 sc.Clear(false); 471 } 472 } 473 } 474 475 previous_symbol = nullptr; 476 SourceLine previous_line; 477 for (size_t i = 0; i < num_instructions_found; ++i) { 478 Instruction *inst = 479 disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 480 481 if (inst) { 482 const Address &addr = inst->GetAddress(); 483 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 484 SourceLinesToDisplay source_lines_to_display; 485 486 prev_sc = sc; 487 488 ModuleSP module_sp(addr.GetModule()); 489 if (module_sp) { 490 uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 491 addr, eSymbolContextEverything, sc); 492 if (resolved_mask) { 493 if (mixed_source_and_assembly) { 494 495 // If we've started a new function (non-inlined), print all of the 496 // source lines from the function declaration until the first line 497 // table entry - typically the opening curly brace of the function. 498 if (previous_symbol != sc.symbol) { 499 // The default disassembly format puts an extra blank line 500 // between functions - so when we're displaying the source 501 // context for a function, we don't want to add a blank line 502 // after the source context or we'll end up with two of them. 503 if (previous_symbol != nullptr) 504 source_lines_to_display.print_source_context_end_eol = false; 505 506 previous_symbol = sc.symbol; 507 if (sc.function && sc.line_entry.IsValid()) { 508 LineEntry prologue_end_line = sc.line_entry; 509 if (ElideMixedSourceAndDisassemblyLine( 510 exe_ctx, sc, prologue_end_line) == false) { 511 FileSpec func_decl_file; 512 uint32_t func_decl_line; 513 sc.function->GetStartLineSourceInfo(func_decl_file, 514 func_decl_line); 515 if (func_decl_file == prologue_end_line.file || 516 func_decl_file == prologue_end_line.original_file) { 517 // Add all the lines between the function declaration and 518 // the first non-prologue source line to the list of lines 519 // to print. 520 for (uint32_t lineno = func_decl_line; 521 lineno <= prologue_end_line.line; lineno++) { 522 SourceLine this_line; 523 this_line.file = func_decl_file; 524 this_line.line = lineno; 525 source_lines_to_display.lines.push_back(this_line); 526 } 527 // Mark the last line as the "current" one. Usually this 528 // is the open curly brace. 529 if (source_lines_to_display.lines.size() > 0) 530 source_lines_to_display.current_source_line = 531 source_lines_to_display.lines.size() - 1; 532 } 533 } 534 } 535 sc.GetAddressRange(scope, 0, use_inline_block_range, 536 current_source_line_range); 537 } 538 539 // If we've left a previous source line's address range, print a 540 // new source line 541 if (!current_source_line_range.ContainsFileAddress(addr)) { 542 sc.GetAddressRange(scope, 0, use_inline_block_range, 543 current_source_line_range); 544 545 if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 546 SourceLine this_line; 547 this_line.file = sc.line_entry.file; 548 this_line.line = sc.line_entry.line; 549 550 if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 551 this_line) == false) { 552 // Only print this source line if it is different from the 553 // last source line we printed. There may have been inlined 554 // functions between these lines that we elided, resulting in 555 // the same line being printed twice in a row for a 556 // contiguous block of assembly instructions. 557 if (this_line != previous_line) { 558 559 std::vector<uint32_t> previous_lines; 560 for (uint32_t i = 0; 561 i < num_mixed_context_lines && 562 (this_line.line - num_mixed_context_lines) > 0; 563 i++) { 564 uint32_t line = 565 this_line.line - num_mixed_context_lines + i; 566 auto pos = source_lines_seen.find(this_line.file); 567 if (pos != source_lines_seen.end()) { 568 if (pos->second.count(line) == 1) { 569 previous_lines.clear(); 570 } else { 571 previous_lines.push_back(line); 572 } 573 } 574 } 575 for (size_t i = 0; i < previous_lines.size(); i++) { 576 SourceLine previous_line; 577 previous_line.file = this_line.file; 578 previous_line.line = previous_lines[i]; 579 auto pos = source_lines_seen.find(previous_line.file); 580 if (pos != source_lines_seen.end()) { 581 pos->second.insert(previous_line.line); 582 } 583 source_lines_to_display.lines.push_back(previous_line); 584 } 585 586 source_lines_to_display.lines.push_back(this_line); 587 source_lines_to_display.current_source_line = 588 source_lines_to_display.lines.size() - 1; 589 590 for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 591 SourceLine next_line; 592 next_line.file = this_line.file; 593 next_line.line = this_line.line + i + 1; 594 auto pos = source_lines_seen.find(next_line.file); 595 if (pos != source_lines_seen.end()) { 596 if (pos->second.count(next_line.line) == 1) 597 break; 598 pos->second.insert(next_line.line); 599 } 600 source_lines_to_display.lines.push_back(next_line); 601 } 602 } 603 previous_line = this_line; 604 } 605 } 606 } 607 } 608 } else { 609 sc.Clear(true); 610 } 611 } 612 613 if (source_lines_to_display.lines.size() > 0) { 614 strm.EOL(); 615 for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 616 idx++) { 617 SourceLine ln = source_lines_to_display.lines[idx]; 618 const char *line_highlight = ""; 619 if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 620 line_highlight = "->"; 621 } else if (idx == source_lines_to_display.current_source_line) { 622 line_highlight = "**"; 623 } 624 source_manager.DisplaySourceLinesWithLineNumbers( 625 ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); 626 } 627 if (source_lines_to_display.print_source_context_end_eol) 628 strm.EOL(); 629 } 630 631 const bool show_bytes = (options & eOptionShowBytes) != 0; 632 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, 633 &prev_sc, nullptr, address_text_size); 634 strm.EOL(); 635 } else { 636 break; 637 } 638 } 639 640 return true; 641 } 642 643 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 644 const char *plugin_name, const char *flavor, 645 const ExecutionContext &exe_ctx, 646 uint32_t num_instructions, 647 bool mixed_source_and_assembly, 648 uint32_t num_mixed_context_lines, 649 uint32_t options, Stream &strm) { 650 AddressRange range; 651 StackFrame *frame = exe_ctx.GetFramePtr(); 652 if (frame) { 653 SymbolContext sc( 654 frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 655 if (sc.function) { 656 range = sc.function->GetAddressRange(); 657 } else if (sc.symbol && sc.symbol->ValueIsAddress()) { 658 range.GetBaseAddress() = sc.symbol->GetAddressRef(); 659 range.SetByteSize(sc.symbol->GetByteSize()); 660 } else { 661 range.GetBaseAddress() = frame->GetFrameCodeAddress(); 662 } 663 664 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 665 range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 666 } 667 668 return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 669 num_instructions, mixed_source_and_assembly, 670 num_mixed_context_lines, options, strm); 671 } 672 673 Instruction::Instruction(const Address &address, AddressClass addr_class) 674 : m_address(address), m_address_class(addr_class), m_opcode(), 675 m_calculated_strings(false) {} 676 677 Instruction::~Instruction() = default; 678 679 AddressClass Instruction::GetAddressClass() { 680 if (m_address_class == AddressClass::eInvalid) 681 m_address_class = m_address.GetAddressClass(); 682 return m_address_class; 683 } 684 685 void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 686 bool show_address, bool show_bytes, 687 const ExecutionContext *exe_ctx, 688 const SymbolContext *sym_ctx, 689 const SymbolContext *prev_sym_ctx, 690 const FormatEntity::Entry *disassembly_addr_format, 691 size_t max_address_text_size) { 692 size_t opcode_column_width = 7; 693 const size_t operand_column_width = 25; 694 695 CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 696 697 StreamString ss; 698 699 if (show_address) { 700 Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 701 prev_sym_ctx, exe_ctx, &m_address, ss); 702 ss.FillLastLineToColumn(max_address_text_size, ' '); 703 } 704 705 if (show_bytes) { 706 if (m_opcode.GetType() == Opcode::eTypeBytes) { 707 // x86_64 and i386 are the only ones that use bytes right now so pad out 708 // the byte dump to be able to always show 15 bytes (3 chars each) plus a 709 // space 710 if (max_opcode_byte_size > 0) 711 m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 712 else 713 m_opcode.Dump(&ss, 15 * 3 + 1); 714 } else { 715 // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000 716 // (10 spaces) plus two for padding... 717 if (max_opcode_byte_size > 0) 718 m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 719 else 720 m_opcode.Dump(&ss, 12); 721 } 722 } 723 724 const size_t opcode_pos = ss.GetSizeOfLastLine(); 725 726 // The default opcode size of 7 characters is plenty for most architectures 727 // but some like arm can pull out the occasional vqrshrun.s16. We won't get 728 // consistent column spacing in these cases, unfortunately. 729 if (m_opcode_name.length() >= opcode_column_width) { 730 opcode_column_width = m_opcode_name.length() + 1; 731 } 732 733 ss.PutCString(m_opcode_name); 734 ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 735 ss.PutCString(m_mnemonics); 736 737 if (!m_comment.empty()) { 738 ss.FillLastLineToColumn( 739 opcode_pos + opcode_column_width + operand_column_width, ' '); 740 ss.PutCString(" ; "); 741 ss.PutCString(m_comment); 742 } 743 s->PutCString(ss.GetString()); 744 } 745 746 bool Instruction::DumpEmulation(const ArchSpec &arch) { 747 std::unique_ptr<EmulateInstruction> insn_emulator_ap( 748 EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 749 if (insn_emulator_ap) { 750 insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 751 return insn_emulator_ap->EvaluateInstruction(0); 752 } 753 754 return false; 755 } 756 757 bool Instruction::CanSetBreakpoint () { 758 return !HasDelaySlot(); 759 } 760 761 bool Instruction::HasDelaySlot() { 762 // Default is false. 763 return false; 764 } 765 766 OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 767 OptionValue::Type data_type) { 768 bool done = false; 769 char buffer[1024]; 770 771 auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type); 772 773 int idx = 0; 774 while (!done) { 775 if (!fgets(buffer, 1023, in_file)) { 776 out_stream->Printf( 777 "Instruction::ReadArray: Error reading file (fgets).\n"); 778 option_value_sp.reset(); 779 return option_value_sp; 780 } 781 782 std::string line(buffer); 783 784 size_t len = line.size(); 785 if (line[len - 1] == '\n') { 786 line[len - 1] = '\0'; 787 line.resize(len - 1); 788 } 789 790 if ((line.size() == 1) && line[0] == ']') { 791 done = true; 792 line.clear(); 793 } 794 795 if (!line.empty()) { 796 std::string value; 797 static RegularExpression g_reg_exp( 798 llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); 799 RegularExpression::Match regex_match(1); 800 bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); 801 if (reg_exp_success) 802 regex_match.GetMatchAtIndex(line.c_str(), 1, value); 803 else 804 value = line; 805 806 OptionValueSP data_value_sp; 807 switch (data_type) { 808 case OptionValue::eTypeUInt64: 809 data_value_sp = std::make_shared<OptionValueUInt64>(0, 0); 810 data_value_sp->SetValueFromString(value); 811 break; 812 // Other types can be added later as needed. 813 default: 814 data_value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 815 break; 816 } 817 818 option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 819 ++idx; 820 } 821 } 822 823 return option_value_sp; 824 } 825 826 OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 827 bool done = false; 828 char buffer[1024]; 829 830 auto option_value_sp = std::make_shared<OptionValueDictionary>(); 831 static ConstString encoding_key("data_encoding"); 832 OptionValue::Type data_type = OptionValue::eTypeInvalid; 833 834 while (!done) { 835 // Read the next line in the file 836 if (!fgets(buffer, 1023, in_file)) { 837 out_stream->Printf( 838 "Instruction::ReadDictionary: Error reading file (fgets).\n"); 839 option_value_sp.reset(); 840 return option_value_sp; 841 } 842 843 // Check to see if the line contains the end-of-dictionary marker ("}") 844 std::string line(buffer); 845 846 size_t len = line.size(); 847 if (line[len - 1] == '\n') { 848 line[len - 1] = '\0'; 849 line.resize(len - 1); 850 } 851 852 if ((line.size() == 1) && (line[0] == '}')) { 853 done = true; 854 line.clear(); 855 } 856 857 // Try to find a key-value pair in the current line and add it to the 858 // dictionary. 859 if (!line.empty()) { 860 static RegularExpression g_reg_exp(llvm::StringRef( 861 "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); 862 RegularExpression::Match regex_match(2); 863 864 bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); 865 std::string key; 866 std::string value; 867 if (reg_exp_success) { 868 regex_match.GetMatchAtIndex(line.c_str(), 1, key); 869 regex_match.GetMatchAtIndex(line.c_str(), 2, value); 870 } else { 871 out_stream->Printf("Instruction::ReadDictionary: Failure executing " 872 "regular expression.\n"); 873 option_value_sp.reset(); 874 return option_value_sp; 875 } 876 877 ConstString const_key(key.c_str()); 878 // Check value to see if it's the start of an array or dictionary. 879 880 lldb::OptionValueSP value_sp; 881 assert(value.empty() == false); 882 assert(key.empty() == false); 883 884 if (value[0] == '{') { 885 assert(value.size() == 1); 886 // value is a dictionary 887 value_sp = ReadDictionary(in_file, out_stream); 888 if (!value_sp) { 889 option_value_sp.reset(); 890 return option_value_sp; 891 } 892 } else if (value[0] == '[') { 893 assert(value.size() == 1); 894 // value is an array 895 value_sp = ReadArray(in_file, out_stream, data_type); 896 if (!value_sp) { 897 option_value_sp.reset(); 898 return option_value_sp; 899 } 900 // We've used the data_type to read an array; re-set the type to 901 // Invalid 902 data_type = OptionValue::eTypeInvalid; 903 } else if ((value[0] == '0') && (value[1] == 'x')) { 904 value_sp = std::make_shared<OptionValueUInt64>(0, 0); 905 value_sp->SetValueFromString(value); 906 } else { 907 size_t len = value.size(); 908 if ((value[0] == '"') && (value[len - 1] == '"')) 909 value = value.substr(1, len - 2); 910 value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 911 } 912 913 if (const_key == encoding_key) { 914 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 915 // indicating the 916 // data type of an upcoming array (usually the next bit of data to be 917 // read in). 918 if (strcmp(value.c_str(), "uint32_t") == 0) 919 data_type = OptionValue::eTypeUInt64; 920 } else 921 option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 922 false); 923 } 924 } 925 926 return option_value_sp; 927 } 928 929 bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 930 if (!out_stream) 931 return false; 932 933 if (!file_name) { 934 out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 935 return false; 936 } 937 FILE *test_file = FileSystem::Fopen(file_name, "r"); 938 if (!test_file) { 939 out_stream->Printf( 940 "Instruction::TestEmulation: Attempt to open test file failed."); 941 return false; 942 } 943 944 char buffer[256]; 945 if (!fgets(buffer, 255, test_file)) { 946 out_stream->Printf( 947 "Instruction::TestEmulation: Error reading first line of test file.\n"); 948 fclose(test_file); 949 return false; 950 } 951 952 if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 953 out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 954 "emulation state dictionary\n"); 955 fclose(test_file); 956 return false; 957 } 958 959 // Read all the test information from the test file into an 960 // OptionValueDictionary. 961 962 OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 963 if (!data_dictionary_sp) { 964 out_stream->Printf( 965 "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 966 fclose(test_file); 967 return false; 968 } 969 970 fclose(test_file); 971 972 OptionValueDictionary *data_dictionary = 973 data_dictionary_sp->GetAsDictionary(); 974 static ConstString description_key("assembly_string"); 975 static ConstString triple_key("triple"); 976 977 OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 978 979 if (!value_sp) { 980 out_stream->Printf("Instruction::TestEmulation: Test file does not " 981 "contain description string.\n"); 982 return false; 983 } 984 985 SetDescription(value_sp->GetStringValue()); 986 987 value_sp = data_dictionary->GetValueForKey(triple_key); 988 if (!value_sp) { 989 out_stream->Printf( 990 "Instruction::TestEmulation: Test file does not contain triple.\n"); 991 return false; 992 } 993 994 ArchSpec arch; 995 arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 996 997 bool success = false; 998 std::unique_ptr<EmulateInstruction> insn_emulator_ap( 999 EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1000 if (insn_emulator_ap) 1001 success = 1002 insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary); 1003 1004 if (success) 1005 out_stream->Printf("Emulation test succeeded."); 1006 else 1007 out_stream->Printf("Emulation test failed."); 1008 1009 return success; 1010 } 1011 1012 bool Instruction::Emulate( 1013 const ArchSpec &arch, uint32_t evaluate_options, void *baton, 1014 EmulateInstruction::ReadMemoryCallback read_mem_callback, 1015 EmulateInstruction::WriteMemoryCallback write_mem_callback, 1016 EmulateInstruction::ReadRegisterCallback read_reg_callback, 1017 EmulateInstruction::WriteRegisterCallback write_reg_callback) { 1018 std::unique_ptr<EmulateInstruction> insn_emulator_ap( 1019 EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1020 if (insn_emulator_ap) { 1021 insn_emulator_ap->SetBaton(baton); 1022 insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, 1023 read_reg_callback, write_reg_callback); 1024 insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 1025 return insn_emulator_ap->EvaluateInstruction(evaluate_options); 1026 } 1027 1028 return false; 1029 } 1030 1031 uint32_t Instruction::GetData(DataExtractor &data) { 1032 return m_opcode.GetData(data); 1033 } 1034 1035 InstructionList::InstructionList() : m_instructions() {} 1036 1037 InstructionList::~InstructionList() = default; 1038 1039 size_t InstructionList::GetSize() const { return m_instructions.size(); } 1040 1041 uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 1042 uint32_t max_inst_size = 0; 1043 collection::const_iterator pos, end; 1044 for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 1045 ++pos) { 1046 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 1047 if (max_inst_size < inst_size) 1048 max_inst_size = inst_size; 1049 } 1050 return max_inst_size; 1051 } 1052 1053 InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 1054 InstructionSP inst_sp; 1055 if (idx < m_instructions.size()) 1056 inst_sp = m_instructions[idx]; 1057 return inst_sp; 1058 } 1059 1060 void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 1061 const ExecutionContext *exe_ctx) { 1062 const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 1063 collection::const_iterator pos, begin, end; 1064 1065 const FormatEntity::Entry *disassembly_format = nullptr; 1066 FormatEntity::Entry format; 1067 if (exe_ctx && exe_ctx->HasTargetScope()) { 1068 disassembly_format = 1069 exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1070 } else { 1071 FormatEntity::Parse("${addr}: ", format); 1072 disassembly_format = &format; 1073 } 1074 1075 for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 1076 pos != end; ++pos) { 1077 if (pos != begin) 1078 s->EOL(); 1079 (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, 1080 nullptr, nullptr, disassembly_format, 0); 1081 } 1082 } 1083 1084 void InstructionList::Clear() { m_instructions.clear(); } 1085 1086 void InstructionList::Append(lldb::InstructionSP &inst_sp) { 1087 if (inst_sp) 1088 m_instructions.push_back(inst_sp); 1089 } 1090 1091 uint32_t 1092 InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 1093 Target &target) const { 1094 size_t num_instructions = m_instructions.size(); 1095 1096 uint32_t next_branch = UINT32_MAX; 1097 size_t i; 1098 for (i = start; i < num_instructions; i++) { 1099 if (m_instructions[i]->DoesBranch()) { 1100 next_branch = i; 1101 break; 1102 } 1103 } 1104 1105 // Hexagon needs the first instruction of the packet with the branch. Go 1106 // backwards until we find an instruction marked end-of-packet, or until we 1107 // hit start. 1108 if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) { 1109 // If we didn't find a branch, find the last packet start. 1110 if (next_branch == UINT32_MAX) { 1111 i = num_instructions - 1; 1112 } 1113 1114 while (i > start) { 1115 --i; 1116 1117 Status error; 1118 uint32_t inst_bytes; 1119 bool prefer_file_cache = false; // Read from process if process is running 1120 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1121 target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache, 1122 &inst_bytes, sizeof(inst_bytes), error, &load_addr); 1123 // If we have an error reading memory, return start 1124 if (!error.Success()) 1125 return start; 1126 // check if this is the last instruction in a packet bits 15:14 will be 1127 // 11b or 00b for a duplex 1128 if (((inst_bytes & 0xC000) == 0xC000) || 1129 ((inst_bytes & 0xC000) == 0x0000)) { 1130 // instruction after this should be the start of next packet 1131 next_branch = i + 1; 1132 break; 1133 } 1134 } 1135 1136 if (next_branch == UINT32_MAX) { 1137 // We couldn't find the previous packet, so return start 1138 next_branch = start; 1139 } 1140 } 1141 return next_branch; 1142 } 1143 1144 uint32_t 1145 InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1146 size_t num_instructions = m_instructions.size(); 1147 uint32_t index = UINT32_MAX; 1148 for (size_t i = 0; i < num_instructions; i++) { 1149 if (m_instructions[i]->GetAddress() == address) { 1150 index = i; 1151 break; 1152 } 1153 } 1154 return index; 1155 } 1156 1157 uint32_t 1158 InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1159 Target &target) { 1160 Address address; 1161 address.SetLoadAddress(load_addr, &target); 1162 return GetIndexOfInstructionAtAddress(address); 1163 } 1164 1165 size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 1166 const AddressRange &range, 1167 Stream *error_strm_ptr, 1168 bool prefer_file_cache) { 1169 if (exe_ctx) { 1170 Target *target = exe_ctx->GetTargetPtr(); 1171 const addr_t byte_size = range.GetByteSize(); 1172 if (target == nullptr || byte_size == 0 || 1173 !range.GetBaseAddress().IsValid()) 1174 return 0; 1175 1176 auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 1177 1178 Status error; 1179 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1180 const size_t bytes_read = target->ReadMemory( 1181 range.GetBaseAddress(), prefer_file_cache, data_sp->GetBytes(), 1182 data_sp->GetByteSize(), error, &load_addr); 1183 1184 if (bytes_read > 0) { 1185 if (bytes_read != data_sp->GetByteSize()) 1186 data_sp->SetByteSize(bytes_read); 1187 DataExtractor data(data_sp, m_arch.GetByteOrder(), 1188 m_arch.GetAddressByteSize()); 1189 const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1190 return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, 1191 false, data_from_file); 1192 } else if (error_strm_ptr) { 1193 const char *error_cstr = error.AsCString(); 1194 if (error_cstr) { 1195 error_strm_ptr->Printf("error: %s\n", error_cstr); 1196 } 1197 } 1198 } else if (error_strm_ptr) { 1199 error_strm_ptr->PutCString("error: invalid execution context\n"); 1200 } 1201 return 0; 1202 } 1203 1204 size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 1205 const Address &start, 1206 uint32_t num_instructions, 1207 bool prefer_file_cache) { 1208 m_instruction_list.Clear(); 1209 1210 if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) 1211 return 0; 1212 1213 Target *target = exe_ctx->GetTargetPtr(); 1214 // Calculate the max buffer size we will need in order to disassemble 1215 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 1216 1217 if (target == nullptr || byte_size == 0) 1218 return 0; 1219 1220 DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); 1221 DataBufferSP data_sp(heap_buffer); 1222 1223 Status error; 1224 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1225 const size_t bytes_read = 1226 target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(), 1227 byte_size, error, &load_addr); 1228 1229 const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1230 1231 if (bytes_read == 0) 1232 return 0; 1233 DataExtractor data(data_sp, m_arch.GetByteOrder(), 1234 m_arch.GetAddressByteSize()); 1235 1236 const bool append_instructions = true; 1237 DecodeInstructions(start, data, 0, num_instructions, append_instructions, 1238 data_from_file); 1239 1240 return m_instruction_list.GetSize(); 1241 } 1242 1243 //---------------------------------------------------------------------- 1244 // Disassembler copy constructor 1245 //---------------------------------------------------------------------- 1246 Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1247 : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1248 m_flavor() { 1249 if (flavor == nullptr) 1250 m_flavor.assign("default"); 1251 else 1252 m_flavor.assign(flavor); 1253 1254 // If this is an arm variant that can only include thumb (T16, T32) 1255 // instructions, force the arch triple to be "thumbv.." instead of "armv..." 1256 if (arch.IsAlwaysThumbInstructions()) { 1257 std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 1258 // Replace "arm" with "thumb" so we get all thumb variants correct 1259 if (thumb_arch_name.size() > 3) { 1260 thumb_arch_name.erase(0, 3); 1261 thumb_arch_name.insert(0, "thumb"); 1262 } 1263 m_arch.SetTriple(thumb_arch_name.c_str()); 1264 } 1265 } 1266 1267 Disassembler::~Disassembler() = default; 1268 1269 InstructionList &Disassembler::GetInstructionList() { 1270 return m_instruction_list; 1271 } 1272 1273 const InstructionList &Disassembler::GetInstructionList() const { 1274 return m_instruction_list; 1275 } 1276 1277 //---------------------------------------------------------------------- 1278 // Class PseudoInstruction 1279 //---------------------------------------------------------------------- 1280 1281 PseudoInstruction::PseudoInstruction() 1282 : Instruction(Address(), AddressClass::eUnknown), m_description() {} 1283 1284 PseudoInstruction::~PseudoInstruction() = default; 1285 1286 bool PseudoInstruction::DoesBranch() { 1287 // This is NOT a valid question for a pseudo instruction. 1288 return false; 1289 } 1290 1291 bool PseudoInstruction::HasDelaySlot() { 1292 // This is NOT a valid question for a pseudo instruction. 1293 return false; 1294 } 1295 1296 size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 1297 const lldb_private::DataExtractor &data, 1298 lldb::offset_t data_offset) { 1299 return m_opcode.GetByteSize(); 1300 } 1301 1302 void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 1303 if (!opcode_data) 1304 return; 1305 1306 switch (opcode_size) { 1307 case 8: { 1308 uint8_t value8 = *((uint8_t *)opcode_data); 1309 m_opcode.SetOpcode8(value8, eByteOrderInvalid); 1310 break; 1311 } 1312 case 16: { 1313 uint16_t value16 = *((uint16_t *)opcode_data); 1314 m_opcode.SetOpcode16(value16, eByteOrderInvalid); 1315 break; 1316 } 1317 case 32: { 1318 uint32_t value32 = *((uint32_t *)opcode_data); 1319 m_opcode.SetOpcode32(value32, eByteOrderInvalid); 1320 break; 1321 } 1322 case 64: { 1323 uint64_t value64 = *((uint64_t *)opcode_data); 1324 m_opcode.SetOpcode64(value64, eByteOrderInvalid); 1325 break; 1326 } 1327 default: 1328 break; 1329 } 1330 } 1331 1332 void PseudoInstruction::SetDescription(llvm::StringRef description) { 1333 m_description = description; 1334 } 1335 1336 Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1337 Operand ret; 1338 ret.m_type = Type::Register; 1339 ret.m_register = r; 1340 return ret; 1341 } 1342 1343 Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1344 bool neg) { 1345 Operand ret; 1346 ret.m_type = Type::Immediate; 1347 ret.m_immediate = imm; 1348 ret.m_negative = neg; 1349 return ret; 1350 } 1351 1352 Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1353 Operand ret; 1354 ret.m_type = Type::Immediate; 1355 if (imm < 0) { 1356 ret.m_immediate = -imm; 1357 ret.m_negative = true; 1358 } else { 1359 ret.m_immediate = imm; 1360 ret.m_negative = false; 1361 } 1362 return ret; 1363 } 1364 1365 Instruction::Operand 1366 Instruction::Operand::BuildDereference(const Operand &ref) { 1367 Operand ret; 1368 ret.m_type = Type::Dereference; 1369 ret.m_children = {ref}; 1370 return ret; 1371 } 1372 1373 Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1374 const Operand &rhs) { 1375 Operand ret; 1376 ret.m_type = Type::Sum; 1377 ret.m_children = {lhs, rhs}; 1378 return ret; 1379 } 1380 1381 Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1382 const Operand &rhs) { 1383 Operand ret; 1384 ret.m_type = Type::Product; 1385 ret.m_children = {lhs, rhs}; 1386 return ret; 1387 } 1388 1389 std::function<bool(const Instruction::Operand &)> 1390 lldb_private::OperandMatchers::MatchBinaryOp( 1391 std::function<bool(const Instruction::Operand &)> base, 1392 std::function<bool(const Instruction::Operand &)> left, 1393 std::function<bool(const Instruction::Operand &)> right) { 1394 return [base, left, right](const Instruction::Operand &op) -> bool { 1395 return (base(op) && op.m_children.size() == 2 && 1396 ((left(op.m_children[0]) && right(op.m_children[1])) || 1397 (left(op.m_children[1]) && right(op.m_children[0])))); 1398 }; 1399 } 1400 1401 std::function<bool(const Instruction::Operand &)> 1402 lldb_private::OperandMatchers::MatchUnaryOp( 1403 std::function<bool(const Instruction::Operand &)> base, 1404 std::function<bool(const Instruction::Operand &)> child) { 1405 return [base, child](const Instruction::Operand &op) -> bool { 1406 return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1407 }; 1408 } 1409 1410 std::function<bool(const Instruction::Operand &)> 1411 lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1412 return [&info](const Instruction::Operand &op) { 1413 return (op.m_type == Instruction::Operand::Type::Register && 1414 (op.m_register == ConstString(info.name) || 1415 op.m_register == ConstString(info.alt_name))); 1416 }; 1417 } 1418 1419 std::function<bool(const Instruction::Operand &)> 1420 lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { 1421 return [®](const Instruction::Operand &op) { 1422 if (op.m_type != Instruction::Operand::Type::Register) { 1423 return false; 1424 } 1425 reg = op.m_register; 1426 return true; 1427 }; 1428 } 1429 1430 std::function<bool(const Instruction::Operand &)> 1431 lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1432 return [imm](const Instruction::Operand &op) { 1433 return (op.m_type == Instruction::Operand::Type::Immediate && 1434 ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1435 (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1436 }; 1437 } 1438 1439 std::function<bool(const Instruction::Operand &)> 1440 lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1441 return [&imm](const Instruction::Operand &op) { 1442 if (op.m_type != Instruction::Operand::Type::Immediate) { 1443 return false; 1444 } 1445 if (op.m_negative) { 1446 imm = -((int64_t)op.m_immediate); 1447 } else { 1448 imm = ((int64_t)op.m_immediate); 1449 } 1450 return true; 1451 }; 1452 } 1453 1454 std::function<bool(const Instruction::Operand &)> 1455 lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1456 return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1457 } 1458