Coverage Report

Created: 2023-11-11 10:31

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