Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/tools/lldb-test/lldb-test.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
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 "FormatUtil.h"
10
#include "SystemInitializerTest.h"
11
12
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
13
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14
#include "lldb/Breakpoint/BreakpointLocation.h"
15
#include "lldb/Core/Debugger.h"
16
#include "lldb/Core/Module.h"
17
#include "lldb/Core/Section.h"
18
#include "lldb/Expression/IRMemoryMap.h"
19
#include "lldb/Initialization/SystemLifetimeManager.h"
20
#include "lldb/Interpreter/CommandInterpreter.h"
21
#include "lldb/Interpreter/CommandReturnObject.h"
22
#include "lldb/Symbol/CompileUnit.h"
23
#include "lldb/Symbol/LineTable.h"
24
#include "lldb/Symbol/SymbolFile.h"
25
#include "lldb/Symbol/TypeList.h"
26
#include "lldb/Symbol/TypeMap.h"
27
#include "lldb/Symbol/VariableList.h"
28
#include "lldb/Target/Language.h"
29
#include "lldb/Target/Process.h"
30
#include "lldb/Target/Target.h"
31
#include "lldb/Utility/DataExtractor.h"
32
#include "lldb/Utility/LLDBAssert.h"
33
#include "lldb/Utility/State.h"
34
#include "lldb/Utility/StreamString.h"
35
36
#include "llvm/ADT/IntervalMap.h"
37
#include "llvm/ADT/ScopeExit.h"
38
#include "llvm/ADT/StringRef.h"
39
#include "llvm/Support/CommandLine.h"
40
#include "llvm/Support/ManagedStatic.h"
41
#include "llvm/Support/MathExtras.h"
42
#include "llvm/Support/Path.h"
43
#include "llvm/Support/PrettyStackTrace.h"
44
#include "llvm/Support/Signals.h"
45
#include "llvm/Support/WithColor.h"
46
47
#include <cstdio>
48
#include <thread>
49
50
using namespace lldb;
51
using namespace lldb_private;
52
using namespace llvm;
53
54
namespace opts {
55
static cl::SubCommand BreakpointSubcommand("breakpoints",
56
                                           "Test breakpoint resolution");
57
cl::SubCommand ObjectFileSubcommand("object-file",
58
                                    "Display LLDB object file information");
59
cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
60
cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
61
cl::SubCommand AssertSubcommand("assert", "Test assert handling");
62
63
cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
64
                         cl::sub(BreakpointSubcommand),
65
                         cl::sub(ObjectFileSubcommand),
66
                         cl::sub(SymbolsSubcommand),
67
                         cl::sub(IRMemoryMapSubcommand));
68
69
/// Create a target using the file pointed to by \p Filename, or abort.
70
TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
71
72
/// Read \p Filename into a null-terminated buffer, or abort.
73
std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
74
75
namespace breakpoint {
76
static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
77
                                   cl::Required, cl::sub(BreakpointSubcommand));
78
static cl::opt<std::string> CommandFile(cl::Positional,
79
                                        cl::desc("<command-file>"),
80
                                        cl::init("-"),
81
                                        cl::sub(BreakpointSubcommand));
82
static cl::opt<bool> Persistent(
83
    "persistent",
84
    cl::desc("Don't automatically remove all breakpoints before each command"),
85
    cl::sub(BreakpointSubcommand));
86
87
69
static llvm::StringRef plural(uintmax_t value) { return value == 1 ? 
""40
:
"s"29
; }
88
static void dumpState(const BreakpointList &List, LinePrinter &P);
89
static std::string substitute(StringRef Cmd);
90
static int evaluateBreakpoints(Debugger &Dbg);
91
} // namespace breakpoint
92
93
namespace object {
94
cl::opt<bool> SectionContents("contents",
95
                              cl::desc("Dump each section's contents"),
96
                              cl::sub(ObjectFileSubcommand));
97
cl::opt<bool> SectionDependentModules("dep-modules",
98
                                      cl::desc("Dump each dependent module"),
99
                                      cl::sub(ObjectFileSubcommand));
100
cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
101
                                     cl::OneOrMore,
102
                                     cl::sub(ObjectFileSubcommand));
103
} // namespace object
104
105
namespace symbols {
106
static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
107
                                      cl::Required, cl::sub(SymbolsSubcommand));
108
109
static cl::opt<std::string>
110
    SymbolPath("symbol-file",
111
               cl::desc("The file from which to fetch symbol information."),
112
               cl::value_desc("file"), cl::sub(SymbolsSubcommand));
113
114
enum class FindType {
115
  None,
116
  Function,
117
  Block,
118
  Namespace,
119
  Type,
120
  Variable,
121
};
122
static cl::opt<FindType> Find(
123
    "find", cl::desc("Choose search type:"),
124
    cl::values(
125
        clEnumValN(FindType::None, "none", "No search, just dump the module."),
126
        clEnumValN(FindType::Function, "function", "Find functions."),
127
        clEnumValN(FindType::Block, "block", "Find blocks."),
128
        clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
129
        clEnumValN(FindType::Type, "type", "Find types."),
130
        clEnumValN(FindType::Variable, "variable", "Find global variables.")),
131
    cl::sub(SymbolsSubcommand));
132
133
static cl::opt<std::string> Name("name", cl::desc("Name to find."),
134
                                 cl::sub(SymbolsSubcommand));
135
static cl::opt<bool>
136
    Regex("regex",
137
          cl::desc("Search using regular expressions (available for variables "
138
                   "and functions only)."),
139
          cl::sub(SymbolsSubcommand));
