xref: /src/contrib/llvm-project/lldb/source/Core/Disassembler.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 &reg) {
129514f1b3e8SDimitry Andric   return [&reg](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