Coverage Report

Created: 2023-09-30 09:22

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