140
static cl::opt<std::string>
141
    Context("context",
142
            cl::desc("Restrict search to the context of the given variable."),
143
            cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
144
145
static cl::opt<std::string> CompilerContext(
146
    "compiler-context",
147
    cl::desc("Specify a compiler context as \"kind:name,...\"."),
148
    cl::value_desc("context"), cl::sub(SymbolsSubcommand));
149
150
static cl::opt<std::string>
151
    Language("language", cl::desc("Specify a language type, like C99."),
152
             cl::value_desc("language"), cl::sub(SymbolsSubcommand));
153
154
static cl::list<FunctionNameType> FunctionNameFlags(
155
    "function-flags", cl::desc("Function search flags:"),
156
    cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
157
                          "Automatically deduce flags based on name."),
158
               clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
159
               clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
160
               clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
161
               clEnumValN(eFunctionNameTypeSelector, "selector",
162
                          "Selector name.")),
163
    cl::sub(SymbolsSubcommand));
164
2
static FunctionNameType getFunctionNameFlags() {
165
2
  FunctionNameType Result = FunctionNameType(0);
166
2
  for (FunctionNameType Flag : FunctionNameFlags)
167
2
    Result = FunctionNameType(Result | Flag);
168
2
  return Result;
169
2
}
170
171
static cl::opt<bool> DumpAST("dump-ast",
172
                             cl::desc("Dump AST restored from symbols."),
173
                             cl::sub(SymbolsSubcommand));
174
static cl::opt<bool> DumpClangAST(
175
    "dump-clang-ast",
176
    cl::desc("Dump clang AST restored from symbols. When used on its own this "
177
             "will dump the entire AST of all loaded symbols. When combined "
178
             "with -find, it changes the presentation of the search results "
179
             "from pretty-printing the types to an AST dump."),
180
    cl::sub(SymbolsSubcommand));
181
182
static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
183
                            cl::sub(SymbolsSubcommand));
184
185
static cl::opt<std::string> File("file",
186
                                 cl::desc("File (compile unit) to search."),
187
                                 cl::sub(SymbolsSubcommand));
188
static cl::opt<int> Line("line", cl::desc("Line to search."),
189
                         cl::sub(SymbolsSubcommand));
190
191
static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile);
192
193
static Error findFunctions(lldb_private::Module &Module);
194
static Error findBlocks(lldb_private::Module &Module);
195
static Error findNamespaces(lldb_private::Module &Module);
196
static Error findTypes(lldb_private::Module &Module);
197
static Error findVariables(lldb_private::Module &Module);
198
static Error dumpModule(lldb_private::Module &Module);
199
static Error dumpAST(lldb_private::Module &Module);
200
static Error dumpEntireClangAST(lldb_private::Module &Module);
201
static Error verify(lldb_private::Module &Module);
202
203
static Expected<Error (*)(lldb_private::Module &)> getAction();
204
static int dumpSymbols(Debugger &Dbg);
205
} // namespace symbols
206
207
namespace irmemorymap {
208
static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
209
                                   cl::Required,
210
                                   cl::sub(IRMemoryMapSubcommand));
211
static cl::opt<std::string> CommandFile(cl::Positional,
212
                                        cl::desc("<command-file>"),
213
                                        cl::init("-"),
214
                                        cl::sub(IRMemoryMapSubcommand));
215
static cl::opt<bool> UseHostOnlyAllocationPolicy(
216
    "host-only", cl::desc("Use the host-only allocation policy"),
217
    cl::init(false), cl::sub(IRMemoryMapSubcommand));
218
219
using AllocationT = std::pair<addr_t, addr_t>;
220
using AddrIntervalMap =
221
    IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
222
223
struct IRMemoryMapTestState {
224
  TargetSP Target;
225
  IRMemoryMap Map;
226
227
  AddrIntervalMap::Allocator IntervalMapAllocator;
228
  AddrIntervalMap Allocations;
229
230
  StringMap<addr_t> Label2AddrMap;
231
232
  IRMemoryMapTestState(TargetSP Target)
233
6
      : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
234
};
235
236
bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
237
bool evalFree(StringRef Line, IRMemoryMapTestState &State);
238
int evaluateMemoryMapCommands(Debugger &Dbg);
239
} // namespace irmemorymap
240
241
namespace assert {
242
int lldb_assert(Debugger &Dbg);
243
} // namespace assert
244
} // namespace opts
245
246
9
std::vector<CompilerContext> parseCompilerContext() {
247
9
  std::vector<CompilerContext> result;
248
9
  if (opts::symbols::CompilerContext.empty())
249
0
    return result;
250
251
9
  StringRef str{opts::symbols::CompilerContext};
252
9
  SmallVector<StringRef, 8> entries_str;
253
9
  str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false);
254
23
  for (auto entry_str : entries_str) {
255
23
    StringRef key, value;
256
23
    std::tie(key, value) = entry_str.split(':');
257
23
    auto kind =
258
23
        StringSwitch<CompilerContextKind>(key)
259
23
            .Case("TranslationUnit", CompilerContextKind::TranslationUnit)
260
23
            .Case("Module", CompilerContextKind::Module)
261
23
            .Case("Namespace", CompilerContextKind::Namespace)
262
23
            .Case("Class", CompilerContextKind::Class)
263
23
            .Case("Struct", CompilerContextKind::Struct)
264
23
            .Case("Union", CompilerContextKind::Union)
265
23
            .Case("Function", CompilerContextKind::Function)
266
23
            .Case("Variable", CompilerContextKind::Variable)
267
23
            .Case("Enum", CompilerContextKind::Enum)
268
23
            .Case("Typedef", CompilerContextKind::Typedef)
269
23
            .Case("AnyModule", CompilerContextKind::AnyModule)
270
23
            .Case("AnyType", CompilerContextKind::AnyType)
271
23
            .Default(CompilerContextKind::Invalid);
272
23
    if (value.empty()) {
273
0
      WithColor::error() << "compiler context entry has no \"name\"\n";
274
0
      exit(1);
275
0
    }
276
23
    result.push_back({kind, ConstString{value}});
277
23
  }
