44 #include "llvm/ADT/Triple.h"
45 #include "llvm/Support/Compiler.h"
53 #define DEFAULT_DISASM_BYTE_SIZE 32
58 DisassemblerSP Disassembler::FindPlugin(
const ArchSpec &arch,
60 const char *plugin_name) {
64 DisassemblerCreateInstance create_callback =
nullptr;
68 PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name);
69 if (create_callback) {
70 DisassemblerSP disassembler_sp(create_callback(arch, flavor));
73 return disassembler_sp;
77 (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
80 DisassemblerSP disassembler_sp(create_callback(arch, flavor));
83 return disassembler_sp;
86 return DisassemblerSP();
89 DisassemblerSP Disassembler::FindPluginForTarget(
const Target &target,
92 const char *plugin_name) {
93 if (flavor ==
nullptr) {
97 if (arch.
GetTriple().getArch() == llvm::Triple::x86 ||
98 arch.
GetTriple().getArch() == llvm::Triple::x86_64)
101 return FindPlugin(arch, flavor, plugin_name);
116 if (is_resolved && resolved_addr.
IsValid())
117 return resolved_addr;
122 lldb::DisassemblerSP Disassembler::DisassembleRange(
123 const ArchSpec &arch,
const char *plugin_name,
const char *flavor,
131 lldb::DisassemblerSP disasm_sp =
132 Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
137 const size_t bytes_disassembled = disasm_sp->ParseInstructions(
138 target, range.
GetBaseAddress(), {Limit::Bytes, range.GetByteSize()},
139 nullptr, force_live_memory);
140 if (bytes_disassembled == 0)
147 Disassembler::DisassembleBytes(
const ArchSpec &arch,
const char *plugin_name,
148 const char *flavor,
const Address &start,
149 const void *src,
size_t src_len,
150 uint32_t num_instructions,
bool data_from_file) {
154 lldb::DisassemblerSP disasm_sp =
155 Disassembler::FindPlugin(arch, flavor, plugin_name);
163 (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions,
false,
169 const char *plugin_name,
const char *flavor,
172 bool mixed_source_and_assembly,
178 lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
183 const bool force_live_memory =
true;
184 size_t bytes_disassembled = disasm_sp->ParseInstructions(
185 exe_ctx.
GetTargetRef(), address, limit, &strm, force_live_memory);
186 if (bytes_disassembled == 0)
189 disasm_sp->PrintInstructions(debugger, arch, exe_ctx,
190 mixed_source_and_assembly,
191 num_mixed_context_lines, options, strm);
208 if (func_decl_file != prologue_end_line.
file &&
213 decl_line.
file = func_decl_file;
214 decl_line.
line = func_decl_line;
221 void Disassembler::AddLineToSourceLineTables(
223 std::map<
FileSpec, std::set<uint32_t>> &source_lines_seen) {
225 auto source_lines_seen_pos = source_lines_seen.find(line.
file);
226 if (source_lines_seen_pos == source_lines_seen.end()) {
227 std::set<uint32_t> lines;
228 lines.insert(line.
line);
229 source_lines_seen.emplace(line.
file, lines);
231 source_lines_seen_pos->second.insert(line.
line);
236 bool Disassembler::ElideMixedSourceAndDisassemblyLine(
250 avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
255 OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
256 &exe_ctx,
"target.process.thread.step-avoid-regexp",
false,
error);
257 if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
265 if (avoid_regex && sc.
symbol !=
nullptr) {
266 const char *function_name =
269 if (function_name && avoid_regex->
Execute(function_name)) {
280 bool mixed_source_and_assembly,
284 size_t num_instructions_found = GetInstructionList().GetSize();
286 const uint32_t max_opcode_byte_size =
287 GetInstructionList().GetMaxOpcocdeByteSize();
291 const Address *pc_addr_ptr =
nullptr;
302 eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
303 const bool use_inline_block_range =
false;
311 FormatEntity::Parse(
"${addr}: ", format);
312 disassembly_format = &format;
323 std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
324 Symbol *previous_symbol =
nullptr;
326 size_t address_text_size = 0;
327 for (
size_t i = 0; i < num_instructions_found; ++i) {
328 Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
333 const SymbolContextItem resolve_mask = eSymbolContextFunction |
334 eSymbolContextSymbol |
335 eSymbolContextLineEntry;
337 module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
340 Debugger::FormatDisassemblerAddress(disassembly_format, &sc,
nullptr,
341 &exe_ctx, &addr, strmstr);
343 if (cur_line > address_text_size)
344 address_text_size = cur_line;
354 if (sc.
symbol != previous_symbol) {
355 SourceLine decl_line = GetFunctionDeclLineEntry(sc);
356 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
357 AddLineToSourceLineTables(decl_line, source_lines_seen);
364 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
365 AddLineToSourceLineTables(this_line, source_lines_seen);
374 previous_symbol =
nullptr;
376 for (
size_t i = 0; i < num_instructions_found; ++i) {
377 Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
381 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
386 ModuleSP module_sp(addr.GetModule());
388 uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
389 addr, eSymbolContextEverything, sc);
391 if (mixed_source_and_assembly) {
396 if (previous_symbol != sc.
symbol) {
401 if (previous_symbol !=
nullptr)
404 previous_symbol = sc.
symbol;
407 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
408 prologue_end_line)) {
413 if (func_decl_file == prologue_end_line.
file ||
418 for (
uint32_t lineno = func_decl_line;
419 lineno <= prologue_end_line.
line; lineno++) {
421 this_line.
file = func_decl_file;
422 this_line.
line = lineno;
423 source_lines_to_display.
lines.push_back(this_line);
427 if (source_lines_to_display.
lines.size() > 0)
429 source_lines_to_display.
lines.size() - 1;
434 current_source_line_range);
441 current_source_line_range);
448 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
455 if (this_line != previous_line) {
457 std::vector<uint32_t> previous_lines;
459 i < num_mixed_context_lines &&
460 (this_line.
line - num_mixed_context_lines) > 0;
463 this_line.
line - num_mixed_context_lines + i;
464 auto pos = source_lines_seen.find(this_line.
file);
465 if (pos != source_lines_seen.end()) {
466 if (pos->second.count(line) == 1) {
467 previous_lines.clear();
469 previous_lines.push_back(line);
473 for (
size_t i = 0; i < previous_lines.size(); i++) {
475 previous_line.
file = this_line.
file;
476 previous_line.
line = previous_lines[i];
477 auto pos = source_lines_seen.find(previous_line.
file);
478 if (pos != source_lines_seen.end()) {
479 pos->second.insert(previous_line.
line);
481 source_lines_to_display.
lines.push_back(previous_line);
484 source_lines_to_display.
lines.push_back(this_line);
486 source_lines_to_display.
lines.size() - 1;
488 for (
uint32_t i = 0; i < num_mixed_context_lines; i++) {
491 next_line.
line = this_line.
line + i + 1;
492 auto pos = source_lines_seen.find(next_line.
file);
493 if (pos != source_lines_seen.end()) {
494 if (pos->second.count(next_line.
line) == 1)
496 pos->second.insert(next_line.
line);
498 source_lines_to_display.
lines.push_back(next_line);
501 previous_line = this_line;
511 if (source_lines_to_display.
lines.size() > 0) {
513 for (
size_t idx = 0; idx < source_lines_to_display.
lines.size();
516 const char *line_highlight =
"";
517 if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
518 line_highlight =
"->";
520 line_highlight =
"**";
529 const bool show_bytes = (options & eOptionShowBytes) != 0;
530 inst->
Dump(&strm, max_opcode_byte_size,
true, show_bytes, &exe_ctx, &sc,
531 &prev_sc,
nullptr, address_text_size);
558 if (limit.
value == 0)
561 return Disassemble(debugger, arch,
nullptr,
nullptr, frame,
566 : m_address(address), m_address_class(addr_class), m_opcode(),
567 m_calculated_strings(false) {}
578 bool show_address,
bool show_bytes,
583 size_t max_address_text_size) {
584 size_t opcode_column_width = 7;
585 const size_t operand_column_width = 25;
602 if (max_opcode_byte_size > 0)
609 if (max_opcode_byte_size > 0)
631 opcode_pos + opcode_column_width + operand_column_width,
' ');
639 std::unique_ptr<EmulateInstruction> insn_emulator_up(
641 if (insn_emulator_up) {
643 return insn_emulator_up->EvaluateInstruction(0);
663 auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type);
667 if (!fgets(buffer, 1023, in_file)) {
669 "Instruction::ReadArray: Error reading file (fgets).\n");
670 option_value_sp.reset();
671 return option_value_sp;
676 size_t len = line.size();
677 if (line[len - 1] ==
'\n') {
678 line[len - 1] =
'\0';
679 line.resize(len - 1);
682 if ((line.size() == 1) && line[0] ==
']') {
690 llvm::StringRef(
"^[ \t]*([^ \t]+)[ \t]*$"));
691 llvm::SmallVector<llvm::StringRef, 2> matches;
692 if (g_reg_exp.
Execute(line, &matches))
693 value = matches[1].str();
697 OptionValueSP data_value_sp;
700 data_value_sp = std::make_shared<OptionValueUInt64>(0, 0);
701 data_value_sp->SetValueFromString(value);
705 data_value_sp = std::make_shared<OptionValueString>(value.c_str(),
"");
709 option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
714 return option_value_sp;
721 auto option_value_sp = std::make_shared<OptionValueDictionary>();
727 if (!fgets(buffer, 1023, in_file)) {
729 "Instruction::ReadDictionary: Error reading file (fgets).\n");
730 option_value_sp.reset();
731 return option_value_sp;
737 size_t len = line.size();
738 if (line[len - 1] ==
'\n') {
739 line[len - 1] =
'\0';
740 line.resize(len - 1);
743 if ((line.size() == 1) && (line[0] ==
'}')) {
752 "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"));
754 llvm::SmallVector<llvm::StringRef, 3> matches;
756 bool reg_exp_success = g_reg_exp.
Execute(line, &matches);
759 if (reg_exp_success) {
760 key = matches[1].str();
761 value = matches[2].str();
763 out_stream->
Printf(
"Instruction::ReadDictionary: Failure executing "
764 "regular expression.\n");
765 option_value_sp.reset();
766 return option_value_sp;
772 lldb::OptionValueSP value_sp;
773 assert(value.empty() ==
false);
774 assert(key.empty() ==
false);
776 if (value[0] ==
'{') {
777 assert(value.size() == 1);
781 option_value_sp.reset();
782 return option_value_sp;
784 }
else if (value[0] ==
'[') {
785 assert(value.size() == 1);
787 value_sp =
ReadArray(in_file, out_stream, data_type);
789 option_value_sp.reset();
790 return option_value_sp;
795 }
else if ((value[0] ==
'0') && (value[1] ==
'x')) {
796 value_sp = std::make_shared<OptionValueUInt64>(0, 0);
797 value_sp->SetValueFromString(value);
799 size_t len = value.size();
800 if ((value[0] ==
'"') && (value[len - 1] ==
'"'))
801 value = value.substr(1, len - 2);
802 value_sp = std::make_shared<OptionValueString>(value.c_str(),
"");
805 if (const_key == encoding_key) {
810 if (strcmp(value.c_str(),
"uint32_t") == 0)
813 option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp,
818 return option_value_sp;
826 out_stream->
Printf(
"Instruction::TestEmulation: Missing file_name.");
832 "Instruction::TestEmulation: Attempt to open test file failed.");
837 if (!fgets(buffer, 255, test_file)) {
839 "Instruction::TestEmulation: Error reading first line of test file.\n");
844 if (strncmp(buffer,
"InstructionEmulationState={", 27) != 0) {
845 out_stream->
Printf(
"Instructin::TestEmulation: Test file does not contain "
846 "emulation state dictionary\n");
854 OptionValueSP data_dictionary_sp(
ReadDictionary(test_file, out_stream));
855 if (!data_dictionary_sp) {
857 "Instruction::TestEmulation: Error reading Dictionary Object.\n");
866 static ConstString description_key(
"assembly_string");
869 OptionValueSP value_sp = data_dictionary->
GetValueForKey(description_key);
872 out_stream->
Printf(
"Instruction::TestEmulation: Test file does not "
873 "contain description string.\n");
882 "Instruction::TestEmulation: Test file does not contain triple.\n");
887 arch.
SetTriple(llvm::Triple(value_sp->GetStringValue()));
889 bool success =
false;
890 std::unique_ptr<EmulateInstruction> insn_emulator_up(
892 if (insn_emulator_up)
894 insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary);
897 out_stream->
Printf(
"Emulation test succeeded.");
899 out_stream->
Printf(
"Emulation test failed.");
910 std::unique_ptr<EmulateInstruction> insn_emulator_up(
912 if (insn_emulator_up) {
913 insn_emulator_up->SetBaton(baton);
914 insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback,
915 read_reg_callback, write_reg_callback);
917 return insn_emulator_up->EvaluateInstruction(evaluate_options);
935 collection::const_iterator pos, end;
938 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
939 if (max_inst_size < inst_size)
940 max_inst_size = inst_size;
942 return max_inst_size;
946 InstructionSP inst_sp;
962 collection::const_iterator pos, begin, end;
971 disassembly_format = &format;
978 (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx,
979 nullptr,
nullptr, disassembly_format, 0);
993 bool *found_calls)
const {
999 *found_calls =
false;
1000 for (
size_t i = start; i < num_instructions; i++) {
1004 *found_calls =
true;
1019 for (
size_t i = 0; i < num_instructions; i++) {
1038 bool force_live_memory) {
1049 auto data_sp = std::make_shared<DataBufferHeap>(byte_size,
'\0');
1053 const size_t bytes_read =
1054 target.
ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(),
1055 error, force_live_memory, &load_addr);
1058 if (bytes_read == 0) {
1059 if (error_strm_ptr) {
1060 if (
const char *error_cstr =
error.AsCString())
1061 error_strm_ptr->
Printf(
"error: %s\n", error_cstr);
1066 if (bytes_read != data_sp->GetByteSize())
1067 data_sp->SetByteSize(bytes_read);
1073 false, data_from_file);
1080 if (flavor ==
nullptr)
1090 if (thumb_arch_name.size() > 3) {
1091 thumb_arch_name.erase(0, 3);
1092 thumb_arch_name.insert(0,
"thumb");
1139 switch (opcode_size) {
1141 uint8_t value8 = *((uint8_t *)opcode_data);
1156 uint64_t value64 = *((uint64_t *)opcode_data);
1179 ret.
m_type = Type::Immediate;
1187 ret.
m_type = Type::Immediate;
1201 ret.
m_type = Type::Dereference;
1217 ret.
m_type = Type::Product;
1228 return (base(op) && op.m_children.size() == 2 &&
1229 ((left(op.m_children[0]) && right(op.m_children[1])) ||
1230 (left(op.m_children[1]) && right(op.m_children[0]))));
1239 return (base(op) && op.m_children.size() == 1 && child(op.m_children[0]));
1258 reg = op.m_register;
1267 ((op.m_negative && op.m_immediate == (uint64_t)-imm) ||
1268 (!op.m_negative && op.m_immediate == (uint64_t)imm)));
1278 if (op.m_negative) {
1279 imm = -((int64_t)op.m_immediate);
1281 imm = ((int64_t)op.m_immediate);