1cfca06d7SDimitry Andric //===-- Disassembler.cpp --------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Core/Disassembler.h"
10f034231aSEd Maste
1194994d37SDimitry Andric #include "lldb/Core/AddressRange.h"
12f034231aSEd Maste #include "lldb/Core/Debugger.h"
13f034231aSEd Maste #include "lldb/Core/EmulateInstruction.h"
1494994d37SDimitry Andric #include "lldb/Core/Mangled.h"
15f034231aSEd Maste #include "lldb/Core/Module.h"
1694994d37SDimitry Andric #include "lldb/Core/ModuleList.h"
17f034231aSEd Maste #include "lldb/Core/PluginManager.h"
1894994d37SDimitry Andric #include "lldb/Core/SourceManager.h"
19f3fbd1c0SDimitry Andric #include "lldb/Host/FileSystem.h"
20f034231aSEd Maste #include "lldb/Interpreter/OptionValue.h"
21f034231aSEd Maste #include "lldb/Interpreter/OptionValueArray.h"
22f034231aSEd Maste #include "lldb/Interpreter/OptionValueDictionary.h"
2314f1b3e8SDimitry Andric #include "lldb/Interpreter/OptionValueRegex.h"
24f034231aSEd Maste #include "lldb/Interpreter/OptionValueString.h"
25f034231aSEd Maste #include "lldb/Interpreter/OptionValueUInt64.h"
26f034231aSEd Maste #include "lldb/Symbol/Function.h"
2794994d37SDimitry Andric #include "lldb/Symbol/Symbol.h"
2894994d37SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
29f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
30866dcdacSEd Maste #include "lldb/Target/SectionLoadList.h"
31f034231aSEd Maste #include "lldb/Target/StackFrame.h"
32f034231aSEd Maste #include "lldb/Target/Target.h"
3394994d37SDimitry Andric #include "lldb/Target/Thread.h"
3474a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
3574a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
3674a628f7SDimitry Andric #include "lldb/Utility/RegularExpression.h"
37b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
3894994d37SDimitry Andric #include "lldb/Utility/Stream.h"
3994994d37SDimitry Andric #include "lldb/Utility/StreamString.h"
401b306c26SDimitry Andric #include "lldb/Utility/Timer.h"
4194994d37SDimitry Andric #include "lldb/lldb-private-enumerations.h"
4294994d37SDimitry Andric #include "lldb/lldb-private-interfaces.h"
4394994d37SDimitry Andric #include "lldb/lldb-private-types.h"
4494994d37SDimitry Andric #include "llvm/Support/Compiler.h"
457fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
4674a628f7SDimitry Andric
4794994d37SDimitry Andric #include <cstdint>
4874a628f7SDimitry Andric #include <cstring>
4994994d37SDimitry Andric #include <utility>
5074a628f7SDimitry Andric
51344a3780SDimitry Andric #include <cassert>
52f034231aSEd Maste
53f034231aSEd Maste #define DEFAULT_DISASM_BYTE_SIZE 32
54f034231aSEd Maste
55f034231aSEd Maste using namespace lldb;
56f034231aSEd Maste using namespace lldb_private;
57f034231aSEd Maste
FindPlugin(const ArchSpec & arch,const char * flavor,const char * plugin_name)5814f1b3e8SDimitry Andric DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
5914f1b3e8SDimitry Andric const char *flavor,
6014f1b3e8SDimitry Andric const char *plugin_name) {
61b60736ecSDimitry Andric LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
6214f1b3e8SDimitry Andric arch.GetArchitectureName(), plugin_name);
63f034231aSEd Maste
64f3fbd1c0SDimitry Andric DisassemblerCreateInstance create_callback = nullptr;
65f034231aSEd Maste
6614f1b3e8SDimitry Andric if (plugin_name) {
67c0981da4SDimitry Andric create_callback =
68c0981da4SDimitry Andric PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name);
6914f1b3e8SDimitry Andric if (create_callback) {
707fa27ce4SDimitry Andric if (auto disasm_sp = create_callback(arch, flavor))
717fa27ce4SDimitry Andric return disasm_sp;
72f034231aSEd Maste }
7314f1b3e8SDimitry Andric } else {
7414f1b3e8SDimitry Andric for (uint32_t idx = 0;
7514f1b3e8SDimitry Andric (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
7614f1b3e8SDimitry Andric idx)) != nullptr;
7714f1b3e8SDimitry Andric ++idx) {
787fa27ce4SDimitry Andric if (auto disasm_sp = create_callback(arch, flavor))
797fa27ce4SDimitry Andric return disasm_sp;
80f034231aSEd Maste }
81f034231aSEd Maste }
82f034231aSEd Maste return DisassemblerSP();
83f034231aSEd Maste }
84f034231aSEd Maste
FindPluginForTarget(const Target & target,const ArchSpec & arch,const char * flavor,const char * plugin_name)85cfca06d7SDimitry Andric DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
8614f1b3e8SDimitry Andric const ArchSpec &arch,
8714f1b3e8SDimitry Andric const char *flavor,
8814f1b3e8SDimitry Andric const char *plugin_name) {
89cfca06d7SDimitry Andric if (flavor == nullptr) {
9014f1b3e8SDimitry Andric // FIXME - we don't have the mechanism in place to do per-architecture
91f73363f1SDimitry Andric // settings. But since we know that for now we only support flavors on x86
92f73363f1SDimitry Andric // & x86_64,
9314f1b3e8SDimitry Andric if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
9414f1b3e8SDimitry Andric arch.GetTriple().getArch() == llvm::Triple::x86_64)
95cfca06d7SDimitry Andric flavor = target.GetDisassemblyFlavor();
96f034231aSEd Maste }
97f034231aSEd Maste return FindPlugin(arch, flavor, plugin_name);
98f034231aSEd Maste }
99f034231aSEd Maste
ResolveAddress(Target & target,const Address & addr)100cfca06d7SDimitry Andric static Address ResolveAddress(Target &target, const Address &addr) {
10114f1b3e8SDimitry Andric if (!addr.IsSectionOffset()) {
102cfca06d7SDimitry Andric Address resolved_addr;
103f73363f1SDimitry Andric // If we weren't passed in a section offset address range, try and resolve
104f73363f1SDimitry Andric // it to something
105cfca06d7SDimitry Andric bool is_resolved = target.GetSectionLoadList().IsEmpty()
106cfca06d7SDimitry Andric ? target.GetImages().ResolveFileAddress(
107cfca06d7SDimitry Andric addr.GetOffset(), resolved_addr)
108cfca06d7SDimitry Andric : target.GetSectionLoadList().ResolveLoadAddress(
109cfca06d7SDimitry Andric addr.GetOffset(), resolved_addr);
110f73363f1SDimitry Andric
111f73363f1SDimitry Andric // We weren't able to resolve the address, just treat it as a raw address
112f73363f1SDimitry Andric if (is_resolved && resolved_addr.IsValid())
113cfca06d7SDimitry Andric return resolved_addr;
114f034231aSEd Maste }
115cfca06d7SDimitry Andric return addr;
116f034231aSEd Maste }
117f034231aSEd Maste
DisassembleRange(const ArchSpec & arch,const char * plugin_name,const char * flavor,Target & target,const AddressRange & range,bool force_live_memory)11814f1b3e8SDimitry Andric lldb::DisassemblerSP Disassembler::DisassembleRange(
11914f1b3e8SDimitry Andric const ArchSpec &arch, const char *plugin_name, const char *flavor,
120344a3780SDimitry Andric Target &target, const AddressRange &range, bool force_live_memory) {
121ead24645SDimitry Andric if (range.GetByteSize() <= 0)
122ead24645SDimitry Andric return {};
123f034231aSEd Maste
124ead24645SDimitry Andric if (!range.GetBaseAddress().IsValid())
125ead24645SDimitry Andric return {};
126ead24645SDimitry Andric
127cfca06d7SDimitry Andric lldb::DisassemblerSP disasm_sp =
128cfca06d7SDimitry Andric Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
129ead24645SDimitry Andric
130ead24645SDimitry Andric if (!disasm_sp)
131ead24645SDimitry Andric return {};
132ead24645SDimitry Andric
133cfca06d7SDimitry Andric const size_t bytes_disassembled = disasm_sp->ParseInstructions(
134cfca06d7SDimitry Andric target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()},
135344a3780SDimitry Andric nullptr, force_live_memory);
136f034231aSEd Maste if (bytes_disassembled == 0)
137ead24645SDimitry Andric return {};
138ead24645SDimitry Andric
139f034231aSEd Maste return disasm_sp;
140f034231aSEd Maste }
141f034231aSEd Maste
142f034231aSEd Maste lldb::DisassemblerSP
DisassembleBytes(const ArchSpec & arch,const char * plugin_name,const char * flavor,const Address & start,const void * src,size_t src_len,uint32_t num_instructions,bool data_from_file)14314f1b3e8SDimitry Andric Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
14414f1b3e8SDimitry Andric const char *flavor, const Address &start,
14514f1b3e8SDimitry Andric const void *src, size_t src_len,
14614f1b3e8SDimitry Andric uint32_t num_instructions, bool data_from_file) {
147ead24645SDimitry Andric if (!src)
148ead24645SDimitry Andric return {};
149f034231aSEd Maste
150ead24645SDimitry Andric lldb::DisassemblerSP disasm_sp =
151ead24645SDimitry Andric Disassembler::FindPlugin(arch, flavor, plugin_name);
152f034231aSEd Maste
153ead24645SDimitry Andric if (!disasm_sp)
154ead24645SDimitry Andric return {};
155ead24645SDimitry Andric
15614f1b3e8SDimitry Andric DataExtractor data(src, src_len, arch.GetByteOrder(),
15714f1b3e8SDimitry Andric arch.GetAddressByteSize());
158f034231aSEd Maste
159ead24645SDimitry Andric (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false,
160ead24645SDimitry Andric data_from_file);
161f034231aSEd Maste return disasm_sp;
162f034231aSEd Maste }
163f034231aSEd Maste
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const Address & address,Limit limit,bool mixed_source_and_assembly,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)16414f1b3e8SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
16514f1b3e8SDimitry Andric const char *plugin_name, const char *flavor,
166f034231aSEd Maste const ExecutionContext &exe_ctx,
167cfca06d7SDimitry Andric const Address &address, Limit limit,
16814f1b3e8SDimitry Andric bool mixed_source_and_assembly,
169f034231aSEd Maste uint32_t num_mixed_context_lines,
17014f1b3e8SDimitry Andric uint32_t options, Stream &strm) {
171cfca06d7SDimitry Andric if (!exe_ctx.GetTargetPtr())
172ead24645SDimitry Andric return false;
173ead24645SDimitry Andric
17414f1b3e8SDimitry Andric lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
175cfca06d7SDimitry Andric exe_ctx.GetTargetRef(), arch, flavor, plugin_name));
176ead24645SDimitry Andric if (!disasm_sp)
177ead24645SDimitry Andric return false;
178ead24645SDimitry Andric
179344a3780SDimitry Andric const bool force_live_memory = true;
18014f1b3e8SDimitry Andric size_t bytes_disassembled = disasm_sp->ParseInstructions(
181344a3780SDimitry Andric exe_ctx.GetTargetRef(), address, limit, &strm, force_live_memory);
182f034231aSEd Maste if (bytes_disassembled == 0)
183f034231aSEd Maste return false;
184ead24645SDimitry Andric
185cfca06d7SDimitry Andric disasm_sp->PrintInstructions(debugger, arch, exe_ctx,
186cfca06d7SDimitry Andric mixed_source_and_assembly,
187f3fbd1c0SDimitry Andric num_mixed_context_lines, options, strm);
188cfca06d7SDimitry Andric return true;
189f034231aSEd Maste }
190f034231aSEd Maste
19114f1b3e8SDimitry Andric Disassembler::SourceLine
GetFunctionDeclLineEntry(const SymbolContext & sc)19214f1b3e8SDimitry Andric Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
193ead24645SDimitry Andric if (!sc.function)
194ead24645SDimitry Andric return {};
195ead24645SDimitry Andric
196ead24645SDimitry Andric if (!sc.line_entry.IsValid())
197ead24645SDimitry Andric return {};
198ead24645SDimitry Andric
19914f1b3e8SDimitry Andric LineEntry prologue_end_line = sc.line_entry;
20014f1b3e8SDimitry Andric FileSpec func_decl_file;
20114f1b3e8SDimitry Andric uint32_t func_decl_line;
20214f1b3e8SDimitry Andric sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
203ead24645SDimitry Andric
204ac9a064cSDimitry Andric if (func_decl_file != prologue_end_line.GetFile() &&
2054df029ccSDimitry Andric func_decl_file != prologue_end_line.original_file_sp->GetSpecOnly())
206ead24645SDimitry Andric return {};
207ead24645SDimitry Andric
208ead24645SDimitry Andric SourceLine decl_line;
20914f1b3e8SDimitry Andric decl_line.file = func_decl_file;
21014f1b3e8SDimitry Andric decl_line.line = func_decl_line;
211ead24645SDimitry Andric // TODO: Do we care about column on these entries? If so, we need to plumb
212ead24645SDimitry Andric // that through GetStartLineSourceInfo.
21314f1b3e8SDimitry Andric decl_line.column = 0;
21414f1b3e8SDimitry Andric return decl_line;
21514f1b3e8SDimitry Andric }
21614f1b3e8SDimitry Andric
AddLineToSourceLineTables(SourceLine & line,std::map<FileSpec,std::set<uint32_t>> & source_lines_seen)21714f1b3e8SDimitry Andric void Disassembler::AddLineToSourceLineTables(
21814f1b3e8SDimitry Andric SourceLine &line,
21914f1b3e8SDimitry Andric std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
22014f1b3e8SDimitry Andric if (line.IsValid()) {
22114f1b3e8SDimitry Andric auto source_lines_seen_pos = source_lines_seen.find(line.file);
22214f1b3e8SDimitry Andric if (source_lines_seen_pos == source_lines_seen.end()) {
22314f1b3e8SDimitry Andric std::set<uint32_t> lines;
22414f1b3e8SDimitry Andric lines.insert(line.line);
22514f1b3e8SDimitry Andric source_lines_seen.emplace(line.file, lines);
22614f1b3e8SDimitry Andric } else {
22714f1b3e8SDimitry Andric source_lines_seen_pos->second.insert(line.line);
22814f1b3e8SDimitry Andric }
22914f1b3e8SDimitry Andric }
23014f1b3e8SDimitry Andric }
23114f1b3e8SDimitry Andric
ElideMixedSourceAndDisassemblyLine(const ExecutionContext & exe_ctx,const SymbolContext & sc,SourceLine & line)23214f1b3e8SDimitry Andric bool Disassembler::ElideMixedSourceAndDisassemblyLine(
23314f1b3e8SDimitry Andric const ExecutionContext &exe_ctx, const SymbolContext &sc,
23414f1b3e8SDimitry Andric SourceLine &line) {
23514f1b3e8SDimitry Andric
23614f1b3e8SDimitry Andric // TODO: should we also check target.process.thread.step-avoid-libraries ?
23714f1b3e8SDimitry Andric
23814f1b3e8SDimitry Andric const RegularExpression *avoid_regex = nullptr;
23914f1b3e8SDimitry Andric
24014f1b3e8SDimitry Andric // Skip any line #0 entries - they are implementation details
24114f1b3e8SDimitry Andric if (line.line == 0)
2427fa27ce4SDimitry Andric return true;
24314f1b3e8SDimitry Andric
24414f1b3e8SDimitry Andric ThreadSP thread_sp = exe_ctx.GetThreadSP();
24514f1b3e8SDimitry Andric if (thread_sp) {
24614f1b3e8SDimitry Andric avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
24714f1b3e8SDimitry Andric } else {
24814f1b3e8SDimitry Andric TargetSP target_sp = exe_ctx.GetTargetSP();
24914f1b3e8SDimitry Andric if (target_sp) {
250b76161e4SDimitry Andric Status error;
25114f1b3e8SDimitry Andric OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
2527fa27ce4SDimitry Andric &exe_ctx, "target.process.thread.step-avoid-regexp", error);
25314f1b3e8SDimitry Andric if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
25414f1b3e8SDimitry Andric OptionValueRegex *re = value_sp->GetAsRegex();
25514f1b3e8SDimitry Andric if (re) {
25614f1b3e8SDimitry Andric avoid_regex = re->GetCurrentValue();
25714f1b3e8SDimitry Andric }
25814f1b3e8SDimitry Andric }
25914f1b3e8SDimitry Andric }
26014f1b3e8SDimitry Andric }
26114f1b3e8SDimitry Andric if (avoid_regex && sc.symbol != nullptr) {
26214f1b3e8SDimitry Andric const char *function_name =
26314f1b3e8SDimitry Andric sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
26414f1b3e8SDimitry Andric .GetCString();
265ead24645SDimitry Andric if (function_name && avoid_regex->Execute(function_name)) {
26614f1b3e8SDimitry Andric // skip this source line
26714f1b3e8SDimitry Andric return true;
26814f1b3e8SDimitry Andric }
26914f1b3e8SDimitry Andric }
27014f1b3e8SDimitry Andric // don't skip this source line
27114f1b3e8SDimitry Andric return false;
27214f1b3e8SDimitry Andric }
27314f1b3e8SDimitry Andric
PrintInstructions(Debugger & debugger,const ArchSpec & arch,const ExecutionContext & exe_ctx,bool mixed_source_and_assembly,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)274cfca06d7SDimitry Andric void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch,
27514f1b3e8SDimitry Andric const ExecutionContext &exe_ctx,
27614f1b3e8SDimitry Andric bool mixed_source_and_assembly,
27714f1b3e8SDimitry Andric uint32_t num_mixed_context_lines,
27814f1b3e8SDimitry Andric uint32_t options, Stream &strm) {
279f034231aSEd Maste // We got some things disassembled...
280cfca06d7SDimitry Andric size_t num_instructions_found = GetInstructionList().GetSize();
281f034231aSEd Maste
28214f1b3e8SDimitry Andric const uint32_t max_opcode_byte_size =
283cfca06d7SDimitry Andric GetInstructionList().GetMaxOpcocdeByteSize();
284f034231aSEd Maste SymbolContext sc;
285f034231aSEd Maste SymbolContext prev_sc;
28614f1b3e8SDimitry Andric AddressRange current_source_line_range;
287f3fbd1c0SDimitry Andric const Address *pc_addr_ptr = nullptr;
288f034231aSEd Maste StackFrame *frame = exe_ctx.GetFramePtr();
289f034231aSEd Maste
290f034231aSEd Maste TargetSP target_sp(exe_ctx.GetTargetSP());
29114f1b3e8SDimitry Andric SourceManager &source_manager =
29214f1b3e8SDimitry Andric target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
293f034231aSEd Maste
29414f1b3e8SDimitry Andric if (frame) {
295f034231aSEd Maste pc_addr_ptr = &frame->GetFrameCodeAddress();
296205afe67SEd Maste }
29714f1b3e8SDimitry Andric const uint32_t scope =
29814f1b3e8SDimitry Andric eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
299f034231aSEd Maste const bool use_inline_block_range = false;
3005e95aa85SEd Maste
301f3fbd1c0SDimitry Andric const FormatEntity::Entry *disassembly_format = nullptr;
3025e95aa85SEd Maste FormatEntity::Entry format;
30314f1b3e8SDimitry Andric if (exe_ctx.HasTargetScope()) {
30414f1b3e8SDimitry Andric disassembly_format =
30514f1b3e8SDimitry Andric exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
30614f1b3e8SDimitry Andric } else {
3075e95aa85SEd Maste FormatEntity::Parse("${addr}: ", format);
3085e95aa85SEd Maste disassembly_format = &format;
3095e95aa85SEd Maste }
3105e95aa85SEd Maste
311f73363f1SDimitry Andric // First pass: step through the list of instructions, find how long the
312f73363f1SDimitry Andric // initial addresses strings are, insert padding in the second pass so the
313f73363f1SDimitry Andric // opcodes all line up nicely.
31414f1b3e8SDimitry Andric
31514f1b3e8SDimitry Andric // Also build up the source line mapping if this is mixed source & assembly
316f73363f1SDimitry Andric // mode. Calculate the source line for each assembly instruction (eliding
317f73363f1SDimitry Andric // inlined functions which the user wants to skip).
31814f1b3e8SDimitry Andric
31914f1b3e8SDimitry Andric std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
32014f1b3e8SDimitry Andric Symbol *previous_symbol = nullptr;
32114f1b3e8SDimitry Andric
3225e95aa85SEd Maste size_t address_text_size = 0;
32314f1b3e8SDimitry Andric for (size_t i = 0; i < num_instructions_found; ++i) {
324cfca06d7SDimitry Andric Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
32514f1b3e8SDimitry Andric if (inst) {
3265e95aa85SEd Maste const Address &addr = inst->GetAddress();
3275e95aa85SEd Maste ModuleSP module_sp(addr.GetModule());
32814f1b3e8SDimitry Andric if (module_sp) {
32994994d37SDimitry Andric const SymbolContextItem resolve_mask = eSymbolContextFunction |
33014f1b3e8SDimitry Andric eSymbolContextSymbol |
33114f1b3e8SDimitry Andric eSymbolContextLineEntry;
33214f1b3e8SDimitry Andric uint32_t resolved_mask =
33314f1b3e8SDimitry Andric module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
33414f1b3e8SDimitry Andric if (resolved_mask) {
3355e95aa85SEd Maste StreamString strmstr;
33614f1b3e8SDimitry Andric Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
33714f1b3e8SDimitry Andric &exe_ctx, &addr, strmstr);
3385e95aa85SEd Maste size_t cur_line = strmstr.GetSizeOfLastLine();
3395e95aa85SEd Maste if (cur_line > address_text_size)
3405e95aa85SEd Maste address_text_size = cur_line;
34114f1b3e8SDimitry Andric
34214f1b3e8SDimitry Andric // Add entries to our "source_lines_seen" map+set which list which
34314f1b3e8SDimitry Andric // sources lines occur in this disassembly session. We will print
34414f1b3e8SDimitry Andric // lines of context around a source line, but we don't want to print
34514f1b3e8SDimitry Andric // a source line that has a line table entry of its own - we'll leave
34614f1b3e8SDimitry Andric // that source line to be printed when it actually occurs in the
34714f1b3e8SDimitry Andric // disassembly.
34814f1b3e8SDimitry Andric
34914f1b3e8SDimitry Andric if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
35014f1b3e8SDimitry Andric if (sc.symbol != previous_symbol) {
35114f1b3e8SDimitry Andric SourceLine decl_line = GetFunctionDeclLineEntry(sc);
35294994d37SDimitry Andric if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
35314f1b3e8SDimitry Andric AddLineToSourceLineTables(decl_line, source_lines_seen);
35414f1b3e8SDimitry Andric }
35514f1b3e8SDimitry Andric if (sc.line_entry.IsValid()) {
35614f1b3e8SDimitry Andric SourceLine this_line;
357ac9a064cSDimitry Andric this_line.file = sc.line_entry.GetFile();
35814f1b3e8SDimitry Andric this_line.line = sc.line_entry.line;
35914f1b3e8SDimitry Andric this_line.column = sc.line_entry.column;
36094994d37SDimitry Andric if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
36114f1b3e8SDimitry Andric AddLineToSourceLineTables(this_line, source_lines_seen);
36214f1b3e8SDimitry Andric }
36314f1b3e8SDimitry Andric }
3645e95aa85SEd Maste }
3655e95aa85SEd Maste sc.Clear(false);
3665e95aa85SEd Maste }
3675e95aa85SEd Maste }
3685e95aa85SEd Maste }
3695e95aa85SEd Maste
37014f1b3e8SDimitry Andric previous_symbol = nullptr;
37114f1b3e8SDimitry Andric SourceLine previous_line;
37214f1b3e8SDimitry Andric for (size_t i = 0; i < num_instructions_found; ++i) {
373cfca06d7SDimitry Andric Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
37414f1b3e8SDimitry Andric
37514f1b3e8SDimitry Andric if (inst) {
376f034231aSEd Maste const Address &addr = inst->GetAddress();
377f034231aSEd Maste const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
37814f1b3e8SDimitry Andric SourceLinesToDisplay source_lines_to_display;
379f034231aSEd Maste
380f034231aSEd Maste prev_sc = sc;
381f034231aSEd Maste
382f034231aSEd Maste ModuleSP module_sp(addr.GetModule());
38314f1b3e8SDimitry Andric if (module_sp) {
38414f1b3e8SDimitry Andric uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
38514f1b3e8SDimitry Andric addr, eSymbolContextEverything, sc);
38614f1b3e8SDimitry Andric if (resolved_mask) {
38714f1b3e8SDimitry Andric if (mixed_source_and_assembly) {
388f034231aSEd Maste
38914f1b3e8SDimitry Andric // If we've started a new function (non-inlined), print all of the
390f73363f1SDimitry Andric // source lines from the function declaration until the first line
391f73363f1SDimitry Andric // table entry - typically the opening curly brace of the function.
39214f1b3e8SDimitry Andric if (previous_symbol != sc.symbol) {
393f73363f1SDimitry Andric // The default disassembly format puts an extra blank line
394f73363f1SDimitry Andric // between functions - so when we're displaying the source
395f73363f1SDimitry Andric // context for a function, we don't want to add a blank line
396f73363f1SDimitry Andric // after the source context or we'll end up with two of them.
39714f1b3e8SDimitry Andric if (previous_symbol != nullptr)
39814f1b3e8SDimitry Andric source_lines_to_display.print_source_context_end_eol = false;
399f034231aSEd Maste
40014f1b3e8SDimitry Andric previous_symbol = sc.symbol;
40114f1b3e8SDimitry Andric if (sc.function && sc.line_entry.IsValid()) {
40214f1b3e8SDimitry Andric LineEntry prologue_end_line = sc.line_entry;
40394994d37SDimitry Andric if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
40494994d37SDimitry Andric prologue_end_line)) {
40514f1b3e8SDimitry Andric FileSpec func_decl_file;
40614f1b3e8SDimitry Andric uint32_t func_decl_line;
40714f1b3e8SDimitry Andric sc.function->GetStartLineSourceInfo(func_decl_file,
40814f1b3e8SDimitry Andric func_decl_line);
409ac9a064cSDimitry Andric if (func_decl_file == prologue_end_line.GetFile() ||
4104df029ccSDimitry Andric func_decl_file ==
4114df029ccSDimitry Andric prologue_end_line.original_file_sp->GetSpecOnly()) {
412f73363f1SDimitry Andric // Add all the lines between the function declaration and
413f73363f1SDimitry Andric // the first non-prologue source line to the list of lines
414f73363f1SDimitry Andric // to print.
41514f1b3e8SDimitry Andric for (uint32_t lineno = func_decl_line;
41614f1b3e8SDimitry Andric lineno <= prologue_end_line.line; lineno++) {
41714f1b3e8SDimitry Andric SourceLine this_line;
41814f1b3e8SDimitry Andric this_line.file = func_decl_file;
41914f1b3e8SDimitry Andric this_line.line = lineno;
42014f1b3e8SDimitry Andric source_lines_to_display.lines.push_back(this_line);
42114f1b3e8SDimitry Andric }
422f73363f1SDimitry Andric // Mark the last line as the "current" one. Usually this
423f73363f1SDimitry Andric // is the open curly brace.
42414f1b3e8SDimitry Andric if (source_lines_to_display.lines.size() > 0)
42514f1b3e8SDimitry Andric source_lines_to_display.current_source_line =
42614f1b3e8SDimitry Andric source_lines_to_display.lines.size() - 1;
42714f1b3e8SDimitry Andric }
42814f1b3e8SDimitry Andric }
42914f1b3e8SDimitry Andric }
43014f1b3e8SDimitry Andric sc.GetAddressRange(scope, 0, use_inline_block_range,
43114f1b3e8SDimitry Andric current_source_line_range);
43214f1b3e8SDimitry Andric }
433f034231aSEd Maste
434f73363f1SDimitry Andric // If we've left a previous source line's address range, print a
435f73363f1SDimitry Andric // new source line
43614f1b3e8SDimitry Andric if (!current_source_line_range.ContainsFileAddress(addr)) {
43714f1b3e8SDimitry Andric sc.GetAddressRange(scope, 0, use_inline_block_range,
43814f1b3e8SDimitry Andric current_source_line_range);
43914f1b3e8SDimitry Andric
44014f1b3e8SDimitry Andric if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
44114f1b3e8SDimitry Andric SourceLine this_line;
442ac9a064cSDimitry Andric this_line.file = sc.line_entry.GetFile();
44314f1b3e8SDimitry Andric this_line.line = sc.line_entry.line;
44414f1b3e8SDimitry Andric
44594994d37SDimitry Andric if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
44694994d37SDimitry Andric this_line)) {
44714f1b3e8SDimitry Andric // Only print this source line if it is different from the
44814f1b3e8SDimitry Andric // last source line we printed. There may have been inlined
44914f1b3e8SDimitry Andric // functions between these lines that we elided, resulting in
450f73363f1SDimitry Andric // the same line being printed twice in a row for a
451f73363f1SDimitry Andric // contiguous block of assembly instructions.
45214f1b3e8SDimitry Andric if (this_line != previous_line) {
45314f1b3e8SDimitry Andric
45414f1b3e8SDimitry Andric std::vector<uint32_t> previous_lines;
45514f1b3e8SDimitry Andric for (uint32_t i = 0;
45614f1b3e8SDimitry Andric i < num_mixed_context_lines &&
45714f1b3e8SDimitry Andric (this_line.line - num_mixed_context_lines) > 0;
45814f1b3e8SDimitry Andric i++) {
45914f1b3e8SDimitry Andric uint32_t line =
46014f1b3e8SDimitry Andric this_line.line - num_mixed_context_lines + i;
46114f1b3e8SDimitry Andric auto pos = source_lines_seen.find(this_line.file);
46214f1b3e8SDimitry Andric if (pos != source_lines_seen.end()) {
46314f1b3e8SDimitry Andric if (pos->second.count(line) == 1) {
46414f1b3e8SDimitry Andric previous_lines.clear();
46514f1b3e8SDimitry Andric } else {
46614f1b3e8SDimitry Andric previous_lines.push_back(line);
46714f1b3e8SDimitry Andric }
46814f1b3e8SDimitry Andric }
46914f1b3e8SDimitry Andric }
47014f1b3e8SDimitry Andric for (size_t i = 0; i < previous_lines.size(); i++) {
47114f1b3e8SDimitry Andric SourceLine previous_line;
47214f1b3e8SDimitry Andric previous_line.file = this_line.file;
47314f1b3e8SDimitry Andric previous_line.line = previous_lines[i];
47414f1b3e8SDimitry Andric auto pos = source_lines_seen.find(previous_line.file);
47514f1b3e8SDimitry Andric if (pos != source_lines_seen.end()) {
47614f1b3e8SDimitry Andric pos->second.insert(previous_line.line);
47714f1b3e8SDimitry Andric }
47814f1b3e8SDimitry Andric source_lines_to_display.lines.push_back(previous_line);
47914f1b3e8SDimitry Andric }
48014f1b3e8SDimitry Andric
48114f1b3e8SDimitry Andric source_lines_to_display.lines.push_back(this_line);
48214f1b3e8SDimitry Andric source_lines_to_display.current_source_line =
48314f1b3e8SDimitry Andric source_lines_to_display.lines.size() - 1;
48414f1b3e8SDimitry Andric
48514f1b3e8SDimitry Andric for (uint32_t i = 0; i < num_mixed_context_lines; i++) {
48614f1b3e8SDimitry Andric SourceLine next_line;
48714f1b3e8SDimitry Andric next_line.file = this_line.file;
48814f1b3e8SDimitry Andric next_line.line = this_line.line + i + 1;
48914f1b3e8SDimitry Andric auto pos = source_lines_seen.find(next_line.file);
49014f1b3e8SDimitry Andric if (pos != source_lines_seen.end()) {
49114f1b3e8SDimitry Andric if (pos->second.count(next_line.line) == 1)
49214f1b3e8SDimitry Andric break;
49314f1b3e8SDimitry Andric pos->second.insert(next_line.line);
49414f1b3e8SDimitry Andric }
49514f1b3e8SDimitry Andric source_lines_to_display.lines.push_back(next_line);
49614f1b3e8SDimitry Andric }
49714f1b3e8SDimitry Andric }
49814f1b3e8SDimitry Andric previous_line = this_line;
499f034231aSEd Maste }
500f034231aSEd Maste }
501f034231aSEd Maste }
502f034231aSEd Maste }
50314f1b3e8SDimitry Andric } else {
504f034231aSEd Maste sc.Clear(true);
505f034231aSEd Maste }
506f034231aSEd Maste }
507f034231aSEd Maste
50814f1b3e8SDimitry Andric if (source_lines_to_display.lines.size() > 0) {
50914f1b3e8SDimitry Andric strm.EOL();
51014f1b3e8SDimitry Andric for (size_t idx = 0; idx < source_lines_to_display.lines.size();
51114f1b3e8SDimitry Andric idx++) {
51214f1b3e8SDimitry Andric SourceLine ln = source_lines_to_display.lines[idx];
51314f1b3e8SDimitry Andric const char *line_highlight = "";
51414f1b3e8SDimitry Andric if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
51514f1b3e8SDimitry Andric line_highlight = "->";
51614f1b3e8SDimitry Andric } else if (idx == source_lines_to_display.current_source_line) {
51714f1b3e8SDimitry Andric line_highlight = "**";
51814f1b3e8SDimitry Andric }
51914f1b3e8SDimitry Andric source_manager.DisplaySourceLinesWithLineNumbers(
52014f1b3e8SDimitry Andric ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm);
52114f1b3e8SDimitry Andric }
52214f1b3e8SDimitry Andric if (source_lines_to_display.print_source_context_end_eol)
523f034231aSEd Maste strm.EOL();
524f034231aSEd Maste }
52514f1b3e8SDimitry Andric
52614f1b3e8SDimitry Andric const bool show_bytes = (options & eOptionShowBytes) != 0;
5271f917f69SDimitry Andric const bool show_control_flow_kind =
5281f917f69SDimitry Andric (options & eOptionShowControlFlowKind) != 0;
5291f917f69SDimitry Andric inst->Dump(&strm, max_opcode_byte_size, true, show_bytes,
5301f917f69SDimitry Andric show_control_flow_kind, &exe_ctx, &sc, &prev_sc, nullptr,
5311f917f69SDimitry Andric address_text_size);
53214f1b3e8SDimitry Andric strm.EOL();
53314f1b3e8SDimitry Andric } else {
534f034231aSEd Maste break;
535f034231aSEd Maste }
536f034231aSEd Maste }
537f034231aSEd Maste }
538f034231aSEd Maste
Disassemble(Debugger & debugger,const ArchSpec & arch,StackFrame & frame,Stream & strm)53914f1b3e8SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
540b60736ecSDimitry Andric StackFrame &frame, Stream &strm) {
541f034231aSEd Maste AddressRange range;
54214f1b3e8SDimitry Andric SymbolContext sc(
543b60736ecSDimitry Andric frame.GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
54414f1b3e8SDimitry Andric if (sc.function) {
545f034231aSEd Maste range = sc.function->GetAddressRange();
54614f1b3e8SDimitry Andric } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
5475e95aa85SEd Maste range.GetBaseAddress() = sc.symbol->GetAddressRef();
548f034231aSEd Maste range.SetByteSize(sc.symbol->GetByteSize());
54914f1b3e8SDimitry Andric } else {
550b60736ecSDimitry Andric range.GetBaseAddress() = frame.GetFrameCodeAddress();
551f034231aSEd Maste }
552f034231aSEd Maste
553f034231aSEd Maste if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
554f034231aSEd Maste range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
555f034231aSEd Maste
556b60736ecSDimitry Andric Disassembler::Limit limit = {Disassembler::Limit::Bytes,
557b60736ecSDimitry Andric range.GetByteSize()};
558b60736ecSDimitry Andric if (limit.value == 0)
559b60736ecSDimitry Andric limit.value = DEFAULT_DISASM_BYTE_SIZE;
560b60736ecSDimitry Andric
561b60736ecSDimitry Andric return Disassemble(debugger, arch, nullptr, nullptr, frame,
562b60736ecSDimitry Andric range.GetBaseAddress(), limit, false, 0, 0, strm);
563f034231aSEd Maste }
564f034231aSEd Maste
Instruction(const Address & address,AddressClass addr_class)56514f1b3e8SDimitry Andric Instruction::Instruction(const Address &address, AddressClass addr_class)
56614f1b3e8SDimitry Andric : m_address(address), m_address_class(addr_class), m_opcode(),
56714f1b3e8SDimitry Andric m_calculated_strings(false) {}
568f034231aSEd Maste
569f3fbd1c0SDimitry Andric Instruction::~Instruction() = default;
570f034231aSEd Maste
GetAddressClass()57114f1b3e8SDimitry Andric AddressClass Instruction::GetAddressClass() {
572f73363f1SDimitry Andric if (m_address_class == AddressClass::eInvalid)
573f034231aSEd Maste m_address_class = m_address.GetAddressClass();
574f034231aSEd Maste return m_address_class;
575f034231aSEd Maste }
576f034231aSEd Maste
GetNameForInstructionControlFlowKind(lldb::InstructionControlFlowKind instruction_control_flow_kind)57708e8dd7bSDimitry Andric const char *Instruction::GetNameForInstructionControlFlowKind(
57808e8dd7bSDimitry Andric lldb::InstructionControlFlowKind instruction_control_flow_kind) {
57908e8dd7bSDimitry Andric switch (instruction_control_flow_kind) {
58008e8dd7bSDimitry Andric case eInstructionControlFlowKindUnknown:
58108e8dd7bSDimitry Andric return "unknown";
58208e8dd7bSDimitry Andric case eInstructionControlFlowKindOther:
58308e8dd7bSDimitry Andric return "other";
58408e8dd7bSDimitry Andric case eInstructionControlFlowKindCall:
58508e8dd7bSDimitry Andric return "call";
58608e8dd7bSDimitry Andric case eInstructionControlFlowKindReturn:
58708e8dd7bSDimitry Andric return "return";
58808e8dd7bSDimitry Andric case eInstructionControlFlowKindJump:
58908e8dd7bSDimitry Andric return "jump";
59008e8dd7bSDimitry Andric case eInstructionControlFlowKindCondJump:
59108e8dd7bSDimitry Andric return "cond jump";
59208e8dd7bSDimitry Andric case eInstructionControlFlowKindFarCall:
59308e8dd7bSDimitry Andric return "far call";
59408e8dd7bSDimitry Andric case eInstructionControlFlowKindFarReturn:
59508e8dd7bSDimitry Andric return "far return";
59608e8dd7bSDimitry Andric case eInstructionControlFlowKindFarJump:
59708e8dd7bSDimitry Andric return "far jump";
59808e8dd7bSDimitry Andric }
599e3b55780SDimitry Andric llvm_unreachable("Fully covered switch above!");
60008e8dd7bSDimitry Andric }
60108e8dd7bSDimitry Andric
Dump(lldb_private::Stream * s,uint32_t max_opcode_byte_size,bool show_address,bool show_bytes,bool show_control_flow_kind,const ExecutionContext * exe_ctx,const SymbolContext * sym_ctx,const SymbolContext * prev_sym_ctx,const FormatEntity::Entry * disassembly_addr_format,size_t max_address_text_size)60214f1b3e8SDimitry Andric void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
60314f1b3e8SDimitry Andric bool show_address, bool show_bytes,
6041f917f69SDimitry Andric bool show_control_flow_kind,
605205afe67SEd Maste const ExecutionContext *exe_ctx,
606205afe67SEd Maste const SymbolContext *sym_ctx,
607205afe67SEd Maste const SymbolContext *prev_sym_ctx,
6085e95aa85SEd Maste const FormatEntity::Entry *disassembly_addr_format,
60914f1b3e8SDimitry Andric size_t max_address_text_size) {
610f034231aSEd Maste size_t opcode_column_width = 7;
611f034231aSEd Maste const size_t operand_column_width = 25;
612f034231aSEd Maste
613f034231aSEd Maste CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
614f034231aSEd Maste
615f034231aSEd Maste StreamString ss;
616f034231aSEd Maste
61714f1b3e8SDimitry Andric if (show_address) {
61814f1b3e8SDimitry Andric Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
61914f1b3e8SDimitry Andric prev_sym_ctx, exe_ctx, &m_address, ss);
6205e95aa85SEd Maste ss.FillLastLineToColumn(max_address_text_size, ' ');
621f034231aSEd Maste }
622f034231aSEd Maste
62314f1b3e8SDimitry Andric if (show_bytes) {
62414f1b3e8SDimitry Andric if (m_opcode.GetType() == Opcode::eTypeBytes) {
625f73363f1SDimitry Andric // x86_64 and i386 are the only ones that use bytes right now so pad out
626f73363f1SDimitry Andric // the byte dump to be able to always show 15 bytes (3 chars each) plus a
627f73363f1SDimitry Andric // space
628f034231aSEd Maste if (max_opcode_byte_size > 0)
629f034231aSEd Maste m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
630f034231aSEd Maste else
631f034231aSEd Maste m_opcode.Dump(&ss, 15 * 3 + 1);
63214f1b3e8SDimitry Andric } else {
633f73363f1SDimitry Andric // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000
634f73363f1SDimitry Andric // (10 spaces) plus two for padding...
635f034231aSEd Maste if (max_opcode_byte_size > 0)
636f034231aSEd Maste m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
637f034231aSEd Maste else
638f034231aSEd Maste m_opcode.Dump(&ss, 12);
639f034231aSEd Maste }
640f034231aSEd Maste }
641f034231aSEd Maste
6421f917f69SDimitry Andric if (show_control_flow_kind) {
64308e8dd7bSDimitry Andric lldb::InstructionControlFlowKind instruction_control_flow_kind =
64408e8dd7bSDimitry Andric GetControlFlowKind(exe_ctx);
64508e8dd7bSDimitry Andric ss.Printf("%-12s", GetNameForInstructionControlFlowKind(
64608e8dd7bSDimitry Andric instruction_control_flow_kind));
6471f917f69SDimitry Andric }
6481f917f69SDimitry Andric
649b1c73532SDimitry Andric bool show_color = false;
650b1c73532SDimitry Andric if (exe_ctx) {
651b1c73532SDimitry Andric if (TargetSP target_sp = exe_ctx->GetTargetSP()) {
652b1c73532SDimitry Andric show_color = target_sp->GetDebugger().GetUseColor();
653b1c73532SDimitry Andric }
654b1c73532SDimitry Andric }
655205afe67SEd Maste const size_t opcode_pos = ss.GetSizeOfLastLine();
656b1c73532SDimitry Andric const std::string &opcode_name =
657b1c73532SDimitry Andric show_color ? m_markup_opcode_name : m_opcode_name;
658b1c73532SDimitry Andric const std::string &mnemonics = show_color ? m_markup_mnemonics : m_mnemonics;
659f034231aSEd Maste
660f034231aSEd Maste // The default opcode size of 7 characters is plenty for most architectures
661f034231aSEd Maste // but some like arm can pull out the occasional vqrshrun.s16. We won't get
662b1c73532SDimitry Andric // consistent column spacing in these cases, unfortunately. Also note that we
663b1c73532SDimitry Andric // need to directly use m_opcode_name here (instead of opcode_name) so we
664b1c73532SDimitry Andric // don't include color codes as characters.
66514f1b3e8SDimitry Andric if (m_opcode_name.length() >= opcode_column_width) {
666f034231aSEd Maste opcode_column_width = m_opcode_name.length() + 1;
667f034231aSEd Maste }
668f034231aSEd Maste
669b1c73532SDimitry Andric ss.PutCString(opcode_name);
670f034231aSEd Maste ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
671b1c73532SDimitry Andric ss.PutCString(mnemonics);
672f034231aSEd Maste
67314f1b3e8SDimitry Andric if (!m_comment.empty()) {
67414f1b3e8SDimitry Andric ss.FillLastLineToColumn(
67514f1b3e8SDimitry Andric opcode_pos + opcode_column_width + operand_column_width, ' ');
676f034231aSEd Maste ss.PutCString(" ; ");
67714f1b3e8SDimitry Andric ss.PutCString(m_comment);
678f034231aSEd Maste }
67914f1b3e8SDimitry Andric s->PutCString(ss.GetString());
680f034231aSEd Maste }
681f034231aSEd Maste
DumpEmulation(const ArchSpec & arch)68214f1b3e8SDimitry Andric bool Instruction::DumpEmulation(const ArchSpec &arch) {
6835f29bb8aSDimitry Andric std::unique_ptr<EmulateInstruction> insn_emulator_up(
68414f1b3e8SDimitry Andric EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
6855f29bb8aSDimitry Andric if (insn_emulator_up) {
6865f29bb8aSDimitry Andric insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
6875f29bb8aSDimitry Andric return insn_emulator_up->EvaluateInstruction(0);
688f034231aSEd Maste }
689f034231aSEd Maste
690f034231aSEd Maste return false;
691f034231aSEd Maste }
692f034231aSEd Maste
CanSetBreakpoint()6938b4000f1SDimitry Andric bool Instruction::CanSetBreakpoint () {
6948b4000f1SDimitry Andric return !HasDelaySlot();
6958b4000f1SDimitry Andric }
6968b4000f1SDimitry Andric
HasDelaySlot()69714f1b3e8SDimitry Andric bool Instruction::HasDelaySlot() {
698e81d9d49SDimitry Andric // Default is false.
699e81d9d49SDimitry Andric return false;
700e81d9d49SDimitry Andric }
701e81d9d49SDimitry Andric
ReadArray(FILE * in_file,Stream & out_stream,OptionValue::Type data_type)7027fa27ce4SDimitry Andric OptionValueSP Instruction::ReadArray(FILE *in_file, Stream &out_stream,
70314f1b3e8SDimitry Andric OptionValue::Type data_type) {
704f034231aSEd Maste bool done = false;
705f034231aSEd Maste char buffer[1024];
706f034231aSEd Maste
70774a628f7SDimitry Andric auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type);
708f034231aSEd Maste
709f034231aSEd Maste int idx = 0;
71014f1b3e8SDimitry Andric while (!done) {
71114f1b3e8SDimitry Andric if (!fgets(buffer, 1023, in_file)) {
7127fa27ce4SDimitry Andric out_stream.Printf(
71314f1b3e8SDimitry Andric "Instruction::ReadArray: Error reading file (fgets).\n");
714f034231aSEd Maste option_value_sp.reset();
715f034231aSEd Maste return option_value_sp;
716f034231aSEd Maste }
717f034231aSEd Maste
718f034231aSEd Maste std::string line(buffer);
719f034231aSEd Maste
720f034231aSEd Maste size_t len = line.size();
72114f1b3e8SDimitry Andric if (line[len - 1] == '\n') {
722f034231aSEd Maste line[len - 1] = '\0';
723f034231aSEd Maste line.resize(len - 1);
724f034231aSEd Maste }
725f034231aSEd Maste
72614f1b3e8SDimitry Andric if ((line.size() == 1) && line[0] == ']') {
727f034231aSEd Maste done = true;
728f034231aSEd Maste line.clear();
729f034231aSEd Maste }
730f034231aSEd Maste
73114f1b3e8SDimitry Andric if (!line.empty()) {
732f034231aSEd Maste std::string value;
73314f1b3e8SDimitry Andric static RegularExpression g_reg_exp(
73414f1b3e8SDimitry Andric llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$"));
735ead24645SDimitry Andric llvm::SmallVector<llvm::StringRef, 2> matches;
736ead24645SDimitry Andric if (g_reg_exp.Execute(line, &matches))
737ead24645SDimitry Andric value = matches[1].str();
738f034231aSEd Maste else
739f034231aSEd Maste value = line;
740f034231aSEd Maste
741f034231aSEd Maste OptionValueSP data_value_sp;
74214f1b3e8SDimitry Andric switch (data_type) {
743f034231aSEd Maste case OptionValue::eTypeUInt64:
74474a628f7SDimitry Andric data_value_sp = std::make_shared<OptionValueUInt64>(0, 0);
7455e95aa85SEd Maste data_value_sp->SetValueFromString(value);
746f034231aSEd Maste break;
747f034231aSEd Maste // Other types can be added later as needed.
748f034231aSEd Maste default:
74974a628f7SDimitry Andric data_value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
750f034231aSEd Maste break;
751f034231aSEd Maste }
752f034231aSEd Maste
753f034231aSEd Maste option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
754f034231aSEd Maste ++idx;
755f034231aSEd Maste }
756f034231aSEd Maste }
757f034231aSEd Maste
758f034231aSEd Maste return option_value_sp;
759f034231aSEd Maste }
760f034231aSEd Maste
ReadDictionary(FILE * in_file,Stream & out_stream)7617fa27ce4SDimitry Andric OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream &out_stream) {
762f034231aSEd Maste bool done = false;
763f034231aSEd Maste char buffer[1024];
764f034231aSEd Maste
76574a628f7SDimitry Andric auto option_value_sp = std::make_shared<OptionValueDictionary>();
7667fa27ce4SDimitry Andric static constexpr llvm::StringLiteral encoding_key("data_encoding");
767f034231aSEd Maste OptionValue::Type data_type = OptionValue::eTypeInvalid;
768f034231aSEd Maste
76914f1b3e8SDimitry Andric while (!done) {
770f034231aSEd Maste // Read the next line in the file
77114f1b3e8SDimitry Andric if (!fgets(buffer, 1023, in_file)) {
7727fa27ce4SDimitry Andric out_stream.Printf(
77314f1b3e8SDimitry Andric "Instruction::ReadDictionary: Error reading file (fgets).\n");
774f034231aSEd Maste option_value_sp.reset();
775f034231aSEd Maste return option_value_sp;
776f034231aSEd Maste }
777f034231aSEd Maste
778f034231aSEd Maste // Check to see if the line contains the end-of-dictionary marker ("}")
779f034231aSEd Maste std::string line(buffer);
780f034231aSEd Maste
781f034231aSEd Maste size_t len = line.size();
78214f1b3e8SDimitry Andric if (line[len - 1] == '\n') {
783f034231aSEd Maste line[len - 1] = '\0';
784f034231aSEd Maste line.resize(len - 1);
785f034231aSEd Maste }
786f034231aSEd Maste
78714f1b3e8SDimitry Andric if ((line.size() == 1) && (line[0] == '}')) {
788f034231aSEd Maste done = true;
789f034231aSEd Maste line.clear();
790f034231aSEd Maste }
791f034231aSEd Maste
79214f1b3e8SDimitry Andric // Try to find a key-value pair in the current line and add it to the
79314f1b3e8SDimitry Andric // dictionary.
79414f1b3e8SDimitry Andric if (!line.empty()) {
79514f1b3e8SDimitry Andric static RegularExpression g_reg_exp(llvm::StringRef(
79614f1b3e8SDimitry Andric "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"));
797f034231aSEd Maste
798ead24645SDimitry Andric llvm::SmallVector<llvm::StringRef, 3> matches;
799ead24645SDimitry Andric
800ead24645SDimitry Andric bool reg_exp_success = g_reg_exp.Execute(line, &matches);
801f034231aSEd Maste std::string key;
802f034231aSEd Maste std::string value;
80314f1b3e8SDimitry Andric if (reg_exp_success) {
804ead24645SDimitry Andric key = matches[1].str();
805ead24645SDimitry Andric value = matches[2].str();
80614f1b3e8SDimitry Andric } else {
8077fa27ce4SDimitry Andric out_stream.Printf("Instruction::ReadDictionary: Failure executing "
80814f1b3e8SDimitry Andric "regular expression.\n");
809f034231aSEd Maste option_value_sp.reset();
810f034231aSEd Maste return option_value_sp;
811f034231aSEd Maste }
812f034231aSEd Maste
813f034231aSEd Maste // Check value to see if it's the start of an array or dictionary.
814f034231aSEd Maste
815f034231aSEd Maste lldb::OptionValueSP value_sp;
816f034231aSEd Maste assert(value.empty() == false);
817f034231aSEd Maste assert(key.empty() == false);
818f034231aSEd Maste
81914f1b3e8SDimitry Andric if (value[0] == '{') {
820f034231aSEd Maste assert(value.size() == 1);
821f034231aSEd Maste // value is a dictionary
822f034231aSEd Maste value_sp = ReadDictionary(in_file, out_stream);
82314f1b3e8SDimitry Andric if (!value_sp) {
824f034231aSEd Maste option_value_sp.reset();
825f034231aSEd Maste return option_value_sp;
826f034231aSEd Maste }
82714f1b3e8SDimitry Andric } else if (value[0] == '[') {
828f034231aSEd Maste assert(value.size() == 1);
829f034231aSEd Maste // value is an array
830f034231aSEd Maste value_sp = ReadArray(in_file, out_stream, data_type);
83114f1b3e8SDimitry Andric if (!value_sp) {
832f034231aSEd Maste option_value_sp.reset();
833f034231aSEd Maste return option_value_sp;
834f034231aSEd Maste }
835f73363f1SDimitry Andric // We've used the data_type to read an array; re-set the type to
836f73363f1SDimitry Andric // Invalid
837f034231aSEd Maste data_type = OptionValue::eTypeInvalid;
83814f1b3e8SDimitry Andric } else if ((value[0] == '0') && (value[1] == 'x')) {
83974a628f7SDimitry Andric value_sp = std::make_shared<OptionValueUInt64>(0, 0);
8405e95aa85SEd Maste value_sp->SetValueFromString(value);
84114f1b3e8SDimitry Andric } else {
842f034231aSEd Maste size_t len = value.size();
843f034231aSEd Maste if ((value[0] == '"') && (value[len - 1] == '"'))
844f034231aSEd Maste value = value.substr(1, len - 2);
84574a628f7SDimitry Andric value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
846f034231aSEd Maste }
847f034231aSEd Maste
8487fa27ce4SDimitry Andric if (key == encoding_key) {
84914f1b3e8SDimitry Andric // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data
8507fa27ce4SDimitry Andric // indicating the data type of an upcoming array (usually the next bit
8517fa27ce4SDimitry Andric // of data to be read in).
8527fa27ce4SDimitry Andric if (llvm::StringRef(value) == "uint32_t")
853f034231aSEd Maste data_type = OptionValue::eTypeUInt64;
85414f1b3e8SDimitry Andric } else
8557fa27ce4SDimitry Andric option_value_sp->GetAsDictionary()->SetValueForKey(key, value_sp,
85614f1b3e8SDimitry Andric false);
857f034231aSEd Maste }
858f034231aSEd Maste }
859f034231aSEd Maste
860f034231aSEd Maste return option_value_sp;
861f034231aSEd Maste }
862f034231aSEd Maste
TestEmulation(Stream & out_stream,const char * file_name)8637fa27ce4SDimitry Andric bool Instruction::TestEmulation(Stream &out_stream, const char *file_name) {
86414f1b3e8SDimitry Andric if (!file_name) {
8657fa27ce4SDimitry Andric out_stream.Printf("Instruction::TestEmulation: Missing file_name.");
866f034231aSEd Maste return false;
867f034231aSEd Maste }
86894994d37SDimitry Andric FILE *test_file = FileSystem::Instance().Fopen(file_name, "r");
86914f1b3e8SDimitry Andric if (!test_file) {
8707fa27ce4SDimitry Andric out_stream.Printf(
87114f1b3e8SDimitry Andric "Instruction::TestEmulation: Attempt to open test file failed.");
872f034231aSEd Maste return false;
873f034231aSEd Maste }
874f034231aSEd Maste
875f034231aSEd Maste char buffer[256];
87614f1b3e8SDimitry Andric if (!fgets(buffer, 255, test_file)) {
8777fa27ce4SDimitry Andric out_stream.Printf(
87814f1b3e8SDimitry Andric "Instruction::TestEmulation: Error reading first line of test file.\n");
879f034231aSEd Maste fclose(test_file);
880f034231aSEd Maste return false;
881f034231aSEd Maste }
882f034231aSEd Maste
88314f1b3e8SDimitry Andric if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
8847fa27ce4SDimitry Andric out_stream.Printf("Instructin::TestEmulation: Test file does not contain "
88514f1b3e8SDimitry Andric "emulation state dictionary\n");
886f034231aSEd Maste fclose(test_file);
887f034231aSEd Maste return false;
888f034231aSEd Maste }
889f034231aSEd Maste
89014f1b3e8SDimitry Andric // Read all the test information from the test file into an
89114f1b3e8SDimitry Andric // OptionValueDictionary.
892f034231aSEd Maste
893f034231aSEd Maste OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
89414f1b3e8SDimitry Andric if (!data_dictionary_sp) {
8957fa27ce4SDimitry Andric out_stream.Printf(
89614f1b3e8SDimitry Andric "Instruction::TestEmulation: Error reading Dictionary Object.\n");
897f034231aSEd Maste fclose(test_file);
898f034231aSEd Maste return false;
899f034231aSEd Maste }
900f034231aSEd Maste
901f034231aSEd Maste fclose(test_file);
902f034231aSEd Maste
90314f1b3e8SDimitry Andric OptionValueDictionary *data_dictionary =
90414f1b3e8SDimitry Andric data_dictionary_sp->GetAsDictionary();
9057fa27ce4SDimitry Andric static constexpr llvm::StringLiteral description_key("assembly_string");
9067fa27ce4SDimitry Andric static constexpr llvm::StringLiteral triple_key("triple");
907f034231aSEd Maste
908f034231aSEd Maste OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
909f034231aSEd Maste
91014f1b3e8SDimitry Andric if (!value_sp) {
9117fa27ce4SDimitry Andric out_stream.Printf("Instruction::TestEmulation: Test file does not "
91214f1b3e8SDimitry Andric "contain description string.\n");
913f034231aSEd Maste return false;
914f034231aSEd Maste }
915f034231aSEd Maste
9167fa27ce4SDimitry Andric SetDescription(value_sp->GetValueAs<llvm::StringRef>().value_or(""));
917f034231aSEd Maste
918f034231aSEd Maste value_sp = data_dictionary->GetValueForKey(triple_key);
91914f1b3e8SDimitry Andric if (!value_sp) {
9207fa27ce4SDimitry Andric out_stream.Printf(
92114f1b3e8SDimitry Andric "Instruction::TestEmulation: Test file does not contain triple.\n");
922f034231aSEd Maste return false;
923f034231aSEd Maste }
924f034231aSEd Maste
925f034231aSEd Maste ArchSpec arch;
9267fa27ce4SDimitry Andric arch.SetTriple(
9277fa27ce4SDimitry Andric llvm::Triple(value_sp->GetValueAs<llvm::StringRef>().value_or("")));
928f034231aSEd Maste
929f034231aSEd Maste bool success = false;
9305f29bb8aSDimitry Andric std::unique_ptr<EmulateInstruction> insn_emulator_up(
93114f1b3e8SDimitry Andric EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
9325f29bb8aSDimitry Andric if (insn_emulator_up)
93314f1b3e8SDimitry Andric success =
9345f29bb8aSDimitry Andric insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary);
935f034231aSEd Maste
936f034231aSEd Maste if (success)
9377fa27ce4SDimitry Andric out_stream.Printf("Emulation test succeeded.");
938f034231aSEd Maste else
9397fa27ce4SDimitry Andric out_stream.Printf("Emulation test failed.");
940f034231aSEd Maste
941f034231aSEd Maste return success;
942f034231aSEd Maste }
943f034231aSEd Maste
Emulate(const ArchSpec & arch,uint32_t evaluate_options,void * baton,EmulateInstruction::ReadMemoryCallback read_mem_callback,EmulateInstruction::WriteMemoryCallback write_mem_callback,EmulateInstruction::ReadRegisterCallback read_reg_callback,EmulateInstruction::WriteRegisterCallback write_reg_callback)94414f1b3e8SDimitry Andric bool Instruction::Emulate(
94514f1b3e8SDimitry Andric const ArchSpec &arch, uint32_t evaluate_options, void *baton,
946f034231aSEd Maste EmulateInstruction::ReadMemoryCallback read_mem_callback,
947f034231aSEd Maste EmulateInstruction::WriteMemoryCallback write_mem_callback,
948f034231aSEd Maste EmulateInstruction::ReadRegisterCallback read_reg_callback,
94914f1b3e8SDimitry Andric EmulateInstruction::WriteRegisterCallback write_reg_callback) {
9505f29bb8aSDimitry Andric std::unique_ptr<EmulateInstruction> insn_emulator_up(
95114f1b3e8SDimitry Andric EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
9525f29bb8aSDimitry Andric if (insn_emulator_up) {
9535f29bb8aSDimitry Andric insn_emulator_up->SetBaton(baton);
9545f29bb8aSDimitry Andric insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback,
95514f1b3e8SDimitry Andric read_reg_callback, write_reg_callback);
9565f29bb8aSDimitry Andric insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
9575f29bb8aSDimitry Andric return insn_emulator_up->EvaluateInstruction(evaluate_options);
958f034231aSEd Maste }
959f034231aSEd Maste
960f034231aSEd Maste return false;
961f034231aSEd Maste }
962f034231aSEd Maste
GetData(DataExtractor & data)96314f1b3e8SDimitry Andric uint32_t Instruction::GetData(DataExtractor &data) {
964f034231aSEd Maste return m_opcode.GetData(data);
965f034231aSEd Maste }
966f034231aSEd Maste
InstructionList()96714f1b3e8SDimitry Andric InstructionList::InstructionList() : m_instructions() {}
968f034231aSEd Maste
969f3fbd1c0SDimitry Andric InstructionList::~InstructionList() = default;
970f034231aSEd Maste
GetSize() const97114f1b3e8SDimitry Andric size_t InstructionList::GetSize() const { return m_instructions.size(); }
972f034231aSEd Maste
GetMaxOpcocdeByteSize() const97314f1b3e8SDimitry Andric uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
974f034231aSEd Maste uint32_t max_inst_size = 0;
975f034231aSEd Maste collection::const_iterator pos, end;
97614f1b3e8SDimitry Andric for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
97714f1b3e8SDimitry Andric ++pos) {
978f034231aSEd Maste uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
979f034231aSEd Maste if (max_inst_size < inst_size)
980f034231aSEd Maste max_inst_size = inst_size;
981f034231aSEd Maste }
982f034231aSEd Maste return max_inst_size;
983f034231aSEd Maste }
984f034231aSEd Maste
GetInstructionAtIndex(size_t idx) const98514f1b3e8SDimitry Andric InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
986f034231aSEd Maste InstructionSP inst_sp;
987f034231aSEd Maste if (idx < m_instructions.size())
988f034231aSEd Maste inst_sp = m_instructions[idx];
989f034231aSEd Maste return inst_sp;
990f034231aSEd Maste }
991f034231aSEd Maste
GetInstructionAtAddress(const Address & address)992b60736ecSDimitry Andric InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) {
993b60736ecSDimitry Andric uint32_t index = GetIndexOfInstructionAtAddress(address);
994b60736ecSDimitry Andric if (index != UINT32_MAX)
995b60736ecSDimitry Andric return GetInstructionAtIndex(index);
996b60736ecSDimitry Andric return nullptr;
997b60736ecSDimitry Andric }
998b60736ecSDimitry Andric
Dump(Stream * s,bool show_address,bool show_bytes,bool show_control_flow_kind,const ExecutionContext * exe_ctx)99914f1b3e8SDimitry Andric void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
10001f917f69SDimitry Andric bool show_control_flow_kind,
100114f1b3e8SDimitry Andric const ExecutionContext *exe_ctx) {
1002f034231aSEd Maste const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
1003f034231aSEd Maste collection::const_iterator pos, begin, end;
100412bd4897SEd Maste
1005f3fbd1c0SDimitry Andric const FormatEntity::Entry *disassembly_format = nullptr;
100612bd4897SEd Maste FormatEntity::Entry format;
100714f1b3e8SDimitry Andric if (exe_ctx && exe_ctx->HasTargetScope()) {
100814f1b3e8SDimitry Andric disassembly_format =
100914f1b3e8SDimitry Andric exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
101014f1b3e8SDimitry Andric } else {
101112bd4897SEd Maste FormatEntity::Parse("${addr}: ", format);
101212bd4897SEd Maste disassembly_format = &format;
101312bd4897SEd Maste }
101412bd4897SEd Maste
1015f034231aSEd Maste for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
101614f1b3e8SDimitry Andric pos != end; ++pos) {
1017f034231aSEd Maste if (pos != begin)
1018f034231aSEd Maste s->EOL();
10191f917f69SDimitry Andric (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes,
10201f917f69SDimitry Andric show_control_flow_kind, exe_ctx, nullptr, nullptr,
10211f917f69SDimitry Andric disassembly_format, 0);
1022f034231aSEd Maste }
1023f034231aSEd Maste }
1024f034231aSEd Maste
Clear()102514f1b3e8SDimitry Andric void InstructionList::Clear() { m_instructions.clear(); }
1026f034231aSEd Maste
Append(lldb::InstructionSP & inst_sp)102714f1b3e8SDimitry Andric void InstructionList::Append(lldb::InstructionSP &inst_sp) {
1028f034231aSEd Maste if (inst_sp)
1029f034231aSEd Maste m_instructions.push_back(inst_sp);
1030f034231aSEd Maste }
1031f034231aSEd Maste
1032f034231aSEd Maste uint32_t
GetIndexOfNextBranchInstruction(uint32_t start,bool ignore_calls,bool * found_calls) const103314f1b3e8SDimitry Andric InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
1034706b4fc4SDimitry Andric bool ignore_calls,
1035706b4fc4SDimitry Andric bool *found_calls) const {
1036f034231aSEd Maste size_t num_instructions = m_instructions.size();
1037f034231aSEd Maste
1038f034231aSEd Maste uint32_t next_branch = UINT32_MAX;
1039706b4fc4SDimitry Andric
1040706b4fc4SDimitry Andric if (found_calls)
1041706b4fc4SDimitry Andric *found_calls = false;
1042b60736ecSDimitry Andric for (size_t i = start; i < num_instructions; i++) {
104314f1b3e8SDimitry Andric if (m_instructions[i]->DoesBranch()) {
1044706b4fc4SDimitry Andric if (ignore_calls && m_instructions[i]->IsCall()) {
1045706b4fc4SDimitry Andric if (found_calls)
1046706b4fc4SDimitry Andric *found_calls = true;
10475f29bb8aSDimitry Andric continue;
1048706b4fc4SDimitry Andric }
1049f034231aSEd Maste next_branch = i;
1050f034231aSEd Maste break;
1051f034231aSEd Maste }
1052f034231aSEd Maste }
10535e95aa85SEd Maste
1054f034231aSEd Maste return next_branch;
1055f034231aSEd Maste }
1056f034231aSEd Maste
1057f034231aSEd Maste uint32_t
GetIndexOfInstructionAtAddress(const Address & address)105814f1b3e8SDimitry Andric InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
1059f034231aSEd Maste size_t num_instructions = m_instructions.size();
1060f034231aSEd Maste uint32_t index = UINT32_MAX;
106114f1b3e8SDimitry Andric for (size_t i = 0; i < num_instructions; i++) {
106214f1b3e8SDimitry Andric if (m_instructions[i]->GetAddress() == address) {
1063f034231aSEd Maste index = i;
1064f034231aSEd Maste break;
1065f034231aSEd Maste }
1066f034231aSEd Maste }
1067f034231aSEd Maste return index;
1068f034231aSEd Maste }
1069f034231aSEd Maste
1070866dcdacSEd Maste uint32_t
GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,Target & target)107114f1b3e8SDimitry Andric InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
107214f1b3e8SDimitry Andric Target &target) {
1073866dcdacSEd Maste Address address;
1074866dcdacSEd Maste address.SetLoadAddress(load_addr, &target);
1075866dcdacSEd Maste return GetIndexOfInstructionAtAddress(address);
1076866dcdacSEd Maste }
1077866dcdacSEd Maste
ParseInstructions(Target & target,Address start,Limit limit,Stream * error_strm_ptr,bool force_live_memory)1078cfca06d7SDimitry Andric size_t Disassembler::ParseInstructions(Target &target, Address start,
1079cfca06d7SDimitry Andric Limit limit, Stream *error_strm_ptr,
1080344a3780SDimitry Andric bool force_live_memory) {
1081cfca06d7SDimitry Andric m_instruction_list.Clear();
1082cfca06d7SDimitry Andric
1083cfca06d7SDimitry Andric if (!start.IsValid())
1084f034231aSEd Maste return 0;
1085f034231aSEd Maste
1086cfca06d7SDimitry Andric start = ResolveAddress(target, start);
1087cfca06d7SDimitry Andric
1088cfca06d7SDimitry Andric addr_t byte_size = limit.value;
1089cfca06d7SDimitry Andric if (limit.kind == Limit::Instructions)
1090cfca06d7SDimitry Andric byte_size *= m_arch.GetMaximumOpcodeByteSize();
109174a628f7SDimitry Andric auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
1092f034231aSEd Maste
1093b76161e4SDimitry Andric Status error;
1094f034231aSEd Maste lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1095cfca06d7SDimitry Andric const size_t bytes_read =
1096344a3780SDimitry Andric target.ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(),
1097344a3780SDimitry Andric error, force_live_memory, &load_addr);
1098cfca06d7SDimitry Andric const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1099f034231aSEd Maste
1100cfca06d7SDimitry Andric if (bytes_read == 0) {
1101cfca06d7SDimitry Andric if (error_strm_ptr) {
1102cfca06d7SDimitry Andric if (const char *error_cstr = error.AsCString())
1103cfca06d7SDimitry Andric error_strm_ptr->Printf("error: %s\n", error_cstr);
1104cfca06d7SDimitry Andric }
1105cfca06d7SDimitry Andric return 0;
1106cfca06d7SDimitry Andric }
1107cfca06d7SDimitry Andric
110874a628f7SDimitry Andric if (bytes_read != data_sp->GetByteSize())
110974a628f7SDimitry Andric data_sp->SetByteSize(bytes_read);
111014f1b3e8SDimitry Andric DataExtractor data(data_sp, m_arch.GetByteOrder(),
1111f034231aSEd Maste m_arch.GetAddressByteSize());
1112cfca06d7SDimitry Andric return DecodeInstructions(start, data, 0,
1113cfca06d7SDimitry Andric limit.kind == Limit::Instructions ? limit.value
1114cfca06d7SDimitry Andric : UINT32_MAX,
111514f1b3e8SDimitry Andric false, data_from_file);
1116f034231aSEd Maste }
1117f034231aSEd Maste
1118f034231aSEd Maste // Disassembler copy constructor
Disassembler(const ArchSpec & arch,const char * flavor)111914f1b3e8SDimitry Andric Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
1120ac9a064cSDimitry Andric : m_arch(arch), m_instruction_list(), m_flavor() {
1121f3fbd1c0SDimitry Andric if (flavor == nullptr)
1122f034231aSEd Maste m_flavor.assign("default");
1123f034231aSEd Maste else
1124f034231aSEd Maste m_flavor.assign(flavor);
112512bd4897SEd Maste
112612bd4897SEd Maste // If this is an arm variant that can only include thumb (T16, T32)
1127f73363f1SDimitry Andric // instructions, force the arch triple to be "thumbv.." instead of "armv..."
112814f1b3e8SDimitry Andric if (arch.IsAlwaysThumbInstructions()) {
112912bd4897SEd Maste std::string thumb_arch_name(arch.GetTriple().getArchName().str());
113012bd4897SEd Maste // Replace "arm" with "thumb" so we get all thumb variants correct
113114f1b3e8SDimitry Andric if (thumb_arch_name.size() > 3) {
113212bd4897SEd Maste thumb_arch_name.erase(0, 3);
113312bd4897SEd Maste thumb_arch_name.insert(0, "thumb");
113412bd4897SEd Maste }
113512bd4897SEd Maste m_arch.SetTriple(thumb_arch_name.c_str());
113612bd4897SEd Maste }
1137f034231aSEd Maste }
1138f034231aSEd Maste
1139f3fbd1c0SDimitry Andric Disassembler::~Disassembler() = default;
1140f034231aSEd Maste
GetInstructionList()114114f1b3e8SDimitry Andric InstructionList &Disassembler::GetInstructionList() {
1142f034231aSEd Maste return m_instruction_list;
1143f034231aSEd Maste }
1144f034231aSEd Maste
GetInstructionList() const114514f1b3e8SDimitry Andric const InstructionList &Disassembler::GetInstructionList() const {
1146f034231aSEd Maste return m_instruction_list;
1147f034231aSEd Maste }
1148f034231aSEd Maste
1149f034231aSEd Maste // Class PseudoInstruction
1150f3fbd1c0SDimitry Andric
PseudoInstruction()115114f1b3e8SDimitry Andric PseudoInstruction::PseudoInstruction()
1152f73363f1SDimitry Andric : Instruction(Address(), AddressClass::eUnknown), m_description() {}
1153f034231aSEd Maste
1154f3fbd1c0SDimitry Andric PseudoInstruction::~PseudoInstruction() = default;
1155f034231aSEd Maste
DoesBranch()115614f1b3e8SDimitry Andric bool PseudoInstruction::DoesBranch() {
1157f034231aSEd Maste // This is NOT a valid question for a pseudo instruction.
1158f034231aSEd Maste return false;
1159f034231aSEd Maste }
1160f034231aSEd Maste
HasDelaySlot()116114f1b3e8SDimitry Andric bool PseudoInstruction::HasDelaySlot() {
1162e81d9d49SDimitry Andric // This is NOT a valid question for a pseudo instruction.
1163e81d9d49SDimitry Andric return false;
1164e81d9d49SDimitry Andric }
1165e81d9d49SDimitry Andric
IsLoad()1166c0981da4SDimitry Andric bool PseudoInstruction::IsLoad() { return false; }
1167c0981da4SDimitry Andric
IsAuthenticated()1168c0981da4SDimitry Andric bool PseudoInstruction::IsAuthenticated() { return false; }
1169c0981da4SDimitry Andric
Decode(const lldb_private::Disassembler & disassembler,const lldb_private::DataExtractor & data,lldb::offset_t data_offset)117014f1b3e8SDimitry Andric size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
1171f034231aSEd Maste const lldb_private::DataExtractor &data,
117214f1b3e8SDimitry Andric lldb::offset_t data_offset) {
1173f034231aSEd Maste return m_opcode.GetByteSize();
1174f034231aSEd Maste }
1175f034231aSEd Maste
SetOpcode(size_t opcode_size,void * opcode_data)117614f1b3e8SDimitry Andric void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
1177f034231aSEd Maste if (!opcode_data)
1178f034231aSEd Maste return;
1179f034231aSEd Maste
118014f1b3e8SDimitry Andric switch (opcode_size) {
118114f1b3e8SDimitry Andric case 8: {
1182f034231aSEd Maste uint8_t value8 = *((uint8_t *)opcode_data);
1183866dcdacSEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid);
1184f034231aSEd Maste break;
1185f034231aSEd Maste }
118614f1b3e8SDimitry Andric case 16: {
1187f034231aSEd Maste uint16_t value16 = *((uint16_t *)opcode_data);
1188866dcdacSEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid);
1189f034231aSEd Maste break;
1190f034231aSEd Maste }
119114f1b3e8SDimitry Andric case 32: {
1192f034231aSEd Maste uint32_t value32 = *((uint32_t *)opcode_data);
1193866dcdacSEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid);
1194f034231aSEd Maste break;
1195f034231aSEd Maste }
119614f1b3e8SDimitry Andric case 64: {
1197f034231aSEd Maste uint64_t value64 = *((uint64_t *)opcode_data);
1198866dcdacSEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid);
1199f034231aSEd Maste break;
1200f034231aSEd Maste }
1201f034231aSEd Maste default:
1202f034231aSEd Maste break;
1203f034231aSEd Maste }
1204f034231aSEd Maste }
1205f034231aSEd Maste
SetDescription(llvm::StringRef description)120614f1b3e8SDimitry Andric void PseudoInstruction::SetDescription(llvm::StringRef description) {
1207cfca06d7SDimitry Andric m_description = std::string(description);
1208f034231aSEd Maste }
120914f1b3e8SDimitry Andric
BuildRegister(ConstString & r)121014f1b3e8SDimitry Andric Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) {
121114f1b3e8SDimitry Andric Operand ret;
121214f1b3e8SDimitry Andric ret.m_type = Type::Register;
121314f1b3e8SDimitry Andric ret.m_register = r;
121414f1b3e8SDimitry Andric return ret;
121514f1b3e8SDimitry Andric }
121614f1b3e8SDimitry Andric
BuildImmediate(lldb::addr_t imm,bool neg)121714f1b3e8SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm,
121814f1b3e8SDimitry Andric bool neg) {
121914f1b3e8SDimitry Andric Operand ret;
122014f1b3e8SDimitry Andric ret.m_type = Type::Immediate;
122114f1b3e8SDimitry Andric ret.m_immediate = imm;
122214f1b3e8SDimitry Andric ret.m_negative = neg;
122314f1b3e8SDimitry Andric return ret;
122414f1b3e8SDimitry Andric }
122514f1b3e8SDimitry Andric
BuildImmediate(int64_t imm)122614f1b3e8SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) {
122714f1b3e8SDimitry Andric Operand ret;
122814f1b3e8SDimitry Andric ret.m_type = Type::Immediate;
122914f1b3e8SDimitry Andric if (imm < 0) {
123014f1b3e8SDimitry Andric ret.m_immediate = -imm;
123114f1b3e8SDimitry Andric ret.m_negative = true;
123214f1b3e8SDimitry Andric } else {
123314f1b3e8SDimitry Andric ret.m_immediate = imm;
123414f1b3e8SDimitry Andric ret.m_negative = false;
123514f1b3e8SDimitry Andric }
123614f1b3e8SDimitry Andric return ret;
123714f1b3e8SDimitry Andric }
123814f1b3e8SDimitry Andric
123914f1b3e8SDimitry Andric Instruction::Operand
BuildDereference(const Operand & ref)124014f1b3e8SDimitry Andric Instruction::Operand::BuildDereference(const Operand &ref) {
124114f1b3e8SDimitry Andric Operand ret;
124214f1b3e8SDimitry Andric ret.m_type = Type::Dereference;
124314f1b3e8SDimitry Andric ret.m_children = {ref};
124414f1b3e8SDimitry Andric return ret;
124514f1b3e8SDimitry Andric }
124614f1b3e8SDimitry Andric
BuildSum(const Operand & lhs,const Operand & rhs)124714f1b3e8SDimitry Andric Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs,
124814f1b3e8SDimitry Andric const Operand &rhs) {
124914f1b3e8SDimitry Andric Operand ret;
125014f1b3e8SDimitry Andric ret.m_type = Type::Sum;
125114f1b3e8SDimitry Andric ret.m_children = {lhs, rhs};
125214f1b3e8SDimitry Andric return ret;
125314f1b3e8SDimitry Andric }
125414f1b3e8SDimitry Andric
BuildProduct(const Operand & lhs,const Operand & rhs)125514f1b3e8SDimitry Andric Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs,
125614f1b3e8SDimitry Andric const Operand &rhs) {
125714f1b3e8SDimitry Andric Operand ret;
125814f1b3e8SDimitry Andric ret.m_type = Type::Product;
125914f1b3e8SDimitry Andric ret.m_children = {lhs, rhs};
126014f1b3e8SDimitry Andric return ret;
126114f1b3e8SDimitry Andric }
126214f1b3e8SDimitry Andric
126314f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchBinaryOp(std::function<bool (const Instruction::Operand &)> base,std::function<bool (const Instruction::Operand &)> left,std::function<bool (const Instruction::Operand &)> right)126414f1b3e8SDimitry Andric lldb_private::OperandMatchers::MatchBinaryOp(
126514f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)> base,
126614f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)> left,
126714f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)> right) {
126814f1b3e8SDimitry Andric return [base, left, right](const Instruction::Operand &op) -> bool {
126914f1b3e8SDimitry Andric return (base(op) && op.m_children.size() == 2 &&
127014f1b3e8SDimitry Andric ((left(op.m_children[0]) && right(op.m_children[1])) ||
127114f1b3e8SDimitry Andric (left(op.m_children[1]) && right(op.m_children[0]))));
127214f1b3e8SDimitry Andric };
127314f1b3e8SDimitry Andric }
127414f1b3e8SDimitry Andric
127514f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchUnaryOp(std::function<bool (const Instruction::Operand &)> base,std::function<bool (const Instruction::Operand &)> child)127614f1b3e8SDimitry Andric lldb_private::OperandMatchers::MatchUnaryOp(
127714f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)> base,
127814f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)> child) {
127914f1b3e8SDimitry Andric return [base, child](const Instruction::Operand &op) -> bool {
128014f1b3e8SDimitry Andric return (base(op) && op.m_children.size() == 1 && child(op.m_children[0]));
128114f1b3e8SDimitry Andric };
128214f1b3e8SDimitry Andric }
128314f1b3e8SDimitry Andric
128414f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchRegOp(const RegisterInfo & info)128514f1b3e8SDimitry Andric lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) {
128614f1b3e8SDimitry Andric return [&info](const Instruction::Operand &op) {
128714f1b3e8SDimitry Andric return (op.m_type == Instruction::Operand::Type::Register &&
128814f1b3e8SDimitry Andric (op.m_register == ConstString(info.name) ||
128914f1b3e8SDimitry Andric op.m_register == ConstString(info.alt_name)));
129014f1b3e8SDimitry Andric };
129114f1b3e8SDimitry Andric }
129214f1b3e8SDimitry Andric
129314f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchRegOp(ConstString & reg)129414f1b3e8SDimitry Andric lldb_private::OperandMatchers::FetchRegOp(ConstString ®) {
129514f1b3e8SDimitry Andric return [®](const Instruction::Operand &op) {
129614f1b3e8SDimitry Andric if (op.m_type != Instruction::Operand::Type::Register) {
129714f1b3e8SDimitry Andric return false;
129814f1b3e8SDimitry Andric }
129914f1b3e8SDimitry Andric reg = op.m_register;
130014f1b3e8SDimitry Andric return true;
130114f1b3e8SDimitry Andric };
130214f1b3e8SDimitry Andric }
130314f1b3e8SDimitry Andric
130414f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchImmOp(int64_t imm)130514f1b3e8SDimitry Andric lldb_private::OperandMatchers::MatchImmOp(int64_t imm) {
130614f1b3e8SDimitry Andric return [imm](const Instruction::Operand &op) {
130714f1b3e8SDimitry Andric return (op.m_type == Instruction::Operand::Type::Immediate &&
130814f1b3e8SDimitry Andric ((op.m_negative && op.m_immediate == (uint64_t)-imm) ||
130914f1b3e8SDimitry Andric (!op.m_negative && op.m_immediate == (uint64_t)imm)));
131014f1b3e8SDimitry Andric };
131114f1b3e8SDimitry Andric }
131214f1b3e8SDimitry Andric
131314f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchImmOp(int64_t & imm)131414f1b3e8SDimitry Andric lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) {
131514f1b3e8SDimitry Andric return [&imm](const Instruction::Operand &op) {
131614f1b3e8SDimitry Andric if (op.m_type != Instruction::Operand::Type::Immediate) {
131714f1b3e8SDimitry Andric return false;
131814f1b3e8SDimitry Andric }
131914f1b3e8SDimitry Andric if (op.m_negative) {
132014f1b3e8SDimitry Andric imm = -((int64_t)op.m_immediate);
132114f1b3e8SDimitry Andric } else {
132214f1b3e8SDimitry Andric imm = ((int64_t)op.m_immediate);
132314f1b3e8SDimitry Andric }
132414f1b3e8SDimitry Andric return true;
132514f1b3e8SDimitry Andric };
132614f1b3e8SDimitry Andric }
132714f1b3e8SDimitry Andric
132814f1b3e8SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchOpType(Instruction::Operand::Type type)132914f1b3e8SDimitry Andric lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) {
133014f1b3e8SDimitry Andric return [type](const Instruction::Operand &op) { return op.m_type == type; };
133114f1b3e8SDimitry Andric }
1332