278
9
  outs() << "Search context: {\n";
279
9
  for (auto entry: result)
280
23
    entry.Dump();
281
9
  outs() << "}\n";
282
283
9
  return result;
284
9
}
285
286
template <typename... Args>
287
0
static Error make_string_error(const char *Format, Args &&... args) {
288
0
  return llvm::make_error<llvm::StringError>(
289
0
      llvm::formatv(Format, std::forward<Args>(args)...).str(),
290
0
      llvm::inconvertibleErrorCode());
291
0
}
Unexecuted instantiation: lldb-test.cpp:llvm::Error make_string_error<>(char const*)
Unexecuted instantiation: lldb-test.cpp:llvm::Error make_string_error<unsigned int&>(char const*, unsigned int&)
Unexecuted instantiation: lldb-test.cpp:llvm::Error make_string_error<llvm::cl::opt<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, false, llvm::cl::parser<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&>(char const*, llvm::cl::opt<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, false, llvm::cl::parser<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&)
292
293
15
TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
294
15
  TargetSP Target;
295
15
  Status ST = Dbg.GetTargetList().CreateTarget(
296
15
      Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
297
15
      /*platform_options*/ nullptr, Target);
298
15
  if (ST.Fail()) {
299
0
    errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
300
0
    exit(1);
301
0
  }
302
15
  return Target;
303
15
}
304
305
15
std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
306
15
  auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
307
15
  if (!MB) {
308
0
    errs() << formatv("Could not open file '{0}: {1}\n", Filename,
309
0
                      MB.getError().message());
310
0
    exit(1);
311
0
  }
312
15
  return std::move(*MB);
313
15
}
314
315
23
void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
316
23
  P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
317
23
  if (List.GetSize() > 0)
318
23
    P.formatLine("At least one breakpoint.");
319
46
  for (size_t i = 0, e = List.GetSize(); i < e; 
++i23
) {
320
23
    BreakpointSP BP = List.GetBreakpointAtIndex(i);
321
23
    P.formatLine("Breakpoint ID {0}:", BP->GetID());
322
23
    AutoIndent Indent(P, 2);
323
23
    P.formatLine("{0} location{1}.", BP->GetNumLocations(),
324
23
                 plural(BP->GetNumLocations()));
325
23
    if (BP->GetNumLocations() > 0)
326
17
      P.formatLine("At least one location.");
327
23
    P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
328
23
                 plural(BP->GetNumResolvedLocations()));
329
23
    if (BP->GetNumResolvedLocations() > 0)
330
0
      P.formatLine("At least one resolved location.");
331
40
    for (size_t l = 0, le = BP->GetNumLocations(); l < le; 
++l17
) {
332
17
      BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
333
17
      P.formatLine("Location ID {0}:", Loc->GetID());
334
17
      AutoIndent Indent(P, 2);
335
17
      P.formatLine("Enabled: {0}", Loc->IsEnabled());
336
17
      P.formatLine("Resolved: {0}", Loc->IsResolved());
337
17
      SymbolContext sc;
338
17
      Loc->GetAddress().CalculateSymbolContext(&sc);
339
17
      lldb_private::StreamString S;
340
17
      sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
341
17
                         Loc->GetAddress(), false, true, false, true, true);
342
17
      P.formatLine("Address: {0}", S.GetString());
343
17
    }
344
23
  }
345
23
  P.NewLine();
346
23
}
347
348
23
std::string opts::breakpoint::substitute(StringRef Cmd) {
349
23
  std::string Result;
350
23
  raw_string_ostream OS(Result);
351
58
  while (!Cmd.empty()) {
352
35
    switch (Cmd[0]) {
353
6
    case '%':
354
6
      if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
355
6
        OS << sys::path::parent_path(breakpoint::CommandFile);
356
6
        break;
357
6
      }
358
6
      
LLVM_FALLTHROUGH0
;0
359
29
    default:
360
29
      size_t pos = Cmd.find('%');
361
29
      OS << Cmd.substr(0, pos);
362
29
      Cmd = Cmd.substr(pos);
363
29
      break;
364
35
    }
365
35
  }
366
23
  return std::move(OS.str());
367
23
}
368
369
9
int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
370
9
  TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
371
9
  std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
372
373
9
  LinePrinter P(4, outs());
374
9
  StringRef Rest = MB->getBuffer();
375
9
  int HadErrors = 0;
