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