LLDB mainline
DisassemblerLLVMC.cpp
Go to the documentation of this file.
1//===-- DisassemblerLLVMC.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 "DisassemblerLLVMC.h"
10
11#include "llvm-c/Disassembler.h"
12#include "llvm/ADT/SmallString.h"
13#include "llvm/ADT/StringExtras.h"
14#include "llvm/MC/MCAsmInfo.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCDisassembler/MCDisassembler.h"
17#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"
18#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstPrinter.h"
21#include "llvm/MC/MCInstrAnalysis.h"
22#include "llvm/MC/MCInstrInfo.h"
23#include "llvm/MC/MCRegisterInfo.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCTargetOptions.h"
26#include "llvm/MC/TargetRegistry.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/ScopedPrinter.h"
29#include "llvm/Support/TargetSelect.h"
30#include "llvm/TargetParser/AArch64TargetParser.h"
31
32#include "lldb/Core/Address.h"
33#include "lldb/Core/Module.h"
37#include "lldb/Target/Process.h"
41#include "lldb/Target/Target.h"
44#include "lldb/Utility/Log.h"
46#include "lldb/Utility/Stream.h"
47#include <optional>
48
49using namespace lldb;
50using namespace lldb_private;
51
53
55public:
56 static std::unique_ptr<MCDisasmInstance>
57 Create(const char *triple, const char *cpu, const char *features_str,
58 unsigned flavor, DisassemblerLLVMC &owner);
59
60 ~MCDisasmInstance() = default;
61
62 bool GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
63 lldb::addr_t pc, llvm::MCInst &mc_inst, uint64_t &size) const;
64 void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc,
65 std::string &inst_string, std::string &comments_string);
66 void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style);
67 void SetUseColor(bool use_color);
68 bool GetUseColor() const;
69 bool CanBranch(llvm::MCInst &mc_inst) const;
70 bool HasDelaySlot(llvm::MCInst &mc_inst) const;
71 bool IsCall(llvm::MCInst &mc_inst) const;
72 bool IsLoad(llvm::MCInst &mc_inst) const;
73 bool IsBarrier(llvm::MCInst &mc_inst) const;
74 bool IsAuthenticated(llvm::MCInst &mc_inst) const;
75
76private:
77 MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
78 std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
79 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
80 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
81 std::unique_ptr<llvm::MCContext> &&context_up,
82 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
83 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,
84 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up);
85
86 std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up;
87 std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up;
88 std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up;
89 std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up;
90 std::unique_ptr<llvm::MCContext> m_context_up;
91 std::unique_ptr<llvm::MCDisassembler> m_disasm_up;
92 std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up;
93 std::unique_ptr<llvm::MCInstrAnalysis> m_instr_analysis_up;
94};
95
96namespace x86 {
97
98/// These are the three values deciding instruction control flow kind.
99/// InstructionLengthDecode function decodes an instruction and get this struct.
100///
101/// primary_opcode
102/// Primary opcode of the instruction.
103/// For one-byte opcode instruction, it's the first byte after prefix.
104/// For two- and three-byte opcodes, it's the second byte.
105///
106/// opcode_len
107/// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3.
108///
109/// modrm
110/// ModR/M byte of the instruction.
111/// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0]
112/// may contain a register or specify an addressing mode, depending on MOD.
118
119/// Determine the InstructionControlFlowKind based on opcode and modrm bytes.
120/// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and
121/// instruction set.
122///
123/// \param[in] opcode_and_modrm
124/// Contains primary_opcode byte, its length, and ModR/M byte.
125/// Refer to the struct InstructionOpcodeAndModrm for details.
126///
127/// \return
128/// The control flow kind of the instruction or
129/// eInstructionControlFlowKindOther if the instruction doesn't affect
130/// the control flow of the program.
133 uint8_t opcode = opcode_and_modrm.primary_opcode;
134 uint8_t opcode_len = opcode_and_modrm.opcode_len;
135 uint8_t modrm = opcode_and_modrm.modrm;
136
137 if (opcode_len > 2)
139
140 if (opcode >= 0x70 && opcode <= 0x7F) {
141 if (opcode_len == 1)
143 else
145 }
146
147 if (opcode >= 0x80 && opcode <= 0x8F) {
148 if (opcode_len == 2)
150 else
152 }
153
154 switch (opcode) {
155 case 0x9A:
156 if (opcode_len == 1)
158 break;
159 case 0xFF:
160 if (opcode_len == 1) {
161 uint8_t modrm_reg = (modrm >> 3) & 7;
162 if (modrm_reg == 2)
164 else if (modrm_reg == 3)
166 else if (modrm_reg == 4)
168 else if (modrm_reg == 5)
170 }
171 break;
172 case 0xE8:
173 if (opcode_len == 1)
175 break;
176 case 0xCD:
177 case 0xCC:
178 case 0xCE:
179 case 0xF1:
180 if (opcode_len == 1)
182 break;
183 case 0xCF:
184 if (opcode_len == 1)
186 break;
187 case 0xE9:
188 case 0xEB:
189 if (opcode_len == 1)
191 break;
192 case 0xEA:
193 if (opcode_len == 1)
195 break;
196 case 0xE3:
197 case 0xE0:
198 case 0xE1:
199 case 0xE2:
200 if (opcode_len == 1)
202 break;
203 case 0xC3:
204 case 0xC2:
205 if (opcode_len == 1)
207 break;
208 case 0xCB:
209 case 0xCA:
210 if (opcode_len == 1)
212 break;
213 case 0x05:
214 case 0x34:
215 if (opcode_len == 2)
217 break;
218 case 0x35:
219 case 0x07:
220 if (opcode_len == 2)
222 break;
223 case 0x01:
224 if (opcode_len == 2) {
225 switch (modrm) {
226 case 0xc1:
228 case 0xc2:
229 case 0xc3:
231 default:
232 break;
233 }
234 }
235 break;
236 default:
237 break;
238 }
239
241}
242
243/// Decode an instruction into opcode, modrm and opcode_len.
244/// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout.
245/// Opcodes in x86 are generally the first byte of instruction, though two-byte
246/// instructions and prefixes exist. ModR/M is the byte following the opcode
247/// and adds additional information for how the instruction is executed.
248///
249/// \param[in] inst_bytes
250/// Raw bytes of the instruction
251///
252///
253/// \param[in] bytes_len
254/// The length of the inst_bytes array.
255///
256/// \param[in] is_exec_mode_64b
257/// If true, the execution mode is 64 bit.
258///
259/// \return
260/// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding
261/// primary_opcode, opcode_len and modrm byte. Refer to the struct definition
262/// for more details.
263/// Otherwise if the given instruction is invalid, returns std::nullopt.
264std::optional<InstructionOpcodeAndModrm>
265InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len,
266 bool is_exec_mode_64b) {
267 int op_idx = 0;
268 bool prefix_done = false;
269 InstructionOpcodeAndModrm ret = {0, 0, 0};
270
271 // In most cases, the primary_opcode is the first byte of the instruction
272 // but some instructions have a prefix to be skipped for these calculations.
273 // The following mapping is inspired from libipt's instruction decoding logic
274 // in `src/pt_ild.c`
275 while (!prefix_done) {
276 if (op_idx >= bytes_len)
277 return std::nullopt;
278
279 ret.primary_opcode = inst_bytes[op_idx];
280 switch (ret.primary_opcode) {
281 // prefix_ignore
282 case 0x26:
283 case 0x2e:
284 case 0x36:
285 case 0x3e:
286 case 0x64:
287 case 0x65:
288 // prefix_osz, prefix_asz
289 case 0x66:
290 case 0x67:
291 // prefix_lock, prefix_f2, prefix_f3
292 case 0xf0:
293 case 0xf2:
294 case 0xf3:
295 op_idx++;
296 break;
297
298 // prefix_rex
299 case 0x40:
300 case 0x41:
301 case 0x42:
302 case 0x43:
303 case 0x44:
304 case 0x45:
305 case 0x46:
306 case 0x47:
307 case 0x48:
308 case 0x49:
309 case 0x4a:
310 case 0x4b:
311 case 0x4c:
312 case 0x4d:
313 case 0x4e:
314 case 0x4f:
315 if (is_exec_mode_64b)
316 op_idx++;
317 else
318 prefix_done = true;
319 break;
320
321 // prefix_vex_c4, c5
322 case 0xc5:
323 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
324 prefix_done = true;
325 break;
326 }
327
328 ret.opcode_len = 2;
329 ret.primary_opcode = inst_bytes[op_idx + 2];
330 ret.modrm = inst_bytes[op_idx + 3];
331 return ret;
332
333 case 0xc4:
334 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
335 prefix_done = true;
336 break;
337 }
338 ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f;
339 ret.primary_opcode = inst_bytes[op_idx + 3];
340 ret.modrm = inst_bytes[op_idx + 4];
341 return ret;
342
343 // prefix_evex
344 case 0x62:
345 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
346 prefix_done = true;
347 break;
348 }
349 ret.opcode_len = inst_bytes[op_idx + 1] & 0x03;
350 ret.primary_opcode = inst_bytes[op_idx + 4];
351 ret.modrm = inst_bytes[op_idx + 5];
352 return ret;
353
354 default:
355 prefix_done = true;
356 break;
357 }
358 } // prefix done
359
360 ret.primary_opcode = inst_bytes[op_idx];
361 ret.modrm = inst_bytes[op_idx + 1];
362 ret.opcode_len = 1;
363
364 // If the first opcode is 0F, it's two- or three- byte opcodes.
365 if (ret.primary_opcode == 0x0F) {
366 ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte
367
368 if (ret.primary_opcode == 0x38) {
369 ret.opcode_len = 3;
370 ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte
371 ret.modrm = inst_bytes[op_idx + 1];
372 } else if (ret.primary_opcode == 0x3A) {
373 ret.opcode_len = 3;
374 ret.primary_opcode = inst_bytes[++op_idx];
375 ret.modrm = inst_bytes[op_idx + 1];
376 } else if ((ret.primary_opcode & 0xf8) == 0x38) {
377 ret.opcode_len = 0;
378 ret.primary_opcode = inst_bytes[++op_idx];
379 ret.modrm = inst_bytes[op_idx + 1];
380 } else if (ret.primary_opcode == 0x0F) {
381 ret.opcode_len = 3;
382 // opcode is 0x0F, no needs to update
383 ret.modrm = inst_bytes[op_idx + 1];
384 } else {
385 ret.opcode_len = 2;
386 ret.modrm = inst_bytes[op_idx + 1];
387 }
388 }
389
390 return ret;
391}
392
394 Opcode m_opcode) {
395 std::optional<InstructionOpcodeAndModrm> ret;
396
397 if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) {
398 // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes
400 }
401
402 // Opcode bytes will be decoded into primary_opcode, modrm and opcode length.
403 // These are the three values deciding instruction control flow kind.
404 ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(),
405 m_opcode.GetByteSize(), is_exec_mode_64b);
406 if (!ret)
408 else
409 return MapOpcodeIntoControlFlowKind(*ret);
410}
411
412} // namespace x86
413
415public:
417 const lldb_private::Address &address,
418 AddressClass addr_class)
419 : Instruction(address, addr_class),
420 m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>(
421 disasm.shared_from_this())) {}
422
423 ~InstructionLLVMC() override = default;
424
425 bool DoesBranch() override {
427 return m_does_branch;
428 }
429
430 bool HasDelaySlot() override {
432 return m_has_delay_slot;
433 }
434
435 bool IsLoad() override {
437 return m_is_load;
438 }
439
440 bool IsBarrier() override {
442 return m_is_barrier;
443 }
444
445 bool IsAuthenticated() override {
447 return m_is_authenticated;
448 }
449
451 DisassemblerScope disasm(*this);
452 return GetDisasmToUse(is_alternate_isa, disasm);
453 }
454
455 size_t Decode(const lldb_private::Disassembler &disassembler,
456 const lldb_private::DataExtractor &data,
457 lldb::offset_t data_offset) override {
458 // All we have to do is read the opcode which can be easy for some
459 // architectures
460 bool got_op = false;
461 DisassemblerScope disasm(*this);
462 if (disasm) {
463 const ArchSpec &arch = disasm->GetArchitecture();
464 const lldb::ByteOrder byte_order = data.GetByteOrder();
465
466 const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
467 const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
468 if (min_op_byte_size == max_op_byte_size) {
469 // Fixed size instructions, just read that amount of data.
470 if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
471 return false;
472
473 switch (min_op_byte_size) {
474 case 1:
475 m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order);
476 got_op = true;
477 break;
478
479 case 2:
480 m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order);
481 got_op = true;
482 break;
483
484 case 4:
485 m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);
486 got_op = true;
487 break;
488
489 case 8:
490 m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order);
491 got_op = true;
492 break;
493
494 default:
495 if (arch.GetTriple().isRISCV())
496 m_opcode.SetOpcode16_32TupleBytes(
497 data.PeekData(data_offset, min_op_byte_size), min_op_byte_size,
498 byte_order);
499 else
500 m_opcode.SetOpcodeBytes(
501 data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
502 got_op = true;
503 break;
504 }
505 }
506 if (!got_op) {
507 bool is_alternate_isa = false;
509 GetDisasmToUse(is_alternate_isa, disasm);
510
511 const llvm::Triple::ArchType machine = arch.GetMachine();
512 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) {
513 if (machine == llvm::Triple::thumb || is_alternate_isa) {
514 uint32_t thumb_opcode = data.GetU16(&data_offset);
515 if ((thumb_opcode & 0xe000) != 0xe000 ||
516 ((thumb_opcode & 0x1800u) == 0)) {
517 m_opcode.SetOpcode16(thumb_opcode, byte_order);
518 m_is_valid = true;
519 } else {
520 thumb_opcode <<= 16;
521 thumb_opcode |= data.GetU16(&data_offset);
522 m_opcode.SetOpcode16_2(thumb_opcode, byte_order);
523 m_is_valid = true;
524 }
525 } else {
526 m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);
527 m_is_valid = true;
528 }
529 } else {
530 // The opcode isn't evenly sized, so we need to actually use the llvm
531 // disassembler to parse it and get the size.
532 uint8_t *opcode_data =
533 const_cast<uint8_t *>(data.PeekData(data_offset, 1));
534 const size_t opcode_data_len = data.BytesLeft(data_offset);
535 const addr_t pc = m_address.GetFileAddress();
536 llvm::MCInst inst;
537
538 uint64_t inst_size = 0;
539 m_is_valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len,
540 pc, inst, inst_size);
541 m_opcode.Clear();
542 if (inst_size != 0) {
543 if (arch.GetTriple().isRISCV())
544 m_opcode.SetOpcode16_32TupleBytes(opcode_data, inst_size,
545 byte_order);
546 else
547 m_opcode.SetOpcodeBytes(opcode_data, inst_size);
548 }
549 }
550 }
551 return m_opcode.GetByteSize();
552 }
553 return 0;
554 }
555
556 void AppendComment(std::string &description) {
557 if (m_comment.empty())
558 m_comment.swap(description);
559 else {
560 m_comment.append(", ");
561 m_comment.append(description);
562 }
563 }
564
567 DisassemblerScope disasm(*this, exe_ctx);
568 if (disasm) {
569 if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86)
570 return x86::GetControlFlowKind(/*is_64b=*/false, m_opcode);
571 else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
572 return x86::GetControlFlowKind(/*is_64b=*/true, m_opcode);
573 }
574
576 }
577
579 const lldb_private::ExecutionContext *exe_ctx) override {
580 DataExtractor data;
581 const AddressClass address_class = GetAddressClass();
582
583 if (m_opcode.GetData(data)) {
584 std::string out_string;
585 std::string markup_out_string;
586 std::string comment_string;
587 std::string markup_comment_string;
588
589 DisassemblerScope disasm(*this, exe_ctx);
590 if (disasm) {
592
593 if (address_class == AddressClass::eCodeAlternateISA)
594 mc_disasm_ptr = disasm->m_alternate_disasm_up.get();
595 else
596 mc_disasm_ptr = disasm->m_disasm_up.get();
597
598 lldb::addr_t pc = m_address.GetFileAddress();
599 m_using_file_addr = true;
600
601 bool use_hex_immediates = true;
603
604 if (exe_ctx) {
605 Target *target = exe_ctx->GetTargetPtr();
606 if (target) {
607 use_hex_immediates = target->GetUseHexImmediates();
608 hex_style = target->GetHexImmediateStyle();
609
610 const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
611 if (load_addr != LLDB_INVALID_ADDRESS) {
612 pc = load_addr;
613 m_using_file_addr = false;
614 }
615 }
616 }
617
618 const uint8_t *opcode_data = data.GetDataStart();
619 const size_t opcode_data_len = data.GetByteSize();
620 llvm::MCInst inst;
621 uint64_t inst_size = 0;
622 bool valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc,
623 inst, inst_size);
624
625 if (valid && inst_size > 0) {
626 mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
627
628 const bool saved_use_color = mc_disasm_ptr->GetUseColor();
629 mc_disasm_ptr->SetUseColor(false);
630 mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string);
631 mc_disasm_ptr->SetUseColor(true);
632 mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string,
633 markup_comment_string);
634 mc_disasm_ptr->SetUseColor(saved_use_color);
635
636 if (!comment_string.empty()) {
637 AppendComment(comment_string);
638 }
639 }
640
641 if (inst_size == 0) {
642 m_comment.assign("unknown opcode");
643 inst_size = m_opcode.GetByteSize();
644 StreamString mnemonic_strm;
645 lldb::offset_t offset = 0;
646 lldb::ByteOrder byte_order = data.GetByteOrder();
647 switch (inst_size) {
648 case 1: {
649 const uint8_t uval8 = data.GetU8(&offset);
650 m_opcode.SetOpcode8(uval8, byte_order);
651 m_opcode_name.assign(".byte");
652 mnemonic_strm.Printf("0x%2.2x", uval8);
653 } break;
654 case 2: {
655 const uint16_t uval16 = data.GetU16(&offset);
656 m_opcode.SetOpcode16(uval16, byte_order);
657 m_opcode_name.assign(".short");
658 mnemonic_strm.Printf("0x%4.4x", uval16);
659 } break;
660 case 4: {
661 const uint32_t uval32 = data.GetU32(&offset);
662 m_opcode.SetOpcode32(uval32, byte_order);
663 m_opcode_name.assign(".long");
664 mnemonic_strm.Printf("0x%8.8x", uval32);
665 } break;
666 case 8: {
667 const uint64_t uval64 = data.GetU64(&offset);
668 m_opcode.SetOpcode64(uval64, byte_order);
669 m_opcode_name.assign(".quad");
670 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
671 } break;
672 default:
673 if (inst_size == 0)
674 return;
675 else {
676 const uint8_t *bytes = data.PeekData(offset, inst_size);
677 if (bytes == nullptr)
678 return;
679 m_opcode_name.assign(".byte");
680 m_opcode.SetOpcodeBytes(bytes, inst_size);
681 mnemonic_strm.Printf("0x%2.2x", bytes[0]);
682 for (uint32_t i = 1; i < inst_size; ++i)
683 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
684 }
685 break;
686 }
687 m_mnemonics = std::string(mnemonic_strm.GetString());
688 return;
689 }
690
691 static RegularExpression s_regex(
692 llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"));
693
694 llvm::SmallVector<llvm::StringRef, 4> matches;
695 if (s_regex.Execute(out_string, &matches)) {
696 m_opcode_name = matches[1].str();
697 m_mnemonics = matches[2].str();
698 }
699 matches.clear();
700 if (s_regex.Execute(markup_out_string, &matches)) {
701 m_markup_opcode_name = matches[1].str();
702 m_markup_mnemonics = matches[2].str();
703 }
704 }
705 }
706 }
707
708 bool IsValid() const { return m_is_valid; }
709
710 bool UsingFileAddress() const { return m_using_file_addr; }
711 size_t GetByteSize() const { return m_opcode.GetByteSize(); }
712
713 /// Grants exclusive access to the disassembler and initializes it with the
714 /// given InstructionLLVMC and an optional ExecutionContext.
716 std::shared_ptr<DisassemblerLLVMC> m_disasm;
717
718 public:
721 const lldb_private::ExecutionContext *exe_ctx = nullptr)
722 : m_disasm(i.m_disasm_wp.lock()) {
723 m_disasm->m_mutex.lock();
724 m_disasm->m_inst = &i;
725 m_disasm->m_exe_ctx = exe_ctx;
726 }
727 ~DisassemblerScope() { m_disasm->m_mutex.unlock(); }
728
729 /// Evaluates to true if this scope contains a valid disassembler.
730 operator bool() const { return static_cast<bool>(m_disasm); }
731
732 std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; }
733 };
734
735 static llvm::StringRef::const_iterator
736 ConsumeWhitespace(llvm::StringRef::const_iterator osi,
737 llvm::StringRef::const_iterator ose) {
738 while (osi != ose) {
739 switch (*osi) {
740 default:
741 return osi;
742 case ' ':
743 case '\t':
744 break;
745 }
746 ++osi;
747 }
748
749 return osi;
750 }
751
752 static std::pair<bool, llvm::StringRef::const_iterator>
753 ConsumeChar(llvm::StringRef::const_iterator osi, const char c,
754 llvm::StringRef::const_iterator ose) {
755 bool found = false;
756
757 osi = ConsumeWhitespace(osi, ose);
758 if (osi != ose && *osi == c) {
759 found = true;
760 ++osi;
761 }
762
763 return std::make_pair(found, osi);
764 }
765
766 static std::pair<Operand, llvm::StringRef::const_iterator>
767 ParseRegisterName(llvm::StringRef::const_iterator osi,
768 llvm::StringRef::const_iterator ose) {
769 Operand ret;
770 ret.m_type = Operand::Type::Register;
771 std::string str;
772
773 osi = ConsumeWhitespace(osi, ose);
774
775 while (osi != ose) {
776 if (*osi >= '0' && *osi <= '9') {
777 if (str.empty()) {
778 return std::make_pair(Operand(), osi);
779 } else {
780 str.push_back(*osi);
781 }
782 } else if (*osi >= 'a' && *osi <= 'z') {
783 str.push_back(*osi);
784 } else {
785 switch (*osi) {
786 default:
787 if (str.empty()) {
788 return std::make_pair(Operand(), osi);
789 } else {
790 ret.m_register = ConstString(str);
791 return std::make_pair(ret, osi);
792 }
793 case '%':
794 if (!str.empty()) {
795 return std::make_pair(Operand(), osi);
796 }
797 break;
798 }
799 }
800 ++osi;
801 }
802
803 ret.m_register = ConstString(str);
804 return std::make_pair(ret, osi);
805 }
806
807 static std::pair<Operand, llvm::StringRef::const_iterator>
808 ParseImmediate(llvm::StringRef::const_iterator osi,
809 llvm::StringRef::const_iterator ose) {
810 Operand ret;
811 ret.m_type = Operand::Type::Immediate;
812 std::string str;
813 bool is_hex = false;
814
815 osi = ConsumeWhitespace(osi, ose);
816
817 while (osi != ose) {
818 if (*osi >= '0' && *osi <= '9') {
819 str.push_back(*osi);
820 } else if (*osi >= 'a' && *osi <= 'f') {
821 if (is_hex) {
822 str.push_back(*osi);
823 } else {
824 return std::make_pair(Operand(), osi);
825 }
826 } else {
827 switch (*osi) {
828 default:
829 if (str.empty()) {
830 return std::make_pair(Operand(), osi);
831 } else {
832 ret.m_immediate = strtoull(str.c_str(), nullptr, 0);
833 return std::make_pair(ret, osi);
834 }
835 case 'x':
836 if (str == "0") {
837 is_hex = true;
838 str.push_back(*osi);
839 } else {
840 return std::make_pair(Operand(), osi);
841 }
842 break;
843 case '#':
844 case '$':
845 if (!str.empty()) {
846 return std::make_pair(Operand(), osi);
847 }
848 break;
849 case '-':
850 if (str.empty()) {
851 ret.m_negative = true;
852 } else {
853 return std::make_pair(Operand(), osi);
854 }
855 }
856 }
857 ++osi;
858 }
859
860 ret.m_immediate = strtoull(str.c_str(), nullptr, 0);
861 return std::make_pair(ret, osi);
862 }
863
864 // -0x5(%rax,%rax,2)
865 static std::pair<Operand, llvm::StringRef::const_iterator>
866 ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi,
867 llvm::StringRef::const_iterator ose) {
868 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
869 ParseImmediate(osi, ose);
870 if (offset_and_iterator.first.IsValid()) {
871 osi = offset_and_iterator.second;
872 }
873
874 bool found = false;
875 std::tie(found, osi) = ConsumeChar(osi, '(', ose);
876 if (!found) {
877 return std::make_pair(Operand(), osi);
878 }
879
880 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
881 ParseRegisterName(osi, ose);
882 if (base_and_iterator.first.IsValid()) {
883 osi = base_and_iterator.second;
884 } else {
885 return std::make_pair(Operand(), osi);
886 }
887
888 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
889 if (!found) {
890 return std::make_pair(Operand(), osi);
891 }
892
893 std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator =
894 ParseRegisterName(osi, ose);
895 if (index_and_iterator.first.IsValid()) {
896 osi = index_and_iterator.second;
897 } else {
898 return std::make_pair(Operand(), osi);
899 }
900
901 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
902 if (!found) {
903 return std::make_pair(Operand(), osi);
904 }
905
906 std::pair<Operand, llvm::StringRef::const_iterator>
907 multiplier_and_iterator = ParseImmediate(osi, ose);
908 if (index_and_iterator.first.IsValid()) {
909 osi = index_and_iterator.second;
910 } else {
911 return std::make_pair(Operand(), osi);
912 }
913
914 std::tie(found, osi) = ConsumeChar(osi, ')', ose);
915 if (!found) {
916 return std::make_pair(Operand(), osi);
917 }
918
919 Operand product;
920 product.m_type = Operand::Type::Product;
921 product.m_children.push_back(index_and_iterator.first);
922 product.m_children.push_back(multiplier_and_iterator.first);
923
924 Operand index;
925 index.m_type = Operand::Type::Sum;
926 index.m_children.push_back(base_and_iterator.first);
927 index.m_children.push_back(product);
928
929 if (offset_and_iterator.first.IsValid()) {
930 Operand offset;
931 offset.m_type = Operand::Type::Sum;
932 offset.m_children.push_back(offset_and_iterator.first);
933 offset.m_children.push_back(index);
934
935 Operand deref;
936 deref.m_type = Operand::Type::Dereference;
937 deref.m_children.push_back(offset);
938 return std::make_pair(deref, osi);
939 } else {
940 Operand deref;
941 deref.m_type = Operand::Type::Dereference;
942 deref.m_children.push_back(index);
943 return std::make_pair(deref, osi);
944 }
945 }
946
947 // -0x10(%rbp)
948 static std::pair<Operand, llvm::StringRef::const_iterator>
949 ParseIntelDerefAccess(llvm::StringRef::const_iterator osi,
950 llvm::StringRef::const_iterator ose) {
951 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
952 ParseImmediate(osi, ose);
953 if (offset_and_iterator.first.IsValid()) {
954 osi = offset_and_iterator.second;
955 }
956
957 bool found = false;
958 std::tie(found, osi) = ConsumeChar(osi, '(', ose);
959 if (!found) {
960 return std::make_pair(Operand(), osi);
961 }
962
963 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
964 ParseRegisterName(osi, ose);
965 if (base_and_iterator.first.IsValid()) {
966 osi = base_and_iterator.second;
967 } else {
968 return std::make_pair(Operand(), osi);
969 }
970
971 std::tie(found, osi) = ConsumeChar(osi, ')', ose);
972 if (!found) {
973 return std::make_pair(Operand(), osi);
974 }
975
976 if (offset_and_iterator.first.IsValid()) {
977 Operand offset;
978 offset.m_type = Operand::Type::Sum;
979 offset.m_children.push_back(offset_and_iterator.first);
980 offset.m_children.push_back(base_and_iterator.first);
981
982 Operand deref;
983 deref.m_type = Operand::Type::Dereference;
984 deref.m_children.push_back(offset);
985 return std::make_pair(deref, osi);
986 } else {
987 Operand deref;
988 deref.m_type = Operand::Type::Dereference;
989 deref.m_children.push_back(base_and_iterator.first);
990 return std::make_pair(deref, osi);
991 }
992 }
993
994 // [sp, #8]!
995 static std::pair<Operand, llvm::StringRef::const_iterator>
996 ParseARMOffsetAccess(llvm::StringRef::const_iterator osi,
997 llvm::StringRef::const_iterator ose) {
998 bool found = false;
999 std::tie(found, osi) = ConsumeChar(osi, '[', ose);
1000 if (!found) {
1001 return std::make_pair(Operand(), osi);
1002 }
1003
1004 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
1005 ParseRegisterName(osi, ose);
1006 if (base_and_iterator.first.IsValid()) {
1007 osi = base_and_iterator.second;
1008 } else {
1009 return std::make_pair(Operand(), osi);
1010 }
1011
1012 std::tie(found, osi) = ConsumeChar(osi, ',', ose);
1013 if (!found) {
1014 return std::make_pair(Operand(), osi);
1015 }
1016
1017 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
1018 ParseImmediate(osi, ose);
1019 if (offset_and_iterator.first.IsValid()) {
1020 osi = offset_and_iterator.second;
1021 }
1022
1023 std::tie(found, osi) = ConsumeChar(osi, ']', ose);
1024 if (!found) {
1025 return std::make_pair(Operand(), osi);
1026 }
1027
1028 Operand offset;
1029 offset.m_type = Operand::Type::Sum;
1030 offset.m_children.push_back(offset_and_iterator.first);
1031 offset.m_children.push_back(base_and_iterator.first);
1032
1033 Operand deref;
1034 deref.m_type = Operand::Type::Dereference;
1035 deref.m_children.push_back(offset);
1036 return std::make_pair(deref, osi);
1037 }
1038
1039 // [sp]
1040 static std::pair<Operand, llvm::StringRef::const_iterator>
1041 ParseARMDerefAccess(llvm::StringRef::const_iterator osi,
1042 llvm::StringRef::const_iterator ose) {
1043 bool found = false;
1044 std::tie(found, osi) = ConsumeChar(osi, '[', ose);
1045 if (!found) {
1046 return std::make_pair(Operand(), osi);
1047 }
1048
1049 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
1050 ParseRegisterName(osi, ose);
1051 if (base_and_iterator.first.IsValid()) {
1052 osi = base_and_iterator.second;
1053 } else {
1054 return std::make_pair(Operand(), osi);
1055 }
1056
1057 std::tie(found, osi) = ConsumeChar(osi, ']', ose);
1058 if (!found) {
1059 return std::make_pair(Operand(), osi);
1060 }
1061
1062 Operand deref;
1063 deref.m_type = Operand::Type::Dereference;
1064 deref.m_children.push_back(base_and_iterator.first);
1065 return std::make_pair(deref, osi);
1066 }
1067
1068 static void DumpOperand(const Operand &op, Stream &s) {
1069 switch (op.m_type) {
1070 case Operand::Type::Dereference:
1071 s.PutCString("*");
1072 DumpOperand(op.m_children[0], s);
1073 break;
1074 case Operand::Type::Immediate:
1075 if (op.m_negative) {
1076 s.PutCString("-");
1077 }
1078 s.PutCString(llvm::to_string(op.m_immediate));
1079 break;
1080 case Operand::Type::Invalid:
1081 s.PutCString("Invalid");
1082 break;
1083 case Operand::Type::Product:
1084 s.PutCString("(");
1085 DumpOperand(op.m_children[0], s);
1086 s.PutCString("*");
1087 DumpOperand(op.m_children[1], s);
1088 s.PutCString(")");
1089 break;
1090 case Operand::Type::Register:
1092 break;
1093 case Operand::Type::Sum:
1094 s.PutCString("(");
1095 DumpOperand(op.m_children[0], s);
1096 s.PutCString("+");
1097 DumpOperand(op.m_children[1], s);
1098 s.PutCString(")");
1099 break;
1100 }
1101 }
1102
1105 const char *operands_string = GetOperands(nullptr);
1106
1107 if (!operands_string) {
1108 return false;
1109 }
1110
1111 llvm::StringRef operands_ref(operands_string);
1112
1113 llvm::StringRef::const_iterator osi = operands_ref.begin();
1114 llvm::StringRef::const_iterator ose = operands_ref.end();
1115
1116 while (osi != ose) {
1117 Operand operand;
1118 llvm::StringRef::const_iterator iter;
1119
1120 if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose),
1121 operand.IsValid()) ||
1122 (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose),
1123 operand.IsValid()) ||
1124 (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose),
1125 operand.IsValid()) ||
1126 (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose),
1127 operand.IsValid()) ||
1128 (std::tie(operand, iter) = ParseRegisterName(osi, ose),
1129 operand.IsValid()) ||
1130 (std::tie(operand, iter) = ParseImmediate(osi, ose),
1131 operand.IsValid())) {
1132 osi = iter;
1133 operands.push_back(operand);
1134 } else {
1135 return false;
1136 }
1137
1138 std::pair<bool, llvm::StringRef::const_iterator> found_and_iter =
1139 ConsumeChar(osi, ',', ose);
1140 if (found_and_iter.first) {
1141 osi = found_and_iter.second;
1142 }
1143
1144 osi = ConsumeWhitespace(osi, ose);
1145 }
1146
1147 DisassemblerSP disasm_sp = m_disasm_wp.lock();
1148
1149 if (disasm_sp && operands.size() > 1) {
1150 // TODO tie this into the MC Disassembler's notion of clobbers.
1151 switch (disasm_sp->GetArchitecture().GetMachine()) {
1152 default:
1153 break;
1154 case llvm::Triple::x86:
1155 case llvm::Triple::x86_64:
1156 operands[operands.size() - 1].m_clobbered = true;
1157 break;
1158 case llvm::Triple::arm:
1159 operands[0].m_clobbered = true;
1160 break;
1161 }
1162 }
1163
1165 StreamString ss;
1166
1167 ss.Printf("[%s] expands to %zu operands:\n", operands_string,
1168 operands.size());
1169 for (const Operand &operand : operands) {
1170 ss.PutCString(" ");
1171 DumpOperand(operand, ss);
1172 ss.PutCString("\n");
1173 }
1174
1175 log->PutString(ss.GetString());
1176 }
1177
1178 return true;
1179 }
1180
1181 bool IsCall() override {
1183 return m_is_call;
1184 }
1185
1186protected:
1187 std::weak_ptr<DisassemblerLLVMC> m_disasm_wp;
1188
1189 bool m_is_valid = false;
1190 bool m_using_file_addr = false;
1192
1193 // Be conservative. If we didn't understand the instruction, say it:
1194 // - Might branch
1195 // - Does not have a delay slot
1196 // - Is not a call
1197 // - Is not a load
1198 // - Is not an authenticated instruction
1199 bool m_does_branch = true;
1200 bool m_has_delay_slot = false;
1201 bool m_is_call = false;
1202 bool m_is_load = false;
1204 bool m_is_barrier = false;
1205
1208 return;
1209
1210 DisassemblerScope disasm(*this);
1211 if (!disasm)
1212 return;
1213
1214 DataExtractor data;
1215 if (!m_opcode.GetData(data))
1216 return;
1217
1218 bool is_alternate_isa;
1219 lldb::addr_t pc = m_address.GetFileAddress();
1221 GetDisasmToUse(is_alternate_isa, disasm);
1222 const uint8_t *opcode_data = data.GetDataStart();
1223 const size_t opcode_data_len = data.GetByteSize();
1224 llvm::MCInst inst;
1225 uint64_t inst_size = 0;
1226 const bool valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len,
1227 pc, inst, inst_size);
1228 if (!valid)
1229 return;
1230
1232 m_does_branch = mc_disasm_ptr->CanBranch(inst);
1233 m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
1234 m_is_call = mc_disasm_ptr->IsCall(inst);
1235 m_is_load = mc_disasm_ptr->IsLoad(inst);
1236 m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst);
1237 m_is_barrier = mc_disasm_ptr->IsBarrier(inst);
1238 }
1239
1240private:
1242 GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) {
1243 is_alternate_isa = false;
1244 if (disasm) {
1245 if (disasm->m_alternate_disasm_up) {
1246 const AddressClass address_class = GetAddressClass();
1247
1248 if (address_class == AddressClass::eCodeAlternateISA) {
1249 is_alternate_isa = true;
1250 return disasm->m_alternate_disasm_up.get();
1251 }
1252 }
1253 return disasm->m_disasm_up.get();
1254 }
1255 return nullptr;
1256 }
1257};
1258
1259std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
1261 const char *cpu,
1262 const char *features_str,
1263 unsigned flavor,
1264 DisassemblerLLVMC &owner) {
1265 using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;
1266
1267 llvm::Triple triple(triple_name);
1268
1269 std::string Status;
1270 const llvm::Target *curr_target =
1271 llvm::TargetRegistry::lookupTarget(triple, Status);
1272 if (!curr_target)
1273 return Instance();
1274
1275 std::unique_ptr<llvm::MCInstrInfo> instr_info_up(
1276 curr_target->createMCInstrInfo());
1277 if (!instr_info_up)
1278 return Instance();
1279
1280 std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(
1281 curr_target->createMCRegInfo(triple));
1282 if (!reg_info_up)
1283 return Instance();
1284
1285 std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(
1286 curr_target->createMCSubtargetInfo(triple, cpu, features_str));
1287 if (!subtarget_info_up)
1288 return Instance();
1289
1290 llvm::MCTargetOptions MCOptions;
1291 std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
1292 curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));
1293 if (!asm_info_up)
1294 return Instance();
1295
1296 std::unique_ptr<llvm::MCContext> context_up(
1297 new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(),
1298 reg_info_up.get(), subtarget_info_up.get()));
1299 if (!context_up)
1300 return Instance();
1301
1302 std::unique_ptr<llvm::MCDisassembler> disasm_up(
1303 curr_target->createMCDisassembler(*subtarget_info_up, *context_up));
1304 if (!disasm_up)
1305 return Instance();
1306
1307 std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(
1308 curr_target->createMCRelocationInfo(triple, *context_up));
1309 if (!rel_info_up)
1310 return Instance();
1311
1312 std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
1313 curr_target->createMCSymbolizer(
1314 triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner,
1315 context_up.get(), std::move(rel_info_up)));
1316 disasm_up->setSymbolizer(std::move(symbolizer_up));
1317
1318 unsigned asm_printer_variant =
1319 flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;
1320
1321 std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(
1322 curr_target->createMCInstPrinter(llvm::Triple{triple},
1323 asm_printer_variant, *asm_info_up,
1324 *instr_info_up, *reg_info_up));
1325 if (!instr_printer_up)
1326 return Instance();
1327
1328 instr_printer_up->setPrintBranchImmAsAddress(true);
1329
1330 // Not all targets may have registered createMCInstrAnalysis().
1331 std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up(
1332 curr_target->createMCInstrAnalysis(instr_info_up.get()));
1333
1334 return Instance(new MCDisasmInstance(
1335 std::move(instr_info_up), std::move(reg_info_up),
1336 std::move(subtarget_info_up), std::move(asm_info_up),
1337 std::move(context_up), std::move(disasm_up), std::move(instr_printer_up),
1338 std::move(instr_analysis_up)));
1339}
1340
1342 std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
1343 std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
1344 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
1345 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
1346 std::unique_ptr<llvm::MCContext> &&context_up,
1347 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
1348 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,
1349 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up)
1350 : m_instr_info_up(std::move(instr_info_up)),
1351 m_reg_info_up(std::move(reg_info_up)),
1352 m_subtarget_info_up(std::move(subtarget_info_up)),
1353 m_asm_info_up(std::move(asm_info_up)),
1354 m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)),
1355 m_instr_printer_up(std::move(instr_printer_up)),
1356 m_instr_analysis_up(std::move(instr_analysis_up)) {
1359}
1360
1362 size_t opcode_data_len,
1364 llvm::MCInst &mc_inst,
1365 uint64_t &size) const {
1366 llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
1367 llvm::MCDisassembler::DecodeStatus status;
1368
1369 status = m_disasm_up->getInstruction(mc_inst, size, data, pc, llvm::nulls());
1370 if (status == llvm::MCDisassembler::Success)
1371 return true;
1372 else
1373 return false;
1374}
1375
1377 llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string,
1378 std::string &comments_string) {
1379 llvm::raw_string_ostream inst_stream(inst_string);
1380 llvm::raw_string_ostream comments_stream(comments_string);
1381
1382 inst_stream.enable_colors(m_instr_printer_up->getUseColor());
1383 m_instr_printer_up->setCommentStream(comments_stream);
1384 m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(),
1385 *m_subtarget_info_up, inst_stream);
1386 m_instr_printer_up->setCommentStream(llvm::nulls());
1387
1388 static std::string g_newlines("\r\n");
1389
1390 for (size_t newline_pos = 0;
1391 (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) !=
1392 comments_string.npos;
1393 /**/) {
1394 comments_string.replace(comments_string.begin() + newline_pos,
1395 comments_string.begin() + newline_pos + 1, 1, ' ');
1396 }
1397}
1398
1400 bool use_hex_immed, HexImmediateStyle hex_style) {
1401 m_instr_printer_up->setPrintImmHex(use_hex_immed);
1402 switch (hex_style) {
1403 case eHexStyleC:
1404 m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C);
1405 break;
1406 case eHexStyleAsm:
1407 m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm);
1408 break;
1409 }
1410}
1411
1413 m_instr_printer_up->setUseColor(use_color);
1414}
1415
1417 return m_instr_printer_up->getUseColor();
1418}
1419
1421 llvm::MCInst &mc_inst) const {
1423 return m_instr_analysis_up->mayAffectControlFlow(mc_inst, *m_reg_info_up);
1424 return m_instr_info_up->get(mc_inst.getOpcode())
1425 .mayAffectControlFlow(mc_inst, *m_reg_info_up);
1426}
1427
1429 llvm::MCInst &mc_inst) const {
1430 return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot();
1431}
1432
1433bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {
1435 return m_instr_analysis_up->isCall(mc_inst);
1436 return m_instr_info_up->get(mc_inst.getOpcode()).isCall();
1437}
1438
1439bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const {
1440 return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad();
1441}
1442
1444 llvm::MCInst &mc_inst) const {
1445 return m_instr_info_up->get(mc_inst.getOpcode()).isBarrier();
1446}
1447
1449 llvm::MCInst &mc_inst) const {
1450 const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode());
1451
1452 // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4
1453 // == 'a' + 'c') as authenticated instructions for reporting purposes, in
1454 // addition to the standard authenticated instructions specified in ARMv8.3.
1455 bool IsBrkC47x = false;
1456 if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) {
1457 const llvm::MCOperand &Op0 = mc_inst.getOperand(0);
1458 if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474)
1459 IsBrkC47x = true;
1460 }
1461
1462 return InstrDesc.isAuthenticated() || IsBrkC47x;
1463}
1464
1466 const char *flavor_string,
1467 const char *cpu_string,
1468 const char *features_string)
1469 : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr),
1471 m_adrp_insn() {
1472 if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) {
1473 m_flavor.assign("default");
1474 }
1475
1476 const bool cpu_or_features_overriden = cpu_string || features_string;
1477 unsigned flavor = ~0U;
1478 llvm::Triple triple = arch.GetTriple();
1479
1480 // So far the only supported flavor is "intel" on x86. The base class will
1481 // set this correctly coming in.
1482 if (triple.getArch() == llvm::Triple::x86 ||
1483 triple.getArch() == llvm::Triple::x86_64) {
1484 if (m_flavor == "intel") {
1485 flavor = 1;
1486 } else if (m_flavor == "att") {
1487 flavor = 0;
1488 }
1489 }
1490
1491 ArchSpec thumb_arch(arch);
1492 if (triple.getArch() == llvm::Triple::arm) {
1493 std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str());
1494 // Replace "arm" with "thumb" so we get all thumb variants correct
1495 if (thumb_arch_name.size() > 3) {
1496 thumb_arch_name.erase(0, 3);
1497 thumb_arch_name.insert(0, "thumb");
1498 } else {
1499 thumb_arch_name = "thumbv9.3a";
1500 }
1501 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name));
1502 }
1503
1504 // If no sub architecture specified then use the most recent arm architecture
1505 // so the disassembler will return all instructions. Without it we will see a
1506 // lot of unknown opcodes if the code uses instructions which are not
1507 // available in the oldest arm version (which is used when no sub architecture
1508 // is specified).
1509 if (triple.getArch() == llvm::Triple::arm &&
1510 triple.getSubArch() == llvm::Triple::NoSubArch)
1511 triple.setArchName("armv9.3a");
1512
1513 std::string features_str =
1514 features_string ? std::string(features_string) : "";
1515 const char *triple_str = triple.getTriple().c_str();
1516
1517 // ARM Cortex M0-M7 devices only execute thumb instructions
1518 if (arch.IsAlwaysThumbInstructions()) {
1519 triple_str = thumb_arch.GetTriple().getTriple().c_str();
1520 if (!features_string)
1521 features_str += "+fp-armv8,";
1522 }
1523
1524 const char *cpu = cpu_string;
1525
1526 if (!cpu_or_features_overriden) {
1527 switch (arch.GetCore()) {
1530 cpu = "mips32";
1531 break;
1534 cpu = "mips32r2";
1535 break;
1538 cpu = "mips32r3";
1539 break;
1542 cpu = "mips32r5";
1543 break;
1546 cpu = "mips32r6";
1547 break;
1550 cpu = "mips64";
1551 break;
1554 cpu = "mips64r2";
1555 break;
1558 cpu = "mips64r3";
1559 break;
1562 cpu = "mips64r5";
1563 break;
1566 cpu = "mips64r6";
1567 break;
1568 default:
1569 cpu = "";
1570 break;
1571 }
1572 }
1573
1574 if (arch.IsMIPS() && !cpu_or_features_overriden) {
1575 uint32_t arch_flags = arch.GetFlags();
1576 if (arch_flags & ArchSpec::eMIPSAse_msa)
1577 features_str += "+msa,";
1578 if (arch_flags & ArchSpec::eMIPSAse_dsp)
1579 features_str += "+dsp,";
1580 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
1581 features_str += "+dspr2,";
1582 }
1583
1584 // If any AArch64 variant, enable latest ISA with all extensions unless the
1585 // CPU or features were overridden.
1586 if (triple.isAArch64() && !cpu_or_features_overriden) {
1587 features_str += "+all,";
1588 if (triple.getVendor() == llvm::Triple::Apple)
1589 cpu = "apple-latest";
1590 }
1591
1592 if (triple.isRISCV() && !cpu_or_features_overriden) {
1593 uint32_t arch_flags = arch.GetFlags();
1594 if (arch_flags & ArchSpec::eRISCV_rvc)
1595 features_str += "+c,";
1596 if (arch_flags & ArchSpec::eRISCV_rve)
1597 features_str += "+e,";
1598 if ((arch_flags & ArchSpec::eRISCV_float_abi_single) ==
1600 features_str += "+f,";
1601 if ((arch_flags & ArchSpec::eRISCV_float_abi_double) ==
1603 features_str += "+f,+d,";
1604 if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) ==
1606 features_str += "+f,+d,+q,";
1607 // FIXME: how do we detect features such as `+a`, `+m`?
1608 // Turn them on by default now, since everyone seems to use them
1609 features_str += "+a,+m,";
1610 }
1611
1612 // We use m_disasm_up.get() to tell whether we are valid or not, so if this
1613 // isn't good for some reason, we won't be valid and FindPlugin will fail and
1614 // we won't get used.
1615 m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),
1616 flavor, *this);
1617
1618 llvm::Triple::ArchType llvm_arch = triple.getArch();
1619
1620 // For arm CPUs that can execute arm or thumb instructions, also create a
1621 // thumb instruction disassembler.
1622 if (llvm_arch == llvm::Triple::arm) {
1623 std::string thumb_triple(thumb_arch.GetTriple().getTriple());
1624 m_alternate_disasm_up = MCDisasmInstance::Create(
1625 thumb_triple.c_str(), "", features_str.c_str(), flavor, *this);
1626 if (!m_alternate_disasm_up)
1627 m_disasm_up.reset();
1628
1629 } else if (arch.IsMIPS()) {
1630 /* Create alternate disassembler for MIPS16 and microMIPS */
1631 uint32_t arch_flags = arch.GetFlags();
1632 if (arch_flags & ArchSpec::eMIPSAse_mips16)
1633 features_str += "+mips16,";
1634 else if (arch_flags & ArchSpec::eMIPSAse_micromips)
1635 features_str += "+micromips,";
1636
1637 m_alternate_disasm_up = MCDisasmInstance::Create(
1638 triple_str, cpu, features_str.c_str(), flavor, *this);
1639 if (!m_alternate_disasm_up)
1640 m_disasm_up.reset();
1641 }
1642}
1643
1645
1647 const char *flavor,
1648 const char *cpu,
1649 const char *features) {
1650 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) {
1651 auto disasm_sp =
1652 std::make_shared<DisassemblerLLVMC>(arch, flavor, cpu, features);
1653 if (disasm_sp && disasm_sp->IsValid())
1654 return disasm_sp;
1655 }
1656 return lldb::DisassemblerSP();
1657}
1658
1660 const DataExtractor &data,
1661 lldb::offset_t data_offset,
1662 size_t num_instructions,
1663 bool append, bool data_from_file) {
1664 if (!append)
1665 m_instruction_list.Clear();
1666
1667 if (!IsValid())
1668 return 0;
1669
1670 m_data_from_file = data_from_file;
1671 uint32_t data_cursor = data_offset;
1672 const size_t data_byte_size = data.GetByteSize();
1673 uint32_t instructions_parsed = 0;
1674 Address inst_addr(base_addr);
1675
1676 while (data_cursor < data_byte_size &&
1677 instructions_parsed < num_instructions) {
1678
1679 AddressClass address_class = AddressClass::eCode;
1680
1682 address_class = inst_addr.GetAddressClass();
1683
1684 InstructionSP inst_sp(
1685 new InstructionLLVMC(*this, inst_addr, address_class));
1686
1687 if (!inst_sp)
1688 break;
1689
1690 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
1691
1692 if (inst_size == 0)
1693 break;
1694
1695 m_instruction_list.Append(inst_sp);
1696 data_cursor += inst_size;
1697 inst_addr.Slide(inst_size);
1698 instructions_parsed++;
1699 }
1700
1701 return data_cursor - data_offset;
1702}
1703
1706 "Disassembler that uses LLVM MC to disassemble "
1707 "i386, x86_64, ARM, and ARM64.",
1709
1710 llvm::InitializeAllTargetInfos();
1711 llvm::InitializeAllTargetMCs();
1712 llvm::InitializeAllAsmParsers();
1713 llvm::InitializeAllDisassemblers();
1714}
1715
1719
1720int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc,
1721 uint64_t offset, uint64_t size,
1722 int tag_type, void *tag_bug) {
1723 return static_cast<DisassemblerLLVMC *>(disassembler)
1724 ->OpInfo(pc, offset, size, tag_type, tag_bug);
1725}
1726
1727const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler,
1728 uint64_t value,
1729 uint64_t *type, uint64_t pc,
1730 const char **name) {
1731 return static_cast<DisassemblerLLVMC *>(disassembler)
1732 ->SymbolLookup(value, type, pc, name);
1733}
1734
1736 const lldb_private::ArchSpec &arch, const char *flavor) {
1737 llvm::Triple triple = arch.GetTriple();
1738 if (flavor == nullptr || strcmp(flavor, "default") == 0)
1739 return true;
1740
1741 if (triple.getArch() == llvm::Triple::x86 ||
1742 triple.getArch() == llvm::Triple::x86_64) {
1743 return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0;
1744 } else
1745 return false;
1746}
1747
1748bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); }
1749
1750int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size,
1751 int tag_type, void *tag_bug) {
1752 switch (tag_type) {
1753 default:
1754 break;
1755 case 1:
1756 memset(tag_bug, 0, sizeof(::LLVMOpInfo1));
1757 break;
1758 }
1759 return 0;
1760}
1761
1762const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
1763 uint64_t pc, const char **name) {
1764 if (*type_ptr) {
1765 if (m_exe_ctx && m_inst) {
1766 // std::string remove_this_prior_to_checkin;
1767 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr;
1768 Address value_so_addr;
1769 Address pc_so_addr;
1770 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 ||
1771 target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_be ||
1772 target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) {
1773 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
1775 m_adrp_insn = value;
1776 *name = nullptr;
1777 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1778 return nullptr;
1779 }
1780 // If this instruction is an ADD and
1781 // the previous instruction was an ADRP and
1782 // the ADRP's register and this ADD's register are the same,
1783 // then this is a pc-relative address calculation.
1784 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
1785 m_adrp_insn && m_adrp_address == pc - 4 &&
1786 (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) {
1787 uint32_t addxri_inst;
1788 uint64_t adrp_imm, addxri_imm;
1789 // Get immlo and immhi bits, OR them together to get the ADRP imm
1790 // value.
1791 adrp_imm =
1792 ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3);
1793 // if high bit of immhi after right-shifting set, sign extend
1794 if (adrp_imm & (1ULL << 20))
1795 adrp_imm |= ~((1ULL << 21) - 1);
1796
1797 addxri_inst = value;
1798 addxri_imm = (addxri_inst >> 10) & 0xfff;
1799 // check if 'sh' bit is set, shift imm value up if so
1800 // (this would make no sense, ADRP already gave us this part)
1801 if ((addxri_inst >> (12 + 5 + 5)) & 1)
1802 addxri_imm <<= 12;
1803 value = (m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) +
1804 addxri_imm;
1805 }
1807 m_adrp_insn.reset();
1808 }
1809
1810 if (m_inst->UsingFileAddress()) {
1811 ModuleSP module_sp(m_inst->GetAddress().GetModule());
1812 if (module_sp) {
1813 module_sp->ResolveFileAddress(value, value_so_addr);
1814 module_sp->ResolveFileAddress(pc, pc_so_addr);
1815 }
1816 } else if (target && target->HasLoadedSections()) {
1817 target->ResolveLoadAddress(value, value_so_addr);
1818 target->ResolveLoadAddress(pc, pc_so_addr);
1819 }
1820
1821 SymbolContext sym_ctx;
1822 const SymbolContextItem resolve_scope =
1823 eSymbolContextFunction | eSymbolContextSymbol;
1824 if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) {
1825 pc_so_addr.GetModule()->ResolveSymbolContextForAddress(
1826 pc_so_addr, resolve_scope, sym_ctx);
1827 }
1828
1829 if (value_so_addr.IsValid() && value_so_addr.GetSection()) {
1830 StreamString ss;
1831
1832 bool format_omitting_current_func_name = false;
1833 if (sym_ctx.symbol || sym_ctx.function) {
1834 AddressRange range;
1835 for (uint32_t idx = 0;
1836 sym_ctx.GetAddressRange(resolve_scope, idx, false, range);
1837 ++idx) {
1838 if (range.ContainsLoadAddress(value_so_addr, target)) {
1839 format_omitting_current_func_name = true;
1840 break;
1841 }
1842 }
1843 }
1844
1845 // If the "value" address (the target address we're symbolicating) is
1846 // inside the same SymbolContext as the current instruction pc
1847 // (pc_so_addr), don't print the full function name - just print it
1848 // with DumpStyleNoFunctionName style, e.g. "<+36>".
1849 if (format_omitting_current_func_name) {
1850 value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName,
1852 } else {
1853 value_so_addr.Dump(
1854 &ss, target,
1857 }
1858
1859 if (!ss.GetString().empty()) {
1860 // If Address::Dump returned a multi-line description, most commonly
1861 // seen when we have multiple levels of inlined functions at an
1862 // address, only show the first line.
1863 std::string str = std::string(ss.GetString());
1864 size_t first_eol_char = str.find_first_of("\r\n");
1865 if (first_eol_char != std::string::npos) {
1866 str.erase(first_eol_char);
1867 }
1868 m_inst->AppendComment(str);
1869 }
1870 }
1871 }
1872 }
1873
1874 // TODO: llvm-objdump sets the type_ptr to the
1875 // LLVMDisassembler_ReferenceType_Out_* values
1876 // based on where value_so_addr is pointing, with
1877 // Mach-O specific augmentations in MachODump.cpp. e.g.
1878 // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand
1879 // handles.
1880 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1881 *name = nullptr;
1882 return nullptr;
1883}
#define LLDB_PLUGIN_DEFINE(PluginName)
bool HasDelaySlot(llvm::MCInst &mc_inst) const
bool IsAuthenticated(llvm::MCInst &mc_inst) const
std::unique_ptr< llvm::MCInstrInfo > m_instr_info_up
std::unique_ptr< llvm::MCRegisterInfo > m_reg_info_up
bool CanBranch(llvm::MCInst &mc_inst) const
std::unique_ptr< llvm::MCContext > m_context_up
std::unique_ptr< llvm::MCAsmInfo > m_asm_info_up
void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string, std::string &comments_string)
bool IsBarrier(llvm::MCInst &mc_inst) const
void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style)
static std::unique_ptr< MCDisasmInstance > Create(const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner)
bool GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst, uint64_t &size) const
bool IsLoad(llvm::MCInst &mc_inst) const
bool IsCall(llvm::MCInst &mc_inst) const
std::unique_ptr< llvm::MCSubtargetInfo > m_subtarget_info_up
std::unique_ptr< llvm::MCInstrAnalysis > m_instr_analysis_up
std::unique_ptr< llvm::MCDisassembler > m_disasm_up
std::unique_ptr< llvm::MCInstPrinter > m_instr_printer_up
MCDisasmInstance(std::unique_ptr< llvm::MCInstrInfo > &&instr_info_up, std::unique_ptr< llvm::MCRegisterInfo > &&reg_info_up, std::unique_ptr< llvm::MCSubtargetInfo > &&subtarget_info_up, std::unique_ptr< llvm::MCAsmInfo > &&asm_info_up, std::unique_ptr< llvm::MCContext > &&context_up, std::unique_ptr< llvm::MCDisassembler > &&disasm_up, std::unique_ptr< llvm::MCInstPrinter > &&instr_printer_up, std::unique_ptr< llvm::MCInstrAnalysis > &&instr_analysis_up)
std::optional< uint32_t > m_adrp_insn
DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor, const char *cpu, const char *features)
static const char * SymbolLookupCallback(void *DisInfo, uint64_t ReferenceValue, uint64_t *ReferenceType, uint64_t ReferencePC, const char **ReferenceName)
int OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int TagType, void *TagBug)
const lldb_private::ExecutionContext * m_exe_ctx
const char * SymbolLookup(uint64_t ReferenceValue, uint64_t *ReferenceType, uint64_t ReferencePC, const char **ReferenceName)
std::unique_ptr< MCDisasmInstance > m_disasm_up
static llvm::StringRef GetPluginNameStatic()
friend class InstructionLLVMC
static int OpInfoCallback(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Size, int TagType, void *TagBug)
static lldb::DisassemblerSP CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor, const char *cpu, const char *features)
lldb::addr_t m_adrp_address
bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override
~DisassemblerLLVMC() override
std::unique_ptr< MCDisasmInstance > m_alternate_disasm_up
InstructionLLVMC * m_inst
size_t DecodeInstructions(const lldb_private::Address &base_addr, const lldb_private::DataExtractor &data, lldb::offset_t data_offset, size_t num_instructions, bool append, bool data_from_file) override
Grants exclusive access to the disassembler and initializes it with the given InstructionLLVMC and an...
std::shared_ptr< DisassemblerLLVMC > m_disasm
DisassemblerScope(InstructionLLVMC &i, const lldb_private::ExecutionContext *exe_ctx=nullptr)
std::shared_ptr< DisassemblerLLVMC > operator->()
static std::pair< Operand, llvm::StringRef::const_iterator > ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
bool DoesBranch() override
DisassemblerLLVMC::MCDisasmInstance * GetDisasmToUse(bool &is_alternate_isa)
static void DumpOperand(const Operand &op, Stream &s)
size_t GetByteSize() const
static llvm::StringRef::const_iterator ConsumeWhitespace(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
std::weak_ptr< DisassemblerLLVMC > m_disasm_wp
void CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override
bool IsLoad() override
static std::pair< Operand, llvm::StringRef::const_iterator > ParseARMOffsetAccess(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
DisassemblerLLVMC::MCDisasmInstance * GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm)
void AppendComment(std::string &description)
bool UsingFileAddress() const
bool IsAuthenticated() override
static std::pair< Operand, llvm::StringRef::const_iterator > ParseIntelDerefAccess(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
static std::pair< bool, llvm::StringRef::const_iterator > ConsumeChar(llvm::StringRef::const_iterator osi, const char c, llvm::StringRef::const_iterator ose)
size_t Decode(const lldb_private::Disassembler &disassembler, const lldb_private::DataExtractor &data, lldb::offset_t data_offset) override
bool ParseOperands(llvm::SmallVectorImpl< Instruction::Operand > &operands) override
bool IsBarrier() override
bool HasDelaySlot() override
static std::pair< Operand, llvm::StringRef::const_iterator > ParseARMDerefAccess(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
static std::pair< Operand, llvm::StringRef::const_iterator > ParseRegisterName(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
~InstructionLLVMC() override=default
lldb::InstructionControlFlowKind GetControlFlowKind(const lldb_private::ExecutionContext *exe_ctx) override
InstructionLLVMC(DisassemblerLLVMC &disasm, const lldb_private::Address &address, AddressClass addr_class)
static std::pair< Operand, llvm::StringRef::const_iterator > ParseImmediate(llvm::StringRef::const_iterator osi, llvm::StringRef::const_iterator ose)
A section + offset based address range class.
bool ContainsLoadAddress(const Address &so_addr, Target *target) const
Check if a section offset so_addr when represented as a load address is contained within this object'...
A section + offset based address class.
Definition Address.h:62
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition Address.h:432
@ DumpStyleSectionNameOffset
Display as the section name + offset.
Definition Address.h:74
@ DumpStyleNoFunctionName
Elide the function name; display an offset into the current function.
Definition Address.h:109
@ DumpStyleResolvedDescriptionNoFunctionArguments
Definition Address.h:106
bool Slide(int64_t offset)
Definition Address.h:452
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX, bool all_ranges=false, std::optional< Stream::HighlightSettings > settings=std::nullopt) const
Dump a description of this object to a Stream.
Definition Address.cpp:396
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition Address.cpp:273
bool IsValid() const
Check if the object state is valid.
Definition Address.h:355
AddressClass GetAddressClass() const
Definition Address.cpp:1021
An architecture specification class.
Definition ArchSpec.h:31
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:468
uint32_t GetMinimumOpcodeByteSize() const
Definition ArchSpec.cpp:924
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:677
@ eRISCV_float_abi_double
single precision floating point, +f
Definition ArchSpec.h:97
@ eRISCV_float_abi_quad
double precision floating point, +d
Definition ArchSpec.h:98
@ eRISCV_float_abi_single
soft float
Definition ArchSpec.h:96
uint32_t GetMaximumOpcodeByteSize() const
Definition ArchSpec.cpp:931
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
An data extractor class.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
virtual const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const
Peek at a bytes at offset.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
const uint8_t * GetDataStart() const
Get the data start pointer.
lldb::offset_t BytesLeft(lldb::offset_t offset) const
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
InstructionList m_instruction_list
Disassembler(const ArchSpec &arch, const char *flavor)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Target * GetTargetPtr() const
Returns a pointer to the target object.
Instruction(const Address &address, AddressClass addr_class=AddressClass::eInvalid)
const char * GetOperands(const ExecutionContext *exe_ctx, bool markup=false)
uint32_t GetByteSize() const
Definition Opcode.h:231
const void * GetOpcodeBytes() const
Definition Opcode.h:225
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
An error handling class.
Definition Status.h:118
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
bool GetAddressRange(uint32_t scope, uint32_t range_idx, bool use_inline_block_range, AddressRange &range) const
Get the address range contained within a symbol context.
Symbol * symbol
The Symbol for a given query.
Disassembler::HexImmediateStyle GetHexImmediateStyle() const
Definition Target.cpp:5089
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow, bool allow_section_end=false)
Definition Target.cpp:3323
const ArchSpec & GetArchitecture() const
Definition Target.h:1153
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
uint64_t offset_t
Definition lldb-types.h:85
std::shared_ptr< lldb_private::Instruction > InstructionSP
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
ByteOrder
Byte ordering definitions.
InstructionControlFlowKind
Architecture-agnostic categorization of instructions for traversing the control flow of a trace.
@ eInstructionControlFlowKindReturn
The instruction is a near (function) return.
@ eInstructionControlFlowKindFarJump
The instruction is a jump-like far transfer.
@ eInstructionControlFlowKindOther
The instruction is something not listed below, i.e.
@ eInstructionControlFlowKindFarCall
The instruction is a call-like far transfer.
@ eInstructionControlFlowKindFarReturn
The instruction is a return-like far transfer.
@ eInstructionControlFlowKindUnknown
The instruction could not be classified.
@ eInstructionControlFlowKindJump
The instruction is a near unconditional jump.
@ eInstructionControlFlowKindCall
The instruction is a near (function) call.
@ eInstructionControlFlowKindCondJump
The instruction is a near conditional jump.
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
std::optional< InstructionOpcodeAndModrm > InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, bool is_exec_mode_64b)
Decode an instruction into opcode, modrm and opcode_len.
lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, Opcode m_opcode)
lldb::InstructionControlFlowKind MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm)
Determine the InstructionControlFlowKind based on opcode and modrm bytes.
enum lldb_private::Instruction::Operand::Type m_type
std::vector< Operand > m_children
These are the three values deciding instruction control flow kind.