376
362
  while (!Rest.empty()) {
377
353
    StringRef Line;
378
353
    std::tie(Line, Rest) = Rest.split('\n');
379
353
    Line = Line.ltrim().rtrim();
380
353
    if (Line.empty() || 
Line[0] == '#'315
)
381
330
      continue;
382
383
23
    if (!Persistent)
384
23
      Target->RemoveAllBreakpoints(/*internal_also*/ true);
385
386
23
    std::string Command = substitute(Line);
387
23
    P.formatLine("Command: {0}", Command);
388
23
    CommandReturnObject Result(/*colors*/ false);
389
23
    if (!Dbg.GetCommandInterpreter().HandleCommand(
390
23
            Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
391
0
      P.formatLine("Failed: {0}", Result.GetErrorData());
392
0
      HadErrors = 1;
393
0
      continue;
394
0
    }
395
396
23
    dumpState(Target->GetBreakpointList(/*internal*/ false), P);
397
23
  }
398
9
  return HadErrors;
399
9
}
400
401
Expected<CompilerDeclContext>
402
11
opts::symbols::getDeclContext(SymbolFile &Symfile) {
403
11
  if (Context.empty())
404
11
    return CompilerDeclContext();
405
0
  VariableList List;
406
0
  Symfile.FindGlobalVariables(ConstString(Context), CompilerDeclContext(),
407
0
                              UINT32_MAX, List);
408
0
  if (List.Empty())
409
0
    return make_string_error("Context search didn't find a match.");
410
0
  if (List.GetSize() > 1)
411
0
    return make_string_error("Context search found multiple matches.");
412
0
  return List.GetVariableAtIndex(0)->GetDeclContext();
413
0
}
414
415
9
static lldb::DescriptionLevel GetDescriptionLevel() {
416
9
  return opts::symbols::DumpClangAST ? 
eDescriptionLevelVerbose3
:
eDescriptionLevelFull6
;
417
9
}
418
419
1
Error opts::symbols::findFunctions(lldb_private::Module &Module) {
420
1
  SymbolFile &Symfile = *Module.GetSymbolFile();
421
1
  SymbolContextList List;
422
1
  if (!File.empty()) {
423
0
    assert(Line != 0);
424
425
0
    FileSpec src_file(File);
426
0
    size_t cu_count = Module.GetNumCompileUnits();
427
0
    for (size_t i = 0; i < cu_count; i++) {
428
0
      lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
429
0
      if (!cu_sp)
430
0
        continue;
431
432
0
      LineEntry le;
433
0
      cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
434
0
      if (!le.IsValid())
435
0
        continue;
436
0
      const bool include_inlined_functions = false;
437
0
      auto addr =
438
0
          le.GetSameLineContiguousAddressRange(include_inlined_functions)
439
0
              .GetBaseAddress();
440
0
      if (!addr.IsValid())
441
0
        continue;
442
443
0
      SymbolContext sc;
444
0
      uint32_t resolved =
445
0
          addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
446
0
      if (resolved & eSymbolContextFunction)
447
0
        List.Append(sc);
448
0
    }
449
1
  } else if (Regex) {
450
0
    RegularExpression RE(Name);
451
0
    assert(RE.IsValid());
452
0
    List.Clear();
453
0
    Symfile.FindFunctions(RE, true, List);
454
1
  } else {
455
1
    Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
456
1
    if (!ContextOr)
457
0
      return ContextOr.takeError();
458
1
    const CompilerDeclContext &ContextPtr =
459
1
        ContextOr->IsValid() ? 
*ContextOr0
: CompilerDeclContext();
460
461
1
    List.Clear();
462
1
    Symfile.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
463
1
                         true, List);
464
1
  }
465
1
  outs() << formatv("Found {0} functions:\n", List.GetSize());
466
1
  StreamString Stream;
467
1
  List.Dump(&Stream, nullptr);
468
1
  outs() << Stream.GetData() << "\n";
469
1
  return Error::success();
470
1
}
471
472
0
Error opts::symbols::findBlocks(lldb_private::Module &Module) {
473
0
  assert(!Regex);
474
0
  assert(!File.empty());
475
0
  assert(Line != 0);
476
477
0
  SymbolContextList List;
478
479
0
  FileSpec src_file(File);
480
0
  size_t cu_count = Module.GetNumCompileUnits();
481
0
  for (size_t i = 0; i < cu_count; i++) {
482
0
    lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
483
0
    if (!cu_sp)
484
0
      continue;
485
486
0
    LineEntry le;
487
0
    cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
488
0
    if (!le.IsValid())
489
0
      continue;
490
0
    const bool include_inlined_functions = false;
491
0
    auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions)
492
0
                    .GetBaseAddress();
493
0
    if (!addr.IsValid())
494
0
      continue;
495
496
0
    SymbolContext sc;
497
0
    uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
498
0
    if (resolved & eSymbolContextBlock)
499
0
      List.Append(sc);
500
0
  }
501
502
0
  outs() << formatv("Found {0} blocks:\n", List.GetSize());
503
0
  StreamString Stream;
504
0
  List.Dump(&Stream, nullptr);
505
0
  outs() << Stream.GetData() << "\n";
506
0
  return Error::success();
507
0
}
508
509
0
Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
510
0
  SymbolFile &Symfile = *Module.GetSymbolFile();
511
0
  Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
512
0
  if (!ContextOr)
513
0
    return ContextOr.takeError();
514
0
  const CompilerDeclContext &ContextPtr =
515
0
      ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
516
517
0
  CompilerDeclContext Result =
518
0
      Symfile.FindNamespace(ConstString(Name), ContextPtr);
519
0
  if (Result)
520
0
    outs() << "Found namespace: "
521
0
           << Result.GetScopeQualifiedName().GetStringRef() << "\n";
522
0
  else
523
0
    outs() << "Namespace not found.\n";
524
0
  return Error::success();
525
0
}
526
527
9
Error opts::symbols::findTypes(lldb_private::Module &Module) {
528
9
  SymbolFile &Symfile = *Module.GetSymbolFile();
529
9
  Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
530
9
  if (!ContextOr)
531
0
    return ContextOr.takeError();
532
9
  const CompilerDeclContext &ContextPtr =
533
9
      ContextOr->IsValid() ? 
*ContextOr0
: CompilerDeclContext();
534
535
9
  LanguageSet languages;
536
9
  if (!Language.empty())
537
9
    languages.Insert(Language::GetLanguageTypeFromString(Language));
538
539
9
  DenseSet<SymbolFile *> SearchedFiles;
540
9
  TypeMap Map;
541
9
  if (!Name.empty())
542
0
    Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
543
0
                      Map);
544
9
  else
545
9
    Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
546
547
9
  outs() << formatv("Found {0} types:\n", Map.GetSize());
548
9
  StreamString Stream;
549
  // Resolve types to force-materialize typedef types.
550
9
  Map.ForEach([&](TypeSP &type) {
551
7
    type->GetFullCompilerType();
552
7
    return false;
553
7
  });
554
9
  Map.Dump(&Stream, false, GetDescriptionLevel());
555
9
  outs() << Stream.GetData() << "\n";
556
9
  return Error::success();
