1 //===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/Disassembler.h"
11 
12 // C Includes
13 // C++ Includes
14 #include <cstdio>
15 #include <cstring>
16 
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Core/DataBufferHeap.h"
20 #include "lldb/Core/DataExtractor.h"
21 #include "lldb/Core/Debugger.h"
22 #include "lldb/Core/EmulateInstruction.h"
23 #include "lldb/Core/Error.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/PluginManager.h"
26 #include "lldb/Core/RegularExpression.h"
27 #include "lldb/Core/Timer.h"
28 #include "lldb/Host/FileSystem.h"
29 #include "lldb/Interpreter/OptionValue.h"
30 #include "lldb/Interpreter/OptionValueArray.h"
31 #include "lldb/Interpreter/OptionValueDictionary.h"
32 #include "lldb/Interpreter/OptionValueRegex.h"
33 #include "lldb/Interpreter/OptionValueString.h"
34 #include "lldb/Interpreter/OptionValueUInt64.h"
35 #include "lldb/Symbol/Function.h"
36 #include "lldb/Symbol/ObjectFile.h"
37 #include "lldb/Target/ExecutionContext.h"
38 #include "lldb/Target/Process.h"
39 #include "lldb/Target/SectionLoadList.h"
40 #include "lldb/Target/StackFrame.h"
41 #include "lldb/Target/Target.h"
42 #include "lldb/lldb-private.h"
43 
44 #define DEFAULT_DISASM_BYTE_SIZE 32
45 
46 using namespace lldb;
47 using namespace lldb_private;
48 
49 DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
50                                         const char *flavor,
51                                         const char *plugin_name) {
52   Timer scoped_timer(LLVM_PRETTY_FUNCTION,
53                      "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
54                      arch.GetArchitectureName(), plugin_name);
55 
56   DisassemblerCreateInstance create_callback = nullptr;
57 
58   if (plugin_name) {
59     ConstString const_plugin_name(plugin_name);
60     create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName(
61         const_plugin_name);
62     if (create_callback) {
63       DisassemblerSP disassembler_sp(create_callback(arch, flavor));
64 
65       if (disassembler_sp)
66         return disassembler_sp;
67     }
68   } else {
69     for (uint32_t idx = 0;
70          (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
71               idx)) != nullptr;
72          ++idx) {
73       DisassemblerSP disassembler_sp(create_callback(arch, flavor));
74 
75       if (disassembler_sp)
76         return disassembler_sp;
77     }
78   }
79   return DisassemblerSP();
80 }
81 
82 DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp,
83                                                  const ArchSpec &arch,
84                                                  const char *flavor,
85                                                  const char *plugin_name) {
86   if (target_sp && flavor == nullptr) {
87     // FIXME - we don't have the mechanism in place to do per-architecture
88     // settings.  But since we know that for now
89     // we only support flavors on x86 & x86_64,
90     if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
91         arch.GetTriple().getArch() == llvm::Triple::x86_64)
92       flavor = target_sp->GetDisassemblyFlavor();
93   }
94   return FindPlugin(arch, flavor, plugin_name);
95 }
96 
97 static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr,
98                            Address &resolved_addr) {
99   if (!addr.IsSectionOffset()) {
100     // If we weren't passed in a section offset address range,
101     // try and resolve it to something
102     Target *target = exe_ctx.GetTargetPtr();
103     if (target) {
104       if (target->GetSectionLoadList().IsEmpty()) {
105         target->GetImages().ResolveFileAddress(addr.GetOffset(), resolved_addr);
106       } else {
107         target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(),
108                                                         resolved_addr);
109       }
110       // We weren't able to resolve the address, just treat it as a
111       // raw address
112       if (resolved_addr.IsValid())
113         return;
114     }
115   }
116   resolved_addr = addr;
117 }
118 
119 size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
120                                  const char *plugin_name, const char *flavor,
121                                  const ExecutionContext &exe_ctx,
122                                  SymbolContextList &sc_list,
123                                  uint32_t num_instructions,
124                                  bool mixed_source_and_assembly,
125                                  uint32_t num_mixed_context_lines,
126                                  uint32_t options, Stream &strm) {
127   size_t success_count = 0;
128   const size_t count = sc_list.GetSize();
129   SymbolContext sc;
130   AddressRange range;
131   const uint32_t scope =
132       eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
133   const bool use_inline_block_range = true;
134   for (size_t i = 0; i < count; ++i) {
135     if (!sc_list.GetContextAtIndex(i, sc))
136       break;
137     for (uint32_t range_idx = 0;
138          sc.GetAddressRange(scope, range_idx, use_inline_block_range, range);
139          ++range_idx) {
140       if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
141                       num_instructions, mixed_source_and_assembly,
142                       num_mixed_context_lines, options, strm)) {
143         ++success_count;
144         strm.EOL();
145       }
146     }
147   }
148   return success_count;
149 }
150 
151 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
152                                const char *plugin_name, const char *flavor,
153                                const ExecutionContext &exe_ctx,
154                                const ConstString &name, Module *module,
155                                uint32_t num_instructions,
156                                bool mixed_source_and_assembly,
157                                uint32_t num_mixed_context_lines,
158                                uint32_t options, Stream &strm) {
159   SymbolContextList sc_list;
160   if (name) {
161     const bool include_symbols = true;
162     const bool include_inlines = true;
163     if (module) {
164       module->FindFunctions(name, nullptr, eFunctionNameTypeAuto,
165                             include_symbols, include_inlines, true, sc_list);
166     } else if (exe_ctx.GetTargetPtr()) {
167       exe_ctx.GetTargetPtr()->GetImages().FindFunctions(
168           name, eFunctionNameTypeAuto, include_symbols, include_inlines, false,
169           sc_list);
170     }
171   }
172 
173   if (sc_list.GetSize()) {
174     return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list,
175                        num_instructions, mixed_source_and_assembly,
176                        num_mixed_context_lines, options, strm);
177   }
178   return false;
179 }
180 
181 lldb::DisassemblerSP Disassembler::DisassembleRange(
182     const ArchSpec &arch, const char *plugin_name, const char *flavor,
183     const ExecutionContext &exe_ctx, const AddressRange &range,
184     bool prefer_file_cache) {
185   lldb::DisassemblerSP disasm_sp;
186   if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) {
187     disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch,
188                                                   flavor, plugin_name);
189 
190     if (disasm_sp) {
191       size_t bytes_disassembled = disasm_sp->ParseInstructions(
192           &exe_ctx, range, nullptr, prefer_file_cache);
193       if (bytes_disassembled == 0)
194         disasm_sp.reset();
195     }
196   }
197   return disasm_sp;
198 }
199 
200 lldb::DisassemblerSP
201 Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
202                                const char *flavor, const Address &start,
203                                const void *src, size_t src_len,
204                                uint32_t num_instructions, bool data_from_file) {
205   lldb::DisassemblerSP disasm_sp;
206 
207   if (src) {
208     disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
209 
210     if (disasm_sp) {
211       DataExtractor data(src, src_len, arch.GetByteOrder(),
212                          arch.GetAddressByteSize());
213 
214       (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions,
215                                           false, data_from_file);
216     }
217   }
218 
219   return disasm_sp;
220 }
221 
222 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
223                                const char *plugin_name, const char *flavor,
224                                const ExecutionContext &exe_ctx,
225                                const AddressRange &disasm_range,
226                                uint32_t num_instructions,
227                                bool mixed_source_and_assembly,
228                                uint32_t num_mixed_context_lines,
229                                uint32_t options, Stream &strm) {
230   if (disasm_range.GetByteSize()) {
231     lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
232         exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
233 
234     if (disasm_sp) {
235       AddressRange range;
236       ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(),
237                      range.GetBaseAddress());
238       range.SetByteSize(disasm_range.GetByteSize());
239       const bool prefer_file_cache = false;
240       size_t bytes_disassembled = disasm_sp->ParseInstructions(
241           &exe_ctx, range, &strm, prefer_file_cache);
242       if (bytes_disassembled == 0)
243         return false;
244 
245       return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
246                                num_instructions, mixed_source_and_assembly,
247                                num_mixed_context_lines, options, strm);
248     }
249   }
250   return false;
251 }
252 
253 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
254                                const char *plugin_name, const char *flavor,
255                                const ExecutionContext &exe_ctx,
256                                const Address &start_address,
257                                uint32_t num_instructions,
258                                bool mixed_source_and_assembly,
259                                uint32_t num_mixed_context_lines,
260                                uint32_t options, Stream &strm) {
261   if (num_instructions > 0) {
262     lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
263         exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
264     if (disasm_sp) {
265       Address addr;
266       ResolveAddress(exe_ctx, start_address, addr);
267       const bool prefer_file_cache = false;
268       size_t bytes_disassembled = disasm_sp->ParseInstructions(
269           &exe_ctx, addr, num_instructions, prefer_file_cache);
270       if (bytes_disassembled == 0)
271         return false;
272       return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
273                                num_instructions, mixed_source_and_assembly,
274                                num_mixed_context_lines, options, strm);
275     }
276   }
277   return false;
278 }
279 
280 Disassembler::SourceLine
281 Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
282   SourceLine decl_line;
283   if (sc.function && sc.line_entry.IsValid()) {
284     LineEntry prologue_end_line = sc.line_entry;
285     FileSpec func_decl_file;
286     uint32_t func_decl_line;
287     sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
288     if (func_decl_file == prologue_end_line.file ||
289         func_decl_file == prologue_end_line.original_file) {
290       decl_line.file = func_decl_file;
291       decl_line.line = func_decl_line;
292     }
293   }
294   return decl_line;
295 }
296 
297 void Disassembler::AddLineToSourceLineTables(
298     SourceLine &line,
299     std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
300   if (line.IsValid()) {
301     auto source_lines_seen_pos = source_lines_seen.find(line.file);
302     if (source_lines_seen_pos == source_lines_seen.end()) {
303       std::set<uint32_t> lines;
304       lines.insert(line.line);
305       source_lines_seen.emplace(line.file, lines);
306     } else {
307       source_lines_seen_pos->second.insert(line.line);
308     }
309   }
310 }
311 
312 bool Disassembler::ElideMixedSourceAndDisassemblyLine(
313     const ExecutionContext &exe_ctx, const SymbolContext &sc,
314     SourceLine &line) {
315 
316   // TODO: should we also check target.process.thread.step-avoid-libraries ?
317 
318   const RegularExpression *avoid_regex = nullptr;
319 
320   // Skip any line #0 entries - they are implementation details
321   if (line.line == 0)
322     return false;
323 
324   ThreadSP thread_sp = exe_ctx.GetThreadSP();
325   if (thread_sp) {
326     avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
327   } else {
328     TargetSP target_sp = exe_ctx.GetTargetSP();
329     if (target_sp) {
330       Error error;
331       OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
332           &exe_ctx, "target.process.thread.step-avoid-regexp", false, error);
333       if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
334         OptionValueRegex *re = value_sp->GetAsRegex();
335         if (re) {
336           avoid_regex = re->GetCurrentValue();
337         }
338       }
339     }
340   }
341   if (avoid_regex && sc.symbol != nullptr) {
342     const char *function_name =
343         sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
344             .GetCString();
345     if (function_name) {
346       RegularExpression::Match regex_match(1);
347       if (avoid_regex->Execute(function_name, &regex_match)) {
348         // skip this source line
349         return true;
350       }
351     }
352   }
353   // don't skip this source line
354   return false;
355 }
356 
357 bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
358                                      Debugger &debugger, const ArchSpec &arch,
359                                      const ExecutionContext &exe_ctx,
360                                      uint32_t num_instructions,
361                                      bool mixed_source_and_assembly,
362                                      uint32_t num_mixed_context_lines,
363                                      uint32_t options, Stream &strm) {
364   // We got some things disassembled...
365   size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
366 
367   if (num_instructions > 0 && num_instructions < num_instructions_found)
368     num_instructions_found = num_instructions;
369 
370   const uint32_t max_opcode_byte_size =
371       disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize();
372   SymbolContext sc;
373   SymbolContext prev_sc;
374   AddressRange current_source_line_range;
375   const Address *pc_addr_ptr = nullptr;
376   StackFrame *frame = exe_ctx.GetFramePtr();
377 
378   TargetSP target_sp(exe_ctx.GetTargetSP());
379   SourceManager &source_manager =
380       target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
381 
382   if (frame) {
383     pc_addr_ptr = &frame->GetFrameCodeAddress();
384   }
385   const uint32_t scope =
386       eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
387   const bool use_inline_block_range = false;
388 
389   const FormatEntity::Entry *disassembly_format = nullptr;
390   FormatEntity::Entry format;
391   if (exe_ctx.HasTargetScope()) {
392     disassembly_format =
393         exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
394   } else {
395     FormatEntity::Parse("${addr}: ", format);
396     disassembly_format = &format;
397   }
398 
399   // First pass: step through the list of instructions,
400   // find how long the initial addresses strings are, insert padding
401   // in the second pass so the opcodes all line up nicely.
402 
403   // Also build up the source line mapping if this is mixed source & assembly
404   // mode.
405   // Calculate the source line for each assembly instruction (eliding inlined
406   // functions
407   // which the user wants to skip).
408 
409   std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
410   Symbol *previous_symbol = nullptr;
411 
412   size_t address_text_size = 0;
413   for (size_t i = 0; i < num_instructions_found; ++i) {
414     Instruction *inst =
415         disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
416     if (inst) {
417       const Address &addr = inst->GetAddress();
418       ModuleSP module_sp(addr.GetModule());
419       if (module_sp) {
420         const uint32_t resolve_mask = eSymbolContextFunction |
421                                       eSymbolContextSymbol |
422                                       eSymbolContextLineEntry;
423         uint32_t resolved_mask =
424             module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
425         if (resolved_mask) {
426           StreamString strmstr;
427           Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
428                                               &exe_ctx, &addr, strmstr);
429           size_t cur_line = strmstr.GetSizeOfLastLine();
430           if (cur_line > address_text_size)
431             address_text_size = cur_line;
432 
433           // Add entries to our "source_lines_seen" map+set which list which
434           // sources lines occur in this disassembly session.  We will print
435           // lines of context around a source line, but we don't want to print
436           // a source line that has a line table entry of its own - we'll leave
437           // that source line to be printed when it actually occurs in the
438           // disassembly.
439 
440           if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
441             if (sc.symbol != previous_symbol) {
442               SourceLine decl_line = GetFunctionDeclLineEntry(sc);
443               if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) ==
444                   false)
445                 AddLineToSourceLineTables(decl_line, source_lines_seen);
446             }
447             if (sc.line_entry.IsValid()) {
448               SourceLine this_line;
449               this_line.file = sc.line_entry.file;
450               this_line.line = sc.line_entry.line;
451               if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) ==
452                   false)
453                 AddLineToSourceLineTables(this_line, source_lines_seen);
454             }
455           }
456         }
457         sc.Clear(false);
458       }
459     }
460   }
461 
462   previous_symbol = nullptr;
463   SourceLine previous_line;
464   for (size_t i = 0; i < num_instructions_found; ++i) {
465     Instruction *inst =
466         disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
467 
468     if (inst) {
469       const Address &addr = inst->GetAddress();
470       const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
471       SourceLinesToDisplay source_lines_to_display;
472 
473       prev_sc = sc;
474 
475       ModuleSP module_sp(addr.GetModule());
476       if (module_sp) {
477         uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
478             addr, eSymbolContextEverything, sc);
479         if (resolved_mask) {
480           if (mixed_source_and_assembly) {
481 
482             // If we've started a new function (non-inlined), print all of the
483             // source lines from the
484             // function declaration until the first line table entry - typically
485             // the opening curly brace of
486             // the function.
487             if (previous_symbol != sc.symbol) {
488               // The default disassembly format puts an extra blank line between
489               // functions - so
490               // when we're displaying the source context for a function, we
491               // don't want to add
492               // a blank line after the source context or we'll end up with two
493               // of them.
494               if (previous_symbol != nullptr)
495                 source_lines_to_display.print_source_context_end_eol = false;
496 
497               previous_symbol = sc.symbol;
498               if (sc.function && sc.line_entry.IsValid()) {
499                 LineEntry prologue_end_line = sc.line_entry;
500                 if (ElideMixedSourceAndDisassemblyLine(
501                         exe_ctx, sc, prologue_end_line) == false) {
502                   FileSpec func_decl_file;
503                   uint32_t func_decl_line;
504                   sc.function->GetStartLineSourceInfo(func_decl_file,
505                                                       func_decl_line);
506                   if (func_decl_file == prologue_end_line.file ||
507                       func_decl_file == prologue_end_line.original_file) {
508                     // Add all the lines between the function declaration
509                     // and the first non-prologue source line to the list
510                     // of lines to print.
511                     for (uint32_t lineno = func_decl_line;
512                          lineno <= prologue_end_line.line; lineno++) {
513                       SourceLine this_line;
514                       this_line.file = func_decl_file;
515                       this_line.line = lineno;
516                       source_lines_to_display.lines.push_back(this_line);
517                     }
518                     // Mark the last line as the "current" one.  Usually
519                     // this is the open curly brace.
520                     if (source_lines_to_display.lines.size() > 0)
521                       source_lines_to_display.current_source_line =
522                           source_lines_to_display.lines.size() - 1;
523                   }
524                 }
525               }
526               sc.GetAddressRange(scope, 0, use_inline_block_range,
527                                  current_source_line_range);
528             }
529 
530             // If we've left a previous source line's address range, print a new
531             // source line
532             if (!current_source_line_range.ContainsFileAddress(addr)) {
533               sc.GetAddressRange(scope, 0, use_inline_block_range,
534                                  current_source_line_range);
535 
536               if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
537                 SourceLine this_line;
538                 this_line.file = sc.line_entry.file;
539                 this_line.line = sc.line_entry.line;
540 
541                 if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
542                                                        this_line) == false) {
543                   // Only print this source line if it is different from the
544                   // last source line we printed.  There may have been inlined
545                   // functions between these lines that we elided, resulting in
546                   // the same line being printed twice in a row for a contiguous
547                   // block of assembly instructions.
548                   if (this_line != previous_line) {
549 
550                     std::vector<uint32_t> previous_lines;
551                     for (uint32_t i = 0;
552                          i < num_mixed_context_lines &&
553                          (this_line.line - num_mixed_context_lines) > 0;
554                          i++) {
555                       uint32_t line =
556                           this_line.line - num_mixed_context_lines + i;
557                       auto pos = source_lines_seen.find(this_line.file);
558                       if (pos != source_lines_seen.end()) {
559                         if (pos->second.count(line) == 1) {
560                           previous_lines.clear();
561                         } else {
562                           previous_lines.push_back(line);
563                         }
564                       }
565                     }
566                     for (size_t i = 0; i < previous_lines.size(); i++) {
567                       SourceLine previous_line;
568                       previous_line.file = this_line.file;
569                       previous_line.line = previous_lines[i];
570                       auto pos = source_lines_seen.find(previous_line.file);
571                       if (pos != source_lines_seen.end()) {
572                         pos->second.insert(previous_line.line);
573                       }
574                       source_lines_to_display.lines.push_back(previous_line);
575                     }
576 
577                     source_lines_to_display.lines.push_back(this_line);
578                     source_lines_to_display.current_source_line =
579                         source_lines_to_display.lines.size() - 1;
580 
581                     for (uint32_t i = 0; i < num_mixed_context_lines; i++) {
582                       SourceLine next_line;
583                       next_line.file = this_line.file;
584                       next_line.line = this_line.line + i + 1;
585                       auto pos = source_lines_seen.find(next_line.file);
586                       if (pos != source_lines_seen.end()) {
587                         if (pos->second.count(next_line.line) == 1)
588                           break;
589                         pos->second.insert(next_line.line);
590                       }
591                       source_lines_to_display.lines.push_back(next_line);
592                     }
593                   }
594                   previous_line = this_line;
595                 }
596               }
597             }
598           }
599         } else {
600           sc.Clear(true);
601         }
602       }
603 
604       if (source_lines_to_display.lines.size() > 0) {
605         strm.EOL();
606         for (size_t idx = 0; idx < source_lines_to_display.lines.size();
607              idx++) {
608           SourceLine ln = source_lines_to_display.lines[idx];
609           const char *line_highlight = "";
610           if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
611             line_highlight = "->";
612           } else if (idx == source_lines_to_display.current_source_line) {
613             line_highlight = "**";
614           }
615           source_manager.DisplaySourceLinesWithLineNumbers(
616               ln.file, ln.line, 0, 0, line_highlight, &strm);
617         }
618         if (source_lines_to_display.print_source_context_end_eol)
619           strm.EOL();
620       }
621 
622       const bool show_bytes = (options & eOptionShowBytes) != 0;
623       inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc,
624                  &prev_sc, nullptr, address_text_size);
625       strm.EOL();
626     } else {
627       break;
628     }
629   }
630 
631   return true;
632 }
633 
634 bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
635                                const char *plugin_name, const char *flavor,
636                                const ExecutionContext &exe_ctx,
637                                uint32_t num_instructions,
638                                bool mixed_source_and_assembly,
639                                uint32_t num_mixed_context_lines,
640                                uint32_t options, Stream &strm) {
641   AddressRange range;
642   StackFrame *frame = exe_ctx.GetFramePtr();
643   if (frame) {
644     SymbolContext sc(
645         frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
646     if (sc.function) {
647       range = sc.function->GetAddressRange();
648     } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
649       range.GetBaseAddress() = sc.symbol->GetAddressRef();
650       range.SetByteSize(sc.symbol->GetByteSize());
651     } else {
652       range.GetBaseAddress() = frame->GetFrameCodeAddress();
653     }
654 
655     if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
656       range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
657   }
658 
659   return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
660                      num_instructions, mixed_source_and_assembly,
661                      num_mixed_context_lines, options, strm);
662 }
663 
664 Instruction::Instruction(const Address &address, AddressClass addr_class)
665     : m_address(address), m_address_class(addr_class), m_opcode(),
666       m_calculated_strings(false) {}
667 
668 Instruction::~Instruction() = default;
669 
670 AddressClass Instruction::GetAddressClass() {
671   if (m_address_class == eAddressClassInvalid)
672     m_address_class = m_address.GetAddressClass();
673   return m_address_class;
674 }
675 
676 void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
677                        bool show_address, bool show_bytes,
678                        const ExecutionContext *exe_ctx,
679                        const SymbolContext *sym_ctx,
680                        const SymbolContext *prev_sym_ctx,
681                        const FormatEntity::Entry *disassembly_addr_format,
682                        size_t max_address_text_size) {
683   size_t opcode_column_width = 7;
684   const size_t operand_column_width = 25;
685 
686   CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
687 
688   StreamString ss;
689 
690   if (show_address) {
691     Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
692                                         prev_sym_ctx, exe_ctx, &m_address, ss);
693     ss.FillLastLineToColumn(max_address_text_size, ' ');
694   }
695 
696   if (show_bytes) {
697     if (m_opcode.GetType() == Opcode::eTypeBytes) {
698       // x86_64 and i386 are the only ones that use bytes right now so
699       // pad out the byte dump to be able to always show 15 bytes (3 chars each)
700       // plus a space
701       if (max_opcode_byte_size > 0)
702         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
703       else
704         m_opcode.Dump(&ss, 15 * 3 + 1);
705     } else {
706       // Else, we have ARM or MIPS which can show up to a uint32_t
707       // 0x00000000 (10 spaces) plus two for padding...
708       if (max_opcode_byte_size > 0)
709         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
710       else
711         m_opcode.Dump(&ss, 12);
712     }
713   }
714 
715   const size_t opcode_pos = ss.GetSizeOfLastLine();
716 
717   // The default opcode size of 7 characters is plenty for most architectures
718   // but some like arm can pull out the occasional vqrshrun.s16.  We won't get
719   // consistent column spacing in these cases, unfortunately.
720   if (m_opcode_name.length() >= opcode_column_width) {
721     opcode_column_width = m_opcode_name.length() + 1;
722   }
723 
724   ss.PutCString(m_opcode_name.c_str());
725   ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
726   ss.PutCString(m_mnemonics.c_str());
727 
728   if (!m_comment.empty()) {
729     ss.FillLastLineToColumn(
730         opcode_pos + opcode_column_width + operand_column_width, ' ');
731     ss.PutCString(" ; ");
732     ss.PutCString(m_comment.c_str());
733   }
734   s->Write(ss.GetData(), ss.GetSize());
735 }
736 
737 bool Instruction::DumpEmulation(const ArchSpec &arch) {
738   std::unique_ptr<EmulateInstruction> insn_emulator_ap(
739       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
740   if (insn_emulator_ap) {
741     insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
742     return insn_emulator_ap->EvaluateInstruction(0);
743   }
744 
745   return false;
746 }
747 
748 bool Instruction::HasDelaySlot() {
749   // Default is false.
750   return false;
751 }
752 
753 OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream,
754                                      OptionValue::Type data_type) {
755   bool done = false;
756   char buffer[1024];
757 
758   OptionValueSP option_value_sp(new OptionValueArray(1u << data_type));
759 
760   int idx = 0;
761   while (!done) {
762     if (!fgets(buffer, 1023, in_file)) {
763       out_stream->Printf(
764           "Instruction::ReadArray:  Error reading file (fgets).\n");
765       option_value_sp.reset();
766       return option_value_sp;
767     }
768 
769     std::string line(buffer);
770 
771     size_t len = line.size();
772     if (line[len - 1] == '\n') {
773       line[len - 1] = '\0';
774       line.resize(len - 1);
775     }
776 
777     if ((line.size() == 1) && line[0] == ']') {
778       done = true;
779       line.clear();
780     }
781 
782     if (!line.empty()) {
783       std::string value;
784       static RegularExpression g_reg_exp("^[ \t]*([^ \t]+)[ \t]*$");
785       RegularExpression::Match regex_match(1);
786       bool reg_exp_success = g_reg_exp.Execute(line.c_str(), &regex_match);
787       if (reg_exp_success)
788         regex_match.GetMatchAtIndex(line.c_str(), 1, value);
789       else
790         value = line;
791 
792       OptionValueSP data_value_sp;
793       switch (data_type) {
794       case OptionValue::eTypeUInt64:
795         data_value_sp.reset(new OptionValueUInt64(0, 0));
796         data_value_sp->SetValueFromString(value);
797         break;
798       // Other types can be added later as needed.
799       default:
800         data_value_sp.reset(new OptionValueString(value.c_str(), ""));
801         break;
802       }
803 
804       option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
805       ++idx;
806     }
807   }
808 
809   return option_value_sp;
810 }
811 
812 OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) {
813   bool done = false;
814   char buffer[1024];
815 
816   OptionValueSP option_value_sp(new OptionValueDictionary());
817   static ConstString encoding_key("data_encoding");
818   OptionValue::Type data_type = OptionValue::eTypeInvalid;
819 
820   while (!done) {
821     // Read the next line in the file
822     if (!fgets(buffer, 1023, in_file)) {
823       out_stream->Printf(
824           "Instruction::ReadDictionary: Error reading file (fgets).\n");
825       option_value_sp.reset();
826       return option_value_sp;
827     }
828 
829     // Check to see if the line contains the end-of-dictionary marker ("}")
830     std::string line(buffer);
831 
832     size_t len = line.size();
833     if (line[len - 1] == '\n') {
834       line[len - 1] = '\0';
835       line.resize(len - 1);
836     }
837 
838     if ((line.size() == 1) && (line[0] == '}')) {
839       done = true;
840       line.clear();
841     }
842 
843     // Try to find a key-value pair in the current line and add it to the
844     // dictionary.
845     if (!line.empty()) {
846       static RegularExpression g_reg_exp(
847           "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
848       RegularExpression::Match regex_match(2);
849 
850       bool reg_exp_success = g_reg_exp.Execute(line.c_str(), &regex_match);
851       std::string key;
852       std::string value;
853       if (reg_exp_success) {
854         regex_match.GetMatchAtIndex(line.c_str(), 1, key);
855         regex_match.GetMatchAtIndex(line.c_str(), 2, value);
856       } else {
857         out_stream->Printf("Instruction::ReadDictionary: Failure executing "
858                            "regular expression.\n");
859         option_value_sp.reset();
860         return option_value_sp;
861       }
862 
863       ConstString const_key(key.c_str());
864       // Check value to see if it's the start of an array or dictionary.
865 
866       lldb::OptionValueSP value_sp;
867       assert(value.empty() == false);
868       assert(key.empty() == false);
869 
870       if (value[0] == '{') {
871         assert(value.size() == 1);
872         // value is a dictionary
873         value_sp = ReadDictionary(in_file, out_stream);
874         if (!value_sp) {
875           option_value_sp.reset();
876           return option_value_sp;
877         }
878       } else if (value[0] == '[') {
879         assert(value.size() == 1);
880         // value is an array
881         value_sp = ReadArray(in_file, out_stream, data_type);
882         if (!value_sp) {
883           option_value_sp.reset();
884           return option_value_sp;
885         }
886         // We've used the data_type to read an array; re-set the type to Invalid
887         data_type = OptionValue::eTypeInvalid;
888       } else if ((value[0] == '0') && (value[1] == 'x')) {
889         value_sp.reset(new OptionValueUInt64(0, 0));
890         value_sp->SetValueFromString(value);
891       } else {
892         size_t len = value.size();
893         if ((value[0] == '"') && (value[len - 1] == '"'))
894           value = value.substr(1, len - 2);
895         value_sp.reset(new OptionValueString(value.c_str(), ""));
896       }
897 
898       if (const_key == encoding_key) {
899         // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data
900         // indicating the
901         // data type of an upcoming array (usually the next bit of data to be
902         // read in).
903         if (strcmp(value.c_str(), "uint32_t") == 0)
904           data_type = OptionValue::eTypeUInt64;
905       } else
906         option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp,
907                                                            false);
908     }
909   }
910 
911   return option_value_sp;
912 }
913 
914 bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) {
915   if (!out_stream)
916     return false;
917 
918   if (!file_name) {
919     out_stream->Printf("Instruction::TestEmulation:  Missing file_name.");
920     return false;
921   }
922   FILE *test_file = FileSystem::Fopen(file_name, "r");
923   if (!test_file) {
924     out_stream->Printf(
925         "Instruction::TestEmulation: Attempt to open test file failed.");
926     return false;
927   }
928 
929   char buffer[256];
930   if (!fgets(buffer, 255, test_file)) {
931     out_stream->Printf(
932         "Instruction::TestEmulation: Error reading first line of test file.\n");
933     fclose(test_file);
934     return false;
935   }
936 
937   if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
938     out_stream->Printf("Instructin::TestEmulation: Test file does not contain "
939                        "emulation state dictionary\n");
940     fclose(test_file);
941     return false;
942   }
943 
944   // Read all the test information from the test file into an
945   // OptionValueDictionary.
946 
947   OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
948   if (!data_dictionary_sp) {
949     out_stream->Printf(
950         "Instruction::TestEmulation:  Error reading Dictionary Object.\n");
951     fclose(test_file);
952     return false;
953   }
954 
955   fclose(test_file);
956 
957   OptionValueDictionary *data_dictionary =
958       data_dictionary_sp->GetAsDictionary();
959   static ConstString description_key("assembly_string");
960   static ConstString triple_key("triple");
961 
962   OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
963 
964   if (!value_sp) {
965     out_stream->Printf("Instruction::TestEmulation:  Test file does not "
966                        "contain description string.\n");
967     return false;
968   }
969 
970   SetDescription(value_sp->GetStringValue());
971 
972   value_sp = data_dictionary->GetValueForKey(triple_key);
973   if (!value_sp) {
974     out_stream->Printf(
975         "Instruction::TestEmulation: Test file does not contain triple.\n");
976     return false;
977   }
978 
979   ArchSpec arch;
980   arch.SetTriple(llvm::Triple(value_sp->GetStringValue()));
981 
982   bool success = false;
983   std::unique_ptr<EmulateInstruction> insn_emulator_ap(
984       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
985   if (insn_emulator_ap)
986     success =
987         insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary);
988 
989   if (success)
990     out_stream->Printf("Emulation test succeeded.");
991   else
992     out_stream->Printf("Emulation test failed.");
993 
994   return success;
995 }
996 
997 bool Instruction::Emulate(
998     const ArchSpec &arch, uint32_t evaluate_options, void *baton,
999     EmulateInstruction::ReadMemoryCallback read_mem_callback,
1000     EmulateInstruction::WriteMemoryCallback write_mem_callback,
1001     EmulateInstruction::ReadRegisterCallback read_reg_callback,
1002     EmulateInstruction::WriteRegisterCallback write_reg_callback) {
1003   std::unique_ptr<EmulateInstruction> insn_emulator_ap(
1004       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
1005   if (insn_emulator_ap) {
1006     insn_emulator_ap->SetBaton(baton);
1007     insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback,
1008                                    read_reg_callback, write_reg_callback);
1009     insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
1010     return insn_emulator_ap->EvaluateInstruction(evaluate_options);
1011   }
1012 
1013   return false;
1014 }
1015 
1016 uint32_t Instruction::GetData(DataExtractor &data) {
1017   return m_opcode.GetData(data);
1018 }
1019 
1020 InstructionList::InstructionList() : m_instructions() {}
1021 
1022 InstructionList::~InstructionList() = default;
1023 
1024 size_t InstructionList::GetSize() const { return m_instructions.size(); }
1025 
1026 uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
1027   uint32_t max_inst_size = 0;
1028   collection::const_iterator pos, end;
1029   for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
1030        ++pos) {
1031     uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
1032     if (max_inst_size < inst_size)
1033       max_inst_size = inst_size;
1034   }
1035   return max_inst_size;
1036 }
1037 
1038 InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
1039   InstructionSP inst_sp;
1040   if (idx < m_instructions.size())
1041     inst_sp = m_instructions[idx];
1042   return inst_sp;
1043 }
1044 
1045 void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
1046                            const ExecutionContext *exe_ctx) {
1047   const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
1048   collection::const_iterator pos, begin, end;
1049 
1050   const FormatEntity::Entry *disassembly_format = nullptr;
1051   FormatEntity::Entry format;
1052   if (exe_ctx && exe_ctx->HasTargetScope()) {
1053     disassembly_format =
1054         exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1055   } else {
1056     FormatEntity::Parse("${addr}: ", format);
1057     disassembly_format = &format;
1058   }
1059 
1060   for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
1061        pos != end; ++pos) {
1062     if (pos != begin)
1063       s->EOL();
1064     (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx,
1065                  nullptr, nullptr, disassembly_format, 0);
1066   }
1067 }
1068 
1069 void InstructionList::Clear() { m_instructions.clear(); }
1070 
1071 void InstructionList::Append(lldb::InstructionSP &inst_sp) {
1072   if (inst_sp)
1073     m_instructions.push_back(inst_sp);
1074 }
1075 
1076 uint32_t
1077 InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
1078                                                  Target &target) const {
1079   size_t num_instructions = m_instructions.size();
1080 
1081   uint32_t next_branch = UINT32_MAX;
1082   size_t i;
1083   for (i = start; i < num_instructions; i++) {
1084     if (m_instructions[i]->DoesBranch()) {
1085       next_branch = i;
1086       break;
1087     }
1088   }
1089 
1090   // Hexagon needs the first instruction of the packet with the branch.
1091   // Go backwards until we find an instruction marked end-of-packet, or
1092   // until we hit start.
1093   if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) {
1094     // If we didn't find a branch, find the last packet start.
1095     if (next_branch == UINT32_MAX) {
1096       i = num_instructions - 1;
1097     }
1098 
1099     while (i > start) {
1100       --i;
1101 
1102       Error error;
1103       uint32_t inst_bytes;
1104       bool prefer_file_cache = false; // Read from process if process is running
1105       lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1106       target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache,
1107                         &inst_bytes, sizeof(inst_bytes), error, &load_addr);
1108       // If we have an error reading memory, return start
1109       if (!error.Success())
1110         return start;
1111       // check if this is the last instruction in a packet
1112       // bits 15:14 will be 11b or 00b for a duplex
1113       if (((inst_bytes & 0xC000) == 0xC000) ||
1114           ((inst_bytes & 0xC000) == 0x0000)) {
1115         // instruction after this should be the start of next packet
1116         next_branch = i + 1;
1117         break;
1118       }
1119     }
1120 
1121     if (next_branch == UINT32_MAX) {
1122       // We couldn't find the previous packet, so return start
1123       next_branch = start;
1124     }
1125   }
1126   return next_branch;
1127 }
1128 
1129 uint32_t
1130 InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
1131   size_t num_instructions = m_instructions.size();
1132   uint32_t index = UINT32_MAX;
1133   for (size_t i = 0; i < num_instructions; i++) {
1134     if (m_instructions[i]->GetAddress() == address) {
1135       index = i;
1136       break;
1137     }
1138   }
1139   return index;
1140 }
1141 
1142 uint32_t
1143 InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
1144                                                     Target &target) {
1145   Address address;
1146   address.SetLoadAddress(load_addr, &target);
1147   return GetIndexOfInstructionAtAddress(address);
1148 }
1149 
1150 size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
1151                                        const AddressRange &range,
1152                                        Stream *error_strm_ptr,
1153                                        bool prefer_file_cache) {
1154   if (exe_ctx) {
1155     Target *target = exe_ctx->GetTargetPtr();
1156     const addr_t byte_size = range.GetByteSize();
1157     if (target == nullptr || byte_size == 0 ||
1158         !range.GetBaseAddress().IsValid())
1159       return 0;
1160 
1161     DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0');
1162     DataBufferSP data_sp(heap_buffer);
1163 
1164     Error error;
1165     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1166     const size_t bytes_read = target->ReadMemory(
1167         range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(),
1168         heap_buffer->GetByteSize(), error, &load_addr);
1169 
1170     if (bytes_read > 0) {
1171       if (bytes_read != heap_buffer->GetByteSize())
1172         heap_buffer->SetByteSize(bytes_read);
1173       DataExtractor data(data_sp, m_arch.GetByteOrder(),
1174                          m_arch.GetAddressByteSize());
1175       const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1176       return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX,
1177                                 false, data_from_file);
1178     } else if (error_strm_ptr) {
1179       const char *error_cstr = error.AsCString();
1180       if (error_cstr) {
1181         error_strm_ptr->Printf("error: %s\n", error_cstr);
1182       }
1183     }
1184   } else if (error_strm_ptr) {
1185     error_strm_ptr->PutCString("error: invalid execution context\n");
1186   }
1187   return 0;
1188 }
1189 
1190 size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
1191                                        const Address &start,
1192                                        uint32_t num_instructions,
1193                                        bool prefer_file_cache) {
1194   m_instruction_list.Clear();
1195 
1196   if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid())
1197     return 0;
1198 
1199   Target *target = exe_ctx->GetTargetPtr();
1200   // Calculate the max buffer size we will need in order to disassemble
1201   const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
1202 
1203   if (target == nullptr || byte_size == 0)
1204     return 0;
1205 
1206   DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0');
1207   DataBufferSP data_sp(heap_buffer);
1208 
1209   Error error;
1210   lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1211   const size_t bytes_read =
1212       target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(),
1213                          byte_size, error, &load_addr);
1214 
1215   const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1216 
1217   if (bytes_read == 0)
1218     return 0;
1219   DataExtractor data(data_sp, m_arch.GetByteOrder(),
1220                      m_arch.GetAddressByteSize());
1221 
1222   const bool append_instructions = true;
1223   DecodeInstructions(start, data, 0, num_instructions, append_instructions,
1224                      data_from_file);
1225 
1226   return m_instruction_list.GetSize();
1227 }
1228 
1229 //----------------------------------------------------------------------
1230 // Disassembler copy constructor
1231 //----------------------------------------------------------------------
1232 Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
1233     : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
1234       m_flavor() {
1235   if (flavor == nullptr)
1236     m_flavor.assign("default");
1237   else
1238     m_flavor.assign(flavor);
1239 
1240   // If this is an arm variant that can only include thumb (T16, T32)
1241   // instructions, force the arch triple to be "thumbv.." instead of
1242   // "armv..."
1243   if (arch.IsAlwaysThumbInstructions()) {
1244     std::string thumb_arch_name(arch.GetTriple().getArchName().str());
1245     // Replace "arm" with "thumb" so we get all thumb variants correct
1246     if (thumb_arch_name.size() > 3) {
1247       thumb_arch_name.erase(0, 3);
1248       thumb_arch_name.insert(0, "thumb");
1249     }
1250     m_arch.SetTriple(thumb_arch_name.c_str());
1251   }
1252 }
1253 
1254 Disassembler::~Disassembler() = default;
1255 
1256 InstructionList &Disassembler::GetInstructionList() {
1257   return m_instruction_list;
1258 }
1259 
1260 const InstructionList &Disassembler::GetInstructionList() const {
1261   return m_instruction_list;
1262 }
1263 
1264 //----------------------------------------------------------------------
1265 // Class PseudoInstruction
1266 //----------------------------------------------------------------------
1267 
1268 PseudoInstruction::PseudoInstruction()
1269     : Instruction(Address(), eAddressClassUnknown), m_description() {}
1270 
1271 PseudoInstruction::~PseudoInstruction() = default;
1272 
1273 bool PseudoInstruction::DoesBranch() {
1274   // This is NOT a valid question for a pseudo instruction.
1275   return false;
1276 }
1277 
1278 bool PseudoInstruction::HasDelaySlot() {
1279   // This is NOT a valid question for a pseudo instruction.
1280   return false;
1281 }
1282 
1283 size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
1284                                  const lldb_private::DataExtractor &data,
1285                                  lldb::offset_t data_offset) {
1286   return m_opcode.GetByteSize();
1287 }
1288 
1289 void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
1290   if (!opcode_data)
1291     return;
1292 
1293   switch (opcode_size) {
1294   case 8: {
1295     uint8_t value8 = *((uint8_t *)opcode_data);
1296     m_opcode.SetOpcode8(value8, eByteOrderInvalid);
1297     break;
1298   }
1299   case 16: {
1300     uint16_t value16 = *((uint16_t *)opcode_data);
1301     m_opcode.SetOpcode16(value16, eByteOrderInvalid);
1302     break;
1303   }
1304   case 32: {
1305     uint32_t value32 = *((uint32_t *)opcode_data);
1306     m_opcode.SetOpcode32(value32, eByteOrderInvalid);
1307     break;
1308   }
1309   case 64: {
1310     uint64_t value64 = *((uint64_t *)opcode_data);
1311     m_opcode.SetOpcode64(value64, eByteOrderInvalid);
1312     break;
1313   }
1314   default:
1315     break;
1316   }
1317 }
1318 
1319 void PseudoInstruction::SetDescription(const char *description) {
1320   if (description && strlen(description) > 0)
1321     m_description = description;
1322 }
1323