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"
59 static std::unique_ptr<MCDisasmInstance>
60 Create(
const char *triple,
const char *cpu,
const char *features_str,
65 bool GetMCInst(
const uint8_t *opcode_data,
size_t opcode_data_len,
68 std::string &inst_string, std::string &comments_string);
72 bool CanBranch(llvm::MCInst &mc_inst)
const;
74 bool IsCall(llvm::MCInst &mc_inst)
const;
75 bool IsLoad(llvm::MCInst &mc_inst)
const;
76 bool IsBarrier(llvm::MCInst &mc_inst)
const;
81 std::unique_ptr<llvm::MCRegisterInfo> &®_info_up,
82 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
83 llvm::MCTargetOptions mc_options,
84 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
85 std::unique_ptr<llvm::MCContext> &&context_up,
86 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
87 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,
88 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up);
139 uint8_t opcode_len = opcode_and_modrm.
opcode_len;
140 uint8_t modrm = opcode_and_modrm.
modrm;
145 if (opcode >= 0x70 && opcode <= 0x7F) {
152 if (opcode >= 0x80 && opcode <= 0x8F) {
165 if (opcode_len == 1) {
166 uint8_t modrm_reg = (modrm >> 3) & 7;
169 else if (modrm_reg == 3)
171 else if (modrm_reg == 4)
173 else if (modrm_reg == 5)
229 if (opcode_len == 2) {
269std::optional<InstructionOpcodeAndModrm>
271 bool is_exec_mode_64b) {
273 bool prefix_done =
false;
280 while (!prefix_done) {
281 if (op_idx >= bytes_len)
320 if (is_exec_mode_64b)
328 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
335 ret.
modrm = inst_bytes[op_idx + 3];
339 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
343 ret.
opcode_len = inst_bytes[op_idx + 1] & 0x1f;
345 ret.
modrm = inst_bytes[op_idx + 4];
350 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {
354 ret.
opcode_len = inst_bytes[op_idx + 1] & 0x03;
356 ret.
modrm = inst_bytes[op_idx + 5];
366 ret.
modrm = inst_bytes[op_idx + 1];
376 ret.
modrm = inst_bytes[op_idx + 1];
380 ret.
modrm = inst_bytes[op_idx + 1];
384 ret.
modrm = inst_bytes[op_idx + 1];
388 ret.
modrm = inst_bytes[op_idx + 1];
391 ret.
modrm = inst_bytes[op_idx + 1];
400 std::optional<InstructionOpcodeAndModrm> ret;
426 disasm.shared_from_this())) {}
467 const ArchSpec &arch = disasm->GetArchitecture();
472 if (min_op_byte_size == max_op_byte_size) {
477 switch (min_op_byte_size) {
500 bool is_alternate_isa =
false;
504 const llvm::Triple::ArchType machine = arch.
GetMachine();
505 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) {
506 if (machine == llvm::Triple::thumb || is_alternate_isa) {
507 uint32_t thumb_opcode = data.
GetU16(&data_offset);
508 if ((thumb_opcode & 0xe000) != 0xe000 ||
509 ((thumb_opcode & 0x1800u) == 0)) {
510 m_opcode.SetOpcode16(thumb_opcode, byte_order);
514 thumb_opcode |= data.
GetU16(&data_offset);
515 m_opcode.SetOpcode16_2(thumb_opcode, byte_order);
525 uint8_t *opcode_data =
526 const_cast<uint8_t *
>(data.
PeekData(data_offset, 1));
527 const size_t opcode_data_len = data.
BytesLeft(data_offset);
531 uint64_t inst_size = 0;
533 pc, inst, inst_size);
536 if (inst_size != 0) {
538 m_opcode.SetOpcode16_32TupleBytes(opcode_data, inst_size,
541 m_opcode.SetOpcodeBytes(opcode_data, inst_size);
563 if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86)
565 else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
578 std::string out_string;
579 std::string markup_out_string;
580 std::string comment_string;
581 std::string markup_comment_string;
588 mc_disasm_ptr = disasm->m_alternate_disasm_up.get();
590 mc_disasm_ptr = disasm->m_disasm_up.get();
595 bool use_hex_immediates =
true;
615 uint64_t inst_size = 0;
616 bool valid = mc_disasm_ptr->
GetMCInst(opcode_data, opcode_data_len,
pc,
619 if (valid && inst_size > 0) {
620 mc_disasm_ptr->
SetStyle(use_hex_immediates, hex_style);
622 const bool saved_use_color = mc_disasm_ptr->
GetUseColor();
624 mc_disasm_ptr->
PrintMCInst(inst,
pc, out_string, comment_string);
627 markup_comment_string);
630 if (!comment_string.empty()) {
635 if (inst_size == 0) {
643 const uint8_t uval8 = data.
GetU8(&offset);
644 m_opcode.SetOpcode8(uval8, byte_order);
646 mnemonic_strm.
Printf(
"0x%2.2x", uval8);
649 const uint16_t uval16 = data.
GetU16(&offset);
650 m_opcode.SetOpcode16(uval16, byte_order);
652 mnemonic_strm.
Printf(
"0x%4.4x", uval16);
655 const uint32_t uval32 = data.
GetU32(&offset);
656 m_opcode.SetOpcode32(uval32, byte_order);
658 mnemonic_strm.
Printf(
"0x%8.8x", uval32);
661 const uint64_t uval64 = data.
GetU64(&offset);
662 m_opcode.SetOpcode64(uval64, byte_order);
664 mnemonic_strm.
Printf(
"0x%16.16" PRIx64, uval64);
670 const uint8_t *bytes = data.
PeekData(offset, inst_size);
671 if (bytes ==
nullptr)
674 m_opcode.SetOpcodeBytes(bytes, inst_size);
675 mnemonic_strm.
Printf(
"0x%2.2x", bytes[0]);
676 for (uint32_t i = 1; i < inst_size; ++i)
677 mnemonic_strm.
Printf(
" 0x%2.2x", bytes[i]);
686 llvm::StringRef(
"[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"));
688 llvm::SmallVector<llvm::StringRef, 4> matches;
689 if (s_regex.
Execute(out_string, &matches)) {
694 if (s_regex.
Execute(markup_out_string, &matches)) {
729 static llvm::StringRef::const_iterator
731 llvm::StringRef::const_iterator ose) {
746 static std::pair<bool, llvm::StringRef::const_iterator>
748 llvm::StringRef::const_iterator ose) {
752 if (osi != ose && *osi == c) {
757 return std::make_pair(found, osi);
760 static std::pair<Operand, llvm::StringRef::const_iterator>
762 llvm::StringRef::const_iterator ose) {
764 ret.
m_type = Operand::Type::Register;
770 if (*osi >=
'0' && *osi <=
'9') {
772 return std::make_pair(
Operand(), osi);
776 }
else if (*osi >=
'a' && *osi <=
'z') {
782 return std::make_pair(
Operand(), osi);
785 return std::make_pair(ret, osi);
789 return std::make_pair(
Operand(), osi);
798 return std::make_pair(ret, osi);
801 static std::pair<Operand, llvm::StringRef::const_iterator>
803 llvm::StringRef::const_iterator ose) {
805 ret.
m_type = Operand::Type::Immediate;
812 if (*osi >=
'0' && *osi <=
'9') {
814 }
else if (*osi >=
'a' && *osi <=
'f') {
818 return std::make_pair(
Operand(), osi);
824 return std::make_pair(
Operand(), osi);
826 ret.
m_immediate = strtoull(str.c_str(),
nullptr, 0);
827 return std::make_pair(ret, osi);
834 return std::make_pair(
Operand(), osi);
840 return std::make_pair(
Operand(), osi);
847 return std::make_pair(
Operand(), osi);
854 ret.
m_immediate = strtoull(str.c_str(),
nullptr, 0);
855 return std::make_pair(ret, osi);
859 static std::pair<Operand, llvm::StringRef::const_iterator>
861 llvm::StringRef::const_iterator ose) {
862 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
864 if (offset_and_iterator.first.IsValid()) {
865 osi = offset_and_iterator.second;
871 return std::make_pair(
Operand(), osi);
874 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
876 if (base_and_iterator.first.IsValid()) {
877 osi = base_and_iterator.second;
879 return std::make_pair(
Operand(), osi);
884 return std::make_pair(
Operand(), osi);
887 std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator =
889 if (index_and_iterator.first.IsValid()) {
890 osi = index_and_iterator.second;
892 return std::make_pair(
Operand(), osi);
897 return std::make_pair(
Operand(), osi);
900 std::pair<Operand, llvm::StringRef::const_iterator>
902 if (index_and_iterator.first.IsValid()) {
903 osi = index_and_iterator.second;
905 return std::make_pair(
Operand(), osi);
910 return std::make_pair(
Operand(), osi);
914 product.
m_type = Operand::Type::Product;
915 product.
m_children.push_back(index_and_iterator.first);
916 product.
m_children.push_back(multiplier_and_iterator.first);
919 index.
m_type = Operand::Type::Sum;
920 index.
m_children.push_back(base_and_iterator.first);
923 if (offset_and_iterator.first.IsValid()) {
925 offset.
m_type = Operand::Type::Sum;
926 offset.
m_children.push_back(offset_and_iterator.first);
930 deref.
m_type = Operand::Type::Dereference;
932 return std::make_pair(deref, osi);
935 deref.
m_type = Operand::Type::Dereference;
937 return std::make_pair(deref, osi);
942 static std::pair<Operand, llvm::StringRef::const_iterator>
944 llvm::StringRef::const_iterator ose) {
945 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
947 if (offset_and_iterator.first.IsValid()) {
948 osi = offset_and_iterator.second;
954 return std::make_pair(
Operand(), osi);
957 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
959 if (base_and_iterator.first.IsValid()) {
960 osi = base_and_iterator.second;
962 return std::make_pair(
Operand(), osi);
967 return std::make_pair(
Operand(), osi);
970 if (offset_and_iterator.first.IsValid()) {
972 offset.
m_type = Operand::Type::Sum;
973 offset.
m_children.push_back(offset_and_iterator.first);
974 offset.
m_children.push_back(base_and_iterator.first);
977 deref.
m_type = Operand::Type::Dereference;
979 return std::make_pair(deref, osi);
982 deref.
m_type = Operand::Type::Dereference;
983 deref.
m_children.push_back(base_and_iterator.first);
984 return std::make_pair(deref, osi);
989 static std::pair<Operand, llvm::StringRef::const_iterator>
991 llvm::StringRef::const_iterator ose) {
995 return std::make_pair(
Operand(), osi);
998 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
1000 if (base_and_iterator.first.IsValid()) {
1001 osi = base_and_iterator.second;
1003 return std::make_pair(
Operand(), osi);
1006 std::tie(found, osi) =
ConsumeChar(osi,
',', ose);
1008 return std::make_pair(
Operand(), osi);
1011 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
1013 if (offset_and_iterator.first.IsValid()) {
1014 osi = offset_and_iterator.second;
1017 std::tie(found, osi) =
ConsumeChar(osi,
']', ose);
1019 return std::make_pair(
Operand(), osi);
1023 offset.
m_type = Operand::Type::Sum;
1024 offset.
m_children.push_back(offset_and_iterator.first);
1025 offset.
m_children.push_back(base_and_iterator.first);
1028 deref.
m_type = Operand::Type::Dereference;
1030 return std::make_pair(deref, osi);
1034 static std::pair<Operand, llvm::StringRef::const_iterator>
1036 llvm::StringRef::const_iterator ose) {
1038 std::tie(found, osi) =
ConsumeChar(osi,
'[', ose);
1040 return std::make_pair(
Operand(), osi);
1043 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
1045 if (base_and_iterator.first.IsValid()) {
1046 osi = base_and_iterator.second;
1048 return std::make_pair(
Operand(), osi);
1051 std::tie(found, osi) =
ConsumeChar(osi,
']', ose);
1053 return std::make_pair(
Operand(), osi);
1057 deref.
m_type = Operand::Type::Dereference;
1058 deref.
m_children.push_back(base_and_iterator.first);
1059 return std::make_pair(deref, osi);
1064 case Operand::Type::Dereference:
1068 case Operand::Type::Immediate:
1074 case Operand::Type::Invalid:
1077 case Operand::Type::Product:
1084 case Operand::Type::Register:
1087 case Operand::Type::Sum:
1099 const char *operands_string =
GetOperands(
nullptr);
1101 if (!operands_string) {
1105 llvm::StringRef operands_ref(operands_string);
1107 llvm::StringRef::const_iterator osi = operands_ref.begin();
1108 llvm::StringRef::const_iterator ose = operands_ref.end();
1110 while (osi != ose) {
1112 llvm::StringRef::const_iterator iter;
1127 operands.push_back(operand);
1132 std::pair<bool, llvm::StringRef::const_iterator> found_and_iter =
1134 if (found_and_iter.first) {
1135 osi = found_and_iter.second;
1143 if (disasm_sp && operands.size() > 1) {
1145 switch (disasm_sp->GetArchitecture().GetMachine()) {
1148 case llvm::Triple::x86:
1149 case llvm::Triple::x86_64:
1150 operands[operands.size() - 1].m_clobbered =
true;
1152 case llvm::Triple::arm:
1153 operands[0].m_clobbered =
true;
1161 ss.
Printf(
"[%s] expands to %zu operands:\n", operands_string,
1163 for (
const Operand &operand : operands) {
1212 bool is_alternate_isa;
1217 const size_t opcode_data_len = data.
GetByteSize();
1219 uint64_t inst_size = 0;
1220 const bool valid = mc_disasm_ptr->
GetMCInst(opcode_data, opcode_data_len,
1221 pc, inst, inst_size);
1237 is_alternate_isa =
false;
1239 if (disasm->m_alternate_disasm_up) {
1243 is_alternate_isa =
true;
1244 return disasm->m_alternate_disasm_up.get();
1247 return disasm->m_disasm_up.get();
1253std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
1256 const char *features_str,
1259 using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;
1261 llvm::Triple triple(triple_name);
1264 const llvm::Target *curr_target =
1265 llvm::TargetRegistry::lookupTarget(triple,
Status);
1269 std::unique_ptr<llvm::MCInstrInfo> instr_info_up(
1270 curr_target->createMCInstrInfo());
1274 std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(
1275 curr_target->createMCRegInfo(triple));
1279 std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(
1280 curr_target->createMCSubtargetInfo(triple, cpu, features_str));
1281 if (!subtarget_info_up)
1284 llvm::MCTargetOptions MCOptions;
1285 std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
1286 curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));
1290 std::unique_ptr<llvm::MCContext> context_up(
new llvm::MCContext(
1291 llvm::Triple(triple), *asm_info_up, *reg_info_up, *subtarget_info_up));
1295 std::unique_ptr<llvm::MCDisassembler> disasm_up(
1296 curr_target->createMCDisassembler(*subtarget_info_up, *context_up));
1300 std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(
1301 curr_target->createMCRelocationInfo(triple, *context_up));
1305 std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
1306 curr_target->createMCSymbolizer(
1308 context_up.get(), std::move(rel_info_up)));
1309 disasm_up->setSymbolizer(std::move(symbolizer_up));
1311 unsigned asm_printer_variant =
1312 flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;
1314 std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(
1315 curr_target->createMCInstPrinter(llvm::Triple{triple},
1316 asm_printer_variant, *asm_info_up,
1317 *instr_info_up, *reg_info_up));
1318 if (!instr_printer_up)
1321 instr_printer_up->setPrintBranchImmAsAddress(
true);
1324 std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up(
1325 curr_target->createMCInstrAnalysis(instr_info_up.get()));
1328 std::move(instr_info_up), std::move(reg_info_up),
1329 std::move(subtarget_info_up), MCOptions, std::move(asm_info_up),
1330 std::move(context_up), std::move(disasm_up), std::move(instr_printer_up),
1331 std::move(instr_analysis_up)));
1335 std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
1336 std::unique_ptr<llvm::MCRegisterInfo> &®_info_up,
1337 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
1338 llvm::MCTargetOptions mc_options,
1339 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
1340 std::unique_ptr<llvm::MCContext> &&context_up,
1341 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
1342 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,
1343 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up)
1356 size_t opcode_data_len,
1358 llvm::MCInst &mc_inst,
1359 uint64_t &size)
const {
1360 llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
1361 llvm::MCDisassembler::DecodeStatus status;
1363 status =
m_disasm_up->getInstruction(mc_inst, size, data,
pc, llvm::nulls());
1364 if (status == llvm::MCDisassembler::Success)
1371 llvm::MCInst &mc_inst,
lldb::addr_t pc, std::string &inst_string,
1372 std::string &comments_string) {
1373 llvm::raw_string_ostream inst_stream(inst_string);
1374 llvm::raw_string_ostream comments_stream(comments_string);
1382 static std::string g_newlines(
"\r\n");
1384 for (
size_t newline_pos = 0;
1385 (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) !=
1386 comments_string.npos;
1388 comments_string.replace(comments_string.begin() + newline_pos,
1389 comments_string.begin() + newline_pos + 1, 1,
' ');
1396 switch (hex_style) {
1415 llvm::MCInst &mc_inst)
const {
1423 llvm::MCInst &mc_inst)
const {
1438 llvm::MCInst &mc_inst)
const {
1443 llvm::MCInst &mc_inst)
const {
1449 bool IsBrkC47x =
false;
1450 if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) {
1451 const llvm::MCOperand &Op0 = mc_inst.getOperand(0);
1452 if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474)
1456 return InstrDesc.isAuthenticated() || IsBrkC47x;
1460 llvm::StringRef subtarget_features, std::string &user_feature_overrides) {
1462 llvm::SmallVector<std::string, 0> valid_user_flags;
1463 llvm::StringSet<> user_disabled_features;
1465 for (llvm::StringRef flag : llvm::split(user_feature_overrides,
",")) {
1466 bool is_valid =
true;
1472 std::string warning_reason;
1473 llvm::raw_string_ostream ostream(warning_reason);
1479 if (flag.size() < 2) {
1481 ostream <<
"must have a name";
1482 }
else if (std::isdigit(
static_cast<unsigned char>(flag[1]))) {
1484 ostream <<
"name cannot start with a digit";
1485 }
else if (flag.front() !=
'+' && flag.front() !=
'-') {
1487 ostream <<
"must start with '+' or '-'";
1488 }
else if (!std::all_of(flag.begin() + 1, flag.end(), [](
unsigned char c) {
1489 return std::isalnum(c) || c ==
'_' || c ==
'-';
1492 ostream <<
"contains invalid characters";
1495 std::string message =
1496 (
"feature flag '" + flag +
"': " + warning_reason).str();
1500 valid_user_flags.push_back(flag.str());
1502 if (flag.starts_with(
'-'))
1503 user_disabled_features.insert(flag.substr(1));
1507 llvm::SmallVector<std::string, 0> final_features;
1510 if (!subtarget_features.empty()) {
1511 for (llvm::StringRef flag : llvm::split(subtarget_features,
",")) {
1519 bool add_flag =
true;
1520 if (flag.size() >= 2 && flag.starts_with(
'+')) {
1521 llvm::StringRef feature_name = flag.substr(1);
1522 if (user_disabled_features.count(feature_name))
1526 final_features.push_back(flag.str());
1531 final_features.insert(final_features.end(), valid_user_flags.begin(),
1532 valid_user_flags.end());
1533 user_feature_overrides = llvm::join(final_features,
",");
1537 const char *flavor_string,
1538 const char *cpu_string,
1539 const char *features_string)
1544 m_flavor.assign(
"default");
1547 const bool cpu_or_features_overriden = cpu_string || features_string;
1548 unsigned flavor = ~0U;
1553 if (triple.getArch() == llvm::Triple::x86 ||
1554 triple.getArch() == llvm::Triple::x86_64) {
1555 if (m_flavor ==
"intel") {
1563 if (triple.getArch() == llvm::Triple::arm) {
1564 std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str());
1566 if (thumb_arch_name.size() > 3) {
1567 thumb_arch_name.erase(0, 3);
1568 thumb_arch_name.insert(0,
"thumb");
1570 thumb_arch_name =
"thumbv9.3a";
1572 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name));
1580 if (triple.getArch() == llvm::Triple::arm &&
1581 triple.getSubArch() == llvm::Triple::NoSubArch)
1582 triple.setArchName(
"armv9.3a");
1584 std::string features_str =
1585 features_string ? std::string(features_string) :
"";
1586 const char *triple_str = triple.getTriple().c_str();
1589 if (arch.IsAlwaysThumbInstructions()) {
1590 triple_str = thumb_arch.GetTriple().getTriple().c_str();
1591 if (!features_string)
1592 features_str +=
"+fp-armv8,";
1595 const char *cpu = cpu_string;
1597 if (!cpu_or_features_overriden) {
1598 switch (arch.GetCore()) {
1645 if (arch.IsMIPS() && !cpu_or_features_overriden) {
1646 uint32_t arch_flags = arch.GetFlags();
1648 features_str +=
"+msa,";
1650 features_str +=
"+dsp,";
1652 features_str +=
"+dspr2,";
1657 if (triple.isAArch64() && !cpu_or_features_overriden) {
1658 features_str +=
"+all,";
1659 if (triple.getVendor() == llvm::Triple::Apple)
1660 cpu =
"apple-latest";
1663 if (triple.isRISCV()) {
1664 auto subtarget_features = arch.GetSubtargetFeatures().getString();
1665 if (!cpu_or_features_overriden) {
1666 if (!subtarget_features.empty()) {
1667 features_str += subtarget_features;
1669 uint32_t arch_flags = arch.GetFlags();
1671 features_str +=
"+c,";
1673 features_str +=
"+e,";
1676 features_str +=
"+f,";
1679 features_str +=
"+f,+d,";
1682 features_str +=
"+f,+d,+q,";
1685 features_str +=
"+a,+m,";
1689 UpdateSubtargetFeatures(subtarget_features, features_str);
1696 m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),
1699 llvm::Triple::ArchType llvm_arch = triple.getArch();
1703 if (llvm_arch == llvm::Triple::arm) {
1704 std::string thumb_triple(thumb_arch.GetTriple().getTriple());
1705 m_alternate_disasm_up = MCDisasmInstance::Create(
1706 thumb_triple.c_str(),
"", features_str.c_str(), flavor, *
this);
1707 if (!m_alternate_disasm_up)
1708 m_disasm_up.reset();
1710 }
else if (arch.IsMIPS()) {
1712 uint32_t arch_flags = arch.GetFlags();
1714 features_str +=
"+mips16,";
1716 features_str +=
"+micromips,";
1718 m_alternate_disasm_up = MCDisasmInstance::Create(
1719 triple_str, cpu, features_str.c_str(), flavor, *
this);
1720 if (!m_alternate_disasm_up)
1721 m_disasm_up.reset();
1730 const char *features) {
1731 if (arch.
GetTriple().getArch() != llvm::Triple::UnknownArch) {
1733 std::make_shared<DisassemblerLLVMC>(arch, flavor, cpu, features);
1734 if (disasm_sp && disasm_sp->IsValid())
1743 size_t num_instructions,
1744 bool append,
bool data_from_file) {
1752 uint32_t data_cursor = data_offset;
1754 uint32_t instructions_parsed = 0;
1757 while (data_cursor < data_byte_size &&
1758 instructions_parsed < num_instructions) {
1771 uint32_t inst_size = inst_sp->Decode(*
this, data, data_cursor);
1777 data_cursor += inst_size;
1778 inst_addr.
Slide(inst_size);
1779 instructions_parsed++;
1782 return data_cursor - data_offset;
1787 "Disassembler that uses LLVM MC to disassemble "
1788 "i386, x86_64, ARM, and ARM64.",
1791 llvm::InitializeAllTargetInfos();
1792 llvm::InitializeAllTargetMCs();
1793 llvm::InitializeAllAsmParsers();
1794 llvm::InitializeAllDisassemblers();
1802 uint64_t offset, uint64_t size,
1803 int tag_type,
void *tag_bug) {
1805 ->
OpInfo(
pc, offset, size, tag_type, tag_bug);
1810 uint64_t *type, uint64_t
pc,
1811 const char **name) {
1819 if (flavor ==
nullptr || strcmp(flavor,
"default") == 0)
1822 if (triple.getArch() == llvm::Triple::x86 ||
1823 triple.getArch() == llvm::Triple::x86_64) {
1824 return strcmp(flavor,
"intel") == 0 || strcmp(flavor,
"att") == 0;
1832 int tag_type,
void *tag_bug) {
1837 memset(tag_bug, 0,
sizeof(::LLVMOpInfo1));
1844 uint64_t
pc,
const char **name) {
1854 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
1858 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1865 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
1868 uint32_t addxri_inst;
1869 uint64_t adrp_imm, addxri_imm;
1875 if (adrp_imm & (1ULL << 20))
1876 adrp_imm |= ~((1ULL << 21) - 1);
1878 addxri_inst = value;
1879 addxri_imm = (addxri_inst >> 10) & 0xfff;
1882 if ((addxri_inst >> (12 + 5 + 5)) & 1)
1884 value = (
m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) +
1891 if (
m_inst->UsingFileAddress()) {
1894 module_sp->ResolveFileAddress(value, value_so_addr);
1895 module_sp->ResolveFileAddress(
pc, pc_so_addr);
1903 const SymbolContextItem resolve_scope =
1904 eSymbolContextFunction | eSymbolContextSymbol;
1906 pc_so_addr.
GetModule()->ResolveSymbolContextForAddress(
1907 pc_so_addr, resolve_scope, sym_ctx);
1913 bool format_omitting_current_func_name =
false;
1916 for (uint32_t idx = 0;
1920 format_omitting_current_func_name =
true;
1930 if (format_omitting_current_func_name) {
1944 std::string str = std::string(ss.
GetString());
1945 size_t first_eol_char = str.find_first_of(
"\r\n");
1946 if (first_eol_char != std::string::npos) {
1947 str.erase(first_eol_char);
1949 m_inst->AppendComment(str);
1961 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
#define LLDB_PLUGIN_DEFINE(PluginName)
bool HasDelaySlot(llvm::MCInst &mc_inst) const
llvm::MCTargetOptions m_mc_options
MCDisasmInstance(std::unique_ptr< llvm::MCInstrInfo > &&instr_info_up, std::unique_ptr< llvm::MCRegisterInfo > &®_info_up, std::unique_ptr< llvm::MCSubtargetInfo > &&subtarget_info_up, llvm::MCTargetOptions mc_options, 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)
~MCDisasmInstance()=default
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
void SetUseColor(bool use_color)
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)
static void UpdateSubtargetFeatures(llvm::StringRef subtarget_features, std::string &user_feature_overrides)
This function merges the user overwrite features (provided via -Y option) with the subtarget features...
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 m_has_visited_instruction
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.
lldb::SectionSP GetSection() const
Get const accessor for the section.
@ DumpStyleSectionNameOffset
Display as the section name + offset.
@ DumpStyleNoFunctionName
Elide the function name; display an offset into the current function.
@ DumpStyleResolvedDescriptionNoFunctionArguments
bool Slide(int64_t offset)
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.
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
bool IsValid() const
Check if the object state is valid.
AddressClass GetAddressClass() const
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
uint32_t GetMinimumOpcodeByteSize() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
@ eRISCV_float_abi_double
single precision floating point, +f
@ eRISCV_float_abi_quad
double precision floating point, +d
@ eRISCV_float_abi_single
soft float
uint32_t GetMaximumOpcodeByteSize() const
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
static void ReportWarning(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report warning events.
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)
std::string m_markup_mnemonics
const char * GetOperands(const ExecutionContext *exe_ctx, bool markup=false)
std::string m_opcode_name
std::string m_markup_opcode_name
AddressClass GetAddressClass()
static constexpr size_t kMaxByteSize
The size in bytes of the fixed buffer used to store opcode bytes.
uint32_t GetByteSize() const
const void * GetOpcodeBytes() const
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...
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
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.
bool GetUseHexImmediates() const
Disassembler::HexImmediateStyle GetHexImmediateStyle() const
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow, bool allow_section_end=false)
const ArchSpec & GetArchitecture() const
#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.
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. E.g. FAR JMP.
@ 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.
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.