557
9
}
558
559
1
Error opts::symbols::findVariables(lldb_private::Module &Module) {
560
1
  SymbolFile &Symfile = *Module.GetSymbolFile();
561
1
  VariableList List;
562
1
  if (Regex) {
563
0
    RegularExpression RE(Name);
564
0
    assert(RE.IsValid());
565
0
    Symfile.FindGlobalVariables(RE, UINT32_MAX, List);
566
1
  } else if (!File.empty()) {
567
0
    CompUnitSP CU;
568
0
    for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
569
0
      CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
570
0
      if (!Candidate ||
571
0
          Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File)
572
0
        continue;
573
0
      if (CU)
574
0
        return make_string_error("Multiple compile units for file `{0}` found.",
575
0
                                 File);
576
0
      CU = std::move(Candidate);
577
0
    }
578
579
0
    if (!CU)
580
0
      return make_string_error("Compile unit `{0}` not found.", File);
581
582
0
    List.AddVariables(CU->GetVariableList(true).get());
583
1
  } else {
584
1
    Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
585
1
    if (!ContextOr)
586
0
      return ContextOr.takeError();
587
1
    const CompilerDeclContext &ContextPtr =
588
1
        ContextOr->IsValid() ? 
*ContextOr0
: CompilerDeclContext();
589
590
1
    Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
591
1
  }
592
1
  outs() << formatv("Found {0} variables:\n", List.GetSize());
593
1
  StreamString Stream;
594
1
  List.Dump(&Stream, false);
595
1
  outs() << Stream.GetData() << "\n";
596
1
  return Error::success();
597
1
}
598
599
11
Error opts::symbols::dumpModule(lldb_private::Module &Module) {
600
11
  StreamString Stream;
601
11
  Module.ParseAllDebugSymbols();
602
11
  Module.Dump(&Stream);
603
11
  outs() << Stream.GetData() << "\n";
604
11
  return Error::success();
605
11
}
606
607
0
Error opts::symbols::dumpAST(lldb_private::Module &Module) {
608
0
  Module.ParseAllDebugSymbols();
609
610
0
  SymbolFile *symfile = Module.GetSymbolFile();
611
0
  if (!symfile)
612
0
    return make_string_error("Module has no symbol file.");
613
614
0
  llvm::Expected<TypeSystem &> type_system_or_err =
615
0
      symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
616
0
  if (!type_system_or_err)
617
0
    return make_string_error("Can't retrieve TypeSystemClang");
618
619
0
  auto *clang_ast_ctx =
620
0
      llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
621
0
  if (!clang_ast_ctx)
622
0
    return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
623
624
0
  clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext();
625
626
0
  clang::TranslationUnitDecl *tu = ast_ctx.getTranslationUnitDecl();
627
0
  if (!tu)
628
0
    return make_string_error("Can't retrieve translation unit declaration.");
629
630
0
  tu->print(outs());
631
632
0
  return Error::success();
633
0
}
634
635
6
Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) {
636
6
  Module.ParseAllDebugSymbols();
637
638
6
  SymbolFile *symfile = Module.GetSymbolFile();
639
6
  if (!symfile)
640
0
    return make_string_error("Module has no symbol file.");
641
642
6
  llvm::Expected<TypeSystem &> type_system_or_err =
643
6
      symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus);
644
6
  if (!type_system_or_err)
645
0
    return make_string_error("Can't retrieve TypeSystemClang");
646
647
6
  auto *clang_ast_ctx =
648
6
      llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get());
649
6
  if (!clang_ast_ctx)
650
0
    return make_string_error("Retrieved TypeSystem was not a TypeSystemClang");
651
652
6
  StreamString Stream;
653
6
  clang_ast_ctx->DumpFromSymbolFile(Stream, Name);
654
6
  outs() << Stream.GetData() << "\n";
655
656
6
  return Error::success();
657
6
}
658
659
0
Error opts::symbols::verify(lldb_private::Module &Module) {
660
0
  SymbolFile *symfile = Module.GetSymbolFile();
661
0
  if (!symfile)
662
0
    return make_string_error("Module has no symbol file.");
663
664
0
  uint32_t comp_units_count = symfile->GetNumCompileUnits();
665
666
0
  outs() << "Found " << comp_units_count << " compile units.\n";
667
668
0
  for (uint32_t i = 0; i < comp_units_count; i++) {
669
0
    lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i);
670
0
    if (!comp_unit)
671
0
      return make_string_error("Cannot parse compile unit {0}.", i);
672
673
0
    outs() << "Processing '"
674
0
           << comp_unit->GetPrimaryFile().GetFilename().AsCString()
675
0
           << "' compile unit.\n";
676
677
0
    LineTable *lt = comp_unit->GetLineTable();
678
0
    if (!lt)
679
0
      return make_string_error("Can't get a line table of a compile unit.");
680
681
0
    uint32_t count = lt->GetSize();
682
683
0
    outs() << "The line table contains " << count << " entries.\n";
684
685
0
    if (count == 0)
686
0
      continue;
687
688
0
    LineEntry le;
689
0
    if (!lt->GetLineEntryAtIndex(0, le))
690
0
      return make_string_error("Can't get a line entry of a compile unit.");
691
692
0
    for (uint32_t i = 1; i < count; i++) {
693
0
      lldb::addr_t curr_end =
694
0
          le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
695
696
0
      if (!lt->GetLineEntryAtIndex(i, le))
697
0
        return make_string_error("Can't get a line entry of a compile unit");
698
699
0
      if (curr_end > le.range.GetBaseAddress().GetFileAddress())
700
0
        return make_string_error(
701
0
            "Line table of a compile unit is inconsistent.");
702
0
    }
703
0
  }
704
705
0
  outs() << "The symbol information is verified.\n";
706
707
0
  return Error::success();
708
0
}
709
710
28
Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
711
28
  if (Verify && 
DumpAST0
)
712
0
    return make_string_error(
713
0
        "Cannot both verify symbol information and dump AST.");
714
715
28
  if (Verify) {
716
0
    if (Find != FindType::None)
717
0
      return make_string_error(
718
0
          "Cannot both search and verify symbol information.");
719
0
    if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
720
0
        Line != 0)
721
0
      return make_string_error(
722
0
          "-regex, -context, -name, -file and -line options are not "
723
0
          "applicable for symbol verification.");
724
0
    return verify;
725
0
  }
726
727
28
  if (DumpAST) {
728
0
    if (Find != FindType::None)
729
0
      return make_string_error("Cannot both search and dump AST.");
730
0
    if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
731
0
        Line != 0)
732
0
      return make_string_error(
733
0
          "-regex, -context, -name, -file and -line options are not "
734
0
          "applicable for dumping AST.");
735
0
    return dumpAST;
736
0
  }
737
738
28
  if (DumpClangAST) {
739
9
    if (Find == FindType::None) {
740
6
      if (Regex || !Context.empty() || !File.empty() || Line != 0)
741
0
        return make_string_error(
742
0
            "-regex, -context, -name, -file and -line options are not "
743
0
            "applicable for dumping the entire clang AST. Either combine with "
744
0
            "-find, or use -dump-clang-ast as a standalone option.");
745
6
      return dumpEntireClangAST;
746
6
    }
747
3
    if (Find != FindType::Type)
748
0
      return make_string_error("This combination of -dump-clang-ast and -find "
749
0
                               "<kind> is not yet implemented.");
750
3
  }
751
752
22
  if (Regex && 
!Context.empty()0
)
753
0
    return make_string_error(
754
0
        "Cannot search using both regular expressions and context.");
755
756
22
  if (Regex && 
!RegularExpression(Name).IsValid()0
)
757
0
    return make_string_error("`{0}` is not a valid regular expression.", Name);
758
759
22
  if (Regex + !Context.empty() + !File.empty() >= 2)
760
0
    return make_string_error(
761
0
        "Only one of -regex, -context and -file may be used simultaneously.");
762
22
  if (Regex && 
Name.empty()0
)
763
0
    return make_string_error("-regex used without a -name");
764
765
22
  switch (Find) {
766
11
  case FindType::None:
767
11
    if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
768
0
      return make_string_error(
769
0
          "Specify search type (-find) to use search options.");
770
11
    return dumpModule;
771
772
1
  case FindType::Function:
773
1
    if (!File.empty() + (Line != 0) == 1)
774
0
      return make_string_error("Both file name and line number must be "
775
0
                               "specified when searching a function "
776
0
                               "by file position.");
777
1
    if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
778
0
      return make_string_error("Only one of regular expression, function-flags "
779
0
                               "and file position may be used simultaneously "
780
0
                               "when searching a function.");
781
1
    return findFunctions;
782
783
0
  case FindType::Block:
784
0
    if (File.empty() || Line == 0)
785
0
      return make_string_error("Both file name and line number must be "
786
0
                               "specified when searching a block.");
787
0
    if (Regex || getFunctionNameFlags() != 0)
788
0
      return make_string_error("Cannot use regular expression or "
789
0
                               "function-flags for searching a block.");
790
0
    return findBlocks;
791
792
0
  case FindType::Namespace:
793
0
    if (Regex || !File.empty() || Line != 0)
794
0
      return make_string_error("Cannot search for namespaces using regular "
795
0
                               "expressions, file names or line numbers.");
796
0
    return findNamespaces;
797
798
9
  case FindType::Type:
799
9
    if (Regex || !File.empty() || Line != 0)
800
0
      return make_string_error("Cannot search for types using regular "
801
0
                               "expressions, file names or line numbers.");
802
9
    if (!Name.empty() && 
!CompilerContext.empty()0
)
803
0
      return make_string_error("Name is ignored if compiler context present.");
804
805
9
    return findTypes;
806
807
1
  case FindType::Variable:
808
1
    if (Line != 0)
809
0
      return make_string_error("Cannot search for variables "
810
0
                               "using line numbers.");
811
1
    return findVariables;
812
22
  }
813
814
0
  llvm_unreachable("Unsupported symbol action.");
815
0
}
816
817
28
int opts::symbols::dumpSymbols(Debugger &Dbg) {
818
28
  auto ActionOr = getAction();
819
28
  if (!ActionOr) {
820
0
    logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
821
0
    return 1;
822
0
  }
823
28
  auto Action = *ActionOr;
824
825
28
  outs() << "Module: " << InputFile << "\n";
826
28
  ModuleSpec Spec{FileSpec(InputFile)};
827
28
  StringRef Symbols = SymbolPath.empty() ? InputFile : 
SymbolPath0
;
828
28
  Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
829
830
28
  auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
831
28
  SymbolFile *Symfile = ModulePtr->GetSymbolFile();
832
28
  if (!Symfile) {
833
0
    WithColor::error() << "Module has no symbol vendor.\n";
834
0
    return 1;
835
0
  }
836
837
28
  if (Error E = Action(*ModulePtr)) {
838
0
    WithColor::error() << toString(std::move(E)) << "\n";
839
0
    return 1;
840
0
  }
841
842
28
  return 0;
843
28
}
844
845
60
static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
846
60
  size_t Count = List.GetNumSections(0);
847
60
  if (Count == 0) {
848
5
    Printer.formatLine("There are no {0}sections", is_subsection ? 
"sub"3
:
""2
);
849
5
    return;
850
5
  }
851
55
  Printer.formatLine("Showing {0} {1}sections", Count,
852
55
                     is_subsection ? 
"sub"12
:
""43
);
853
65.8k
  for (size_t I = 0; I < Count; 
++I65.7k
) {
854
65.7k
    auto S = List.GetSectionAtIndex(I);
855
65.7k
    assert(S);
856
0
    AutoIndent Indent(Printer, 2);
857
65.7k
    Printer.formatLine("Index: {0}", I);
858
65.7k
    Printer.formatLine("ID: {0:x}", S->GetID());
859
65.7k
    Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
860
65.7k
    Printer.formatLine("Type: {0}", S->GetTypeAsCString());
861
65.7k
    Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
862
65.7k
    Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
863
65.7k
    Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
864
65.7k
    Printer.formatLine("VM size: {0}", S->GetByteSize());
865
65.7k
    Printer.formatLine("File size: {0}", S->GetFileSize());
866
867
65.7k
    if (opts::object::SectionContents) {
868
30
      lldb_private::DataExtractor Data;
869
30
      S->GetSectionData(Data);
870
30
      ArrayRef<uint8_t> Bytes(Data.GetDataStart(), Data.GetDataEnd());
871
30
      Printer.formatBinary("Data: ", Bytes, 0);
872
30
    }
873
874
65.7k
    if (S->GetType() == eSectionTypeContainer)
875
15
      dumpSectionList(Printer, S->GetChildren(), true);
876
65.7k
    Printer.NewLine();
877
65.7k
  }
878
55
}
879
880
48
static int dumpObjectFiles(Debugger &Dbg) {
881
48
  LinePrinter Printer(4, llvm::outs());
882
883
48
  int HadErrors = 0;
884
48
  for (const auto &File : opts::object::InputFilenames) {
885
48
    ModuleSpec Spec{FileSpec(File)};
886
887
48
    auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
888
889
48
    ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
890
48
    if (!ObjectPtr) {
891
3
      WithColor::error() << File << " not recognised as an object file\n";
892
3
      HadErrors = 1;
893
3
      continue;
894
3
    }
895
896
    // Fetch symbol vendor before we get the section list to give the symbol
897
    // vendor a chance to populate it.
898
45
    ModulePtr->GetSymbolFile();
899
45
    SectionList *Sections = ModulePtr->GetSectionList();
900
45
    if (!Sections) {
901
0
      llvm::errs() << "Could not load sections for module " << File << "\n";
902
0
      HadErrors = 1;
903
0
      continue;
904
0
    }
905
906
45
    Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
907
45
    Printer.formatLine("Architecture: {0}",
908
45
                       ModulePtr->GetArchitecture().GetTriple().getTriple());
909
45
    Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
910
45
    Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
911
45
    Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
912
45
    Printer.formatLine("Type: {0}", ObjectPtr->GetType());
913
45
    Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
914
45
    Printer.formatLine("Base VM address: {0:x}",
915
45
                       ObjectPtr->GetBaseAddress().GetFileAddress());
916
917
45
    dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
918
919
45
    if (opts::object::SectionDependentModules) {
920
      // A non-empty section list ensures a valid object file.
921
0
      auto Obj = ModulePtr->GetObjectFile();
922
0
      FileSpecList Files;
923
0
      auto Count = Obj->GetDependentModules(Files);
924
0
      Printer.formatLine("Showing {0} dependent module(s)", Count);
925
0
      for (size_t I = 0; I < Files.GetSize(); ++I) {
926
0
        AutoIndent Indent(Printer, 2);
927
0
        Printer.formatLine("Name: {0}",
928
0
                           Files.GetFileSpecAtIndex(I).GetCString());
929
0
      }
930
0
      Printer.NewLine();
931
0
    }
932
45
  }
933
48
  return HadErrors;
934
48
}
935
936
bool opts::irmemorymap::evalMalloc(StringRef Line,
937
602
                                   IRMemoryMapTestState &State) {
938
  // ::= <label> = malloc <size> <alignment>
939
602
  StringRef Label;
940
602
  std::tie(Label, Line) = Line.split('=');
941
602
  if (Line.empty())
942
272
    return false;
943
330
  Label = Label.trim();
944
330
  Line = Line.trim();
945
330
  size_t Size;
946
330
  uint8_t Alignment;
947
330
  int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
948
330
  if (Matches != 2)
949
0
    return false;
950
951
330
  outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
952
330
                    Size, Alignment);
953
330
  if (!isPowerOf2_32(Alignment)) {
954
0
    outs() << "Malloc error: alignment is not a power of 2\n";
955
0
    exit(1);
956
0
  }
957
958
330
  IRMemoryMap::AllocationPolicy AP =
959
330
      UseHostOnlyAllocationPolicy ? 
IRMemoryMap::eAllocationPolicyHostOnly165
960
330
                                  : 
IRMemoryMap::eAllocationPolicyProcessOnly165
;
961
962
  // Issue the malloc in the target process with "-rw" permissions.
963
330
  const uint32_t Permissions = 0x3;
964
330
  const bool ZeroMemory = false;
965
330
  Status ST;
966
330
  addr_t Addr =
967
330
      State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
968
330
  if (ST.Fail()) {
969
0
    outs() << formatv("Malloc error: {0}\n", ST);
970
0
    return true;
971
0
  }
972
973
  // Print the result of the allocation before checking its validity.
974
330
  outs() << formatv("Malloc: address = {0:x}\n", Addr);
975
976
  // Check that the allocation is aligned.
977
330
  if (!Addr || Addr % Alignment != 0) {
978
0
    outs() << "Malloc error: zero or unaligned allocation detected\n";
979
0
    exit(1);
980
0
  }
981
982
  // In case of Size == 0, we still expect the returned address to be unique and
983
  // non-overlapping.
984
330
  addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
985
330
  if (State.Allocations.overlaps(Addr, EndOfRegion)) {
986
0
    auto I = State.Allocations.find(Addr);
987
0
    outs() << "Malloc error: overlapping allocation detected"
988
0
           << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
989
0
                      I.stop());
990
0
    exit(1);
991
0
  }
992
993
  // Insert the new allocation into the interval map. Use unique allocation
994
  // IDs to inhibit interval coalescing.
995
330
  static unsigned AllocationID = 0;
996
330
  State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
997
998
  // Store the label -> address mapping.
999
330
  State.Label2AddrMap[Label] = Addr;
1000
1001
330
  return true;
1002
330
}
1003
1004
272
bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
1005
  // ::= free <label>
1006
272
  if (!Line.consume_front("free"))
1007
0
    return false;
1008
272
  StringRef Label = Line.trim();
1009
1010
272
  outs() << formatv("Command: free({0})\n", Label);
1011
272
  auto LabelIt = State.Label2AddrMap.find(Label);
1012
272
  if (LabelIt == State.Label2AddrMap.end()) {
1013
0
    outs() << "Free error: Invalid allocation label\n";
1014
0
    exit(1);
1015
0
  }
1016
1017
272
  Status ST;
1018
272
  addr_t Addr = LabelIt->getValue();
1019
272
  State.Map.Free(Addr, ST);
1020
272
  if (ST.Fail()) {
1021
0
    outs() << formatv("Free error: {0}\n", ST);
1022
0
    exit(1);
1023
0
  }
1024
1025
  // Erase the allocation from the live interval map.
1026
272
  auto Interval = State.Allocations.find(Addr);
1027
272
  if (Interval != State.Allocations.end()) {
1028
272
    outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
1029
272
                      Interval.stop());
1030
272
    Interval.erase();
1031
272
  }
1032
1033
272
  return true;
1034
272
}
1035
1036
6
int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
1037
  // Set up a Target.
1038
6
  TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
1039
1040
  // Set up a Process. In order to allocate memory within a target, this
1041
  // process must be alive and must support JIT'ing.
1042
6
  CommandReturnObject Result(/*colors*/ false);
1043
6
  Dbg.SetAsyncExecution(false);
1044
6
  CommandInterpreter &CI = Dbg.GetCommandInterpreter();
1045
12
  auto IssueCmd = [&](const char *Cmd) -> bool {
1046
12
    return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
1047
12
  };
1048
6
  if (!IssueCmd("b main") || !IssueCmd("run")) {
1049
0
    outs() << formatv("Failed: {0}\n", Result.GetErrorData());
1050
0
    exit(1);
1051
0
  }
1052
1053
6
  ProcessSP Process = Target->GetProcessSP();
1054
6
  if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
1055
0
    outs() << "Cannot use process to test IRMemoryMap\n";
1056
0
    exit(1);
1057
0
  }
1058
1059
  // Set up an IRMemoryMap and associated testing state.
1060
6
  IRMemoryMapTestState State(Target);
1061
1062
  // Parse and apply commands from the command file.
1063
6
  std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
1064
6
  StringRef Rest = MB->getBuffer();
1065
620
  while (!Rest.empty()) {
1066
614
    StringRef Line;
1067
614
    std::tie(Line, Rest) = Rest.split('\n');
1068
614
    Line = Line.ltrim().rtrim();
1069
1070
614
    if (Line.empty() || 
Line[0] == '#'602
)
1071
12
      continue;
1072
1073
602
    if (evalMalloc(Line, State))
1074
330
      continue;
1075
1076
272
    if (evalFree(Line, State))
1077
272
      continue;
1078
1079
0
    errs() << "Could not parse line: " << Line << "\n";
1080
0
    exit(1);
1081
272
  }
1082
6
  return 0;
1083
6
}
1084
1085
0
int opts::assert::lldb_assert(Debugger &Dbg) {
1086
0
  lldbassert(false && "lldb-test assert");
1087
0
  return 1;
1088
0
}
1089
1090
91
int main(int argc, const char *argv[]) {
1091
91
  StringRef ToolName = argv[0];
1092
91
  sys::PrintStackTraceOnErrorSignal(ToolName);
1093
91
  PrettyStackTraceProgram X(argc, argv);
1094
91
  llvm_shutdown_obj Y;
1095
1096
91
  cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
1097
1098
91
  SystemLifetimeManager DebuggerLifetime;
1099
91
  if (auto e = DebuggerLifetime.Initialize(
1100
91
          std::make_unique<SystemInitializerTest>(), nullptr)) {
1101
0
    WithColor::error() << "initialization failed: " << toString(std::move(e))
1102
0
                       << '\n';
1103
0
    return 1;
1104
0
  }
1105
1106
91
  auto TerminateDebugger =
1107
91
      llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); });
1108
1109
91
  auto Dbg = lldb_private::Debugger::CreateInstance();
1110
91
  ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
1111
91
  CommandReturnObject Result(/*colors*/ false);
1112
91
  Dbg->GetCommandInterpreter().HandleCommand(
1113
91
      "settings set plugin.process.gdb-remote.packet-timeout 60",
1114
91
      /*add_to_history*/ eLazyBoolNo, Result);
1115
91
  Dbg->GetCommandInterpreter().HandleCommand(
1116
91
      "settings set target.inherit-tcc true",
1117
91
      /*add_to_history*/ eLazyBoolNo, Result);
1118
91
  Dbg->GetCommandInterpreter().HandleCommand(
1119
91
      "settings set target.detach-on-error false",
1120
91
      /*add_to_history*/ eLazyBoolNo, Result);
1121
1122
91
  if (!opts::Log.empty())
1123
0
    Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
1124
1125
91
  if (opts::BreakpointSubcommand)
1126
9
    return opts::breakpoint::evaluateBreakpoints(*Dbg);
1127
82
  if (opts::ObjectFileSubcommand)
1128
48
    return dumpObjectFiles(*Dbg);
1129
34
  if (opts::SymbolsSubcommand)
1130
28
    return opts::symbols::dumpSymbols(*Dbg);
1131
6
  if (opts::IRMemoryMapSubcommand)
1132
6
    return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
1133
0
  if (opts::AssertSubcommand)
1134
0
    return opts::assert::lldb_assert(*Dbg);
1135
1136
0
  WithColor::error() << "No command specified.\n";
1137
0
  return 1;
1138
0
}