summaryrefslogtreecommitdiff
path: root/tools/lldb-test/lldb-test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lldb-test/lldb-test.cpp')
-rw-r--r--tools/lldb-test/lldb-test.cpp991
1 files changed, 0 insertions, 991 deletions
diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp
deleted file mode 100644
index f7bfc487c0ce..000000000000
--- a/tools/lldb-test/lldb-test.cpp
+++ /dev/null
@@ -1,991 +0,0 @@
-//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "FormatUtil.h"
-#include "SystemInitializerTest.h"
-
-#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Section.h"
-#include "lldb/Expression/IRMemoryMap.h"
-#include "lldb/Initialization/SystemLifetimeManager.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/LineTable.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/CleanUp.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/State.h"
-#include "lldb/Utility/StreamString.h"
-
-#include "llvm/ADT/IntervalMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/WithColor.h"
-#include <cstdio>
-#include <thread>
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace llvm;
-
-namespace opts {
-static cl::SubCommand BreakpointSubcommand("breakpoints",
- "Test breakpoint resolution");
-cl::SubCommand ObjectFileSubcommand("object-file",
- "Display LLDB object file information");
-cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
-cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap");
-
-cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""),
- cl::sub(BreakpointSubcommand),
- cl::sub(ObjectFileSubcommand),
- cl::sub(SymbolsSubcommand),
- cl::sub(IRMemoryMapSubcommand));
-
-/// Create a target using the file pointed to by \p Filename, or abort.
-TargetSP createTarget(Debugger &Dbg, const std::string &Filename);
-
-/// Read \p Filename into a null-terminated buffer, or abort.
-std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename);
-
-namespace breakpoint {
-static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
- cl::Required, cl::sub(BreakpointSubcommand));
-static cl::opt<std::string> CommandFile(cl::Positional,
- cl::desc("<command-file>"),
- cl::init("-"),
- cl::sub(BreakpointSubcommand));
-static cl::opt<bool> Persistent(
- "persistent",
- cl::desc("Don't automatically remove all breakpoints before each command"),
- cl::sub(BreakpointSubcommand));
-
-static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
-static void dumpState(const BreakpointList &List, LinePrinter &P);
-static std::string substitute(StringRef Cmd);
-static int evaluateBreakpoints(Debugger &Dbg);
-} // namespace breakpoint
-
-namespace object {
-cl::opt<bool> SectionContents("contents",
- cl::desc("Dump each section's contents"),
- cl::sub(ObjectFileSubcommand));
-cl::opt<bool> SectionDependentModules("dep-modules",
- cl::desc("Dump each dependent module"),
- cl::sub(ObjectFileSubcommand));
-cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
- cl::OneOrMore,
- cl::sub(ObjectFileSubcommand));
-} // namespace object
-
-namespace symbols {
-static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
- cl::Required, cl::sub(SymbolsSubcommand));
-
-static cl::opt<std::string>
- SymbolPath("symbol-file",
- cl::desc("The file from which to fetch symbol information."),
- cl::value_desc("file"), cl::sub(SymbolsSubcommand));
-
-enum class FindType {
- None,
- Function,
- Block,
- Namespace,
- Type,
- Variable,
-};
-static cl::opt<FindType> Find(
- "find", cl::desc("Choose search type:"),
- cl::values(
- clEnumValN(FindType::None, "none", "No search, just dump the module."),
- clEnumValN(FindType::Function, "function", "Find functions."),
- clEnumValN(FindType::Block, "block", "Find blocks."),
- clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
- clEnumValN(FindType::Type, "type", "Find types."),
- clEnumValN(FindType::Variable, "variable", "Find global variables.")),
- cl::sub(SymbolsSubcommand));
-
-static cl::opt<std::string> Name("name", cl::desc("Name to find."),
- cl::sub(SymbolsSubcommand));
-static cl::opt<bool>
- Regex("regex",
- cl::desc("Search using regular expressions (avaliable for variables "
- "and functions only)."),
- cl::sub(SymbolsSubcommand));
-static cl::opt<std::string>
- Context("context",
- cl::desc("Restrict search to the context of the given variable."),
- cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
-
-static cl::list<FunctionNameType> FunctionNameFlags(
- "function-flags", cl::desc("Function search flags:"),
- cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
- "Automatically deduce flags based on name."),
- clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
- clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
- clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
- clEnumValN(eFunctionNameTypeSelector, "selector",
- "Selector name.")),
- cl::sub(SymbolsSubcommand));
-static FunctionNameType getFunctionNameFlags() {
- FunctionNameType Result = FunctionNameType(0);
- for (FunctionNameType Flag : FunctionNameFlags)
- Result = FunctionNameType(Result | Flag);
- return Result;
-}
-
-static cl::opt<bool> DumpAST("dump-ast",
- cl::desc("Dump AST restored from symbols."),
- cl::sub(SymbolsSubcommand));
-
-static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
- cl::sub(SymbolsSubcommand));
-
-static cl::opt<std::string> File("file",
- cl::desc("File (compile unit) to search."),
- cl::sub(SymbolsSubcommand));
-static cl::opt<int> Line("line", cl::desc("Line to search."),
- cl::sub(SymbolsSubcommand));
-
-static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
-
-static Error findFunctions(lldb_private::Module &Module);
-static Error findBlocks(lldb_private::Module &Module);
-static Error findNamespaces(lldb_private::Module &Module);
-static Error findTypes(lldb_private::Module &Module);
-static Error findVariables(lldb_private::Module &Module);
-static Error dumpModule(lldb_private::Module &Module);
-static Error dumpAST(lldb_private::Module &Module);
-static Error verify(lldb_private::Module &Module);
-
-static Expected<Error (*)(lldb_private::Module &)> getAction();
-static int dumpSymbols(Debugger &Dbg);
-} // namespace symbols
-
-namespace irmemorymap {
-static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
- cl::Required,
- cl::sub(IRMemoryMapSubcommand));
-static cl::opt<std::string> CommandFile(cl::Positional,
- cl::desc("<command-file>"),
- cl::init("-"),
- cl::sub(IRMemoryMapSubcommand));
-static cl::opt<bool> UseHostOnlyAllocationPolicy(
- "host-only", cl::desc("Use the host-only allocation policy"),
- cl::init(false), cl::sub(IRMemoryMapSubcommand));
-
-using AllocationT = std::pair<addr_t, addr_t>;
-using AddrIntervalMap =
- IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
-
-struct IRMemoryMapTestState {
- TargetSP Target;
- IRMemoryMap Map;
-
- AddrIntervalMap::Allocator IntervalMapAllocator;
- AddrIntervalMap Allocations;
-
- StringMap<addr_t> Label2AddrMap;
-
- IRMemoryMapTestState(TargetSP Target)
- : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
-};
-
-bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
-bool evalFree(StringRef Line, IRMemoryMapTestState &State);
-int evaluateMemoryMapCommands(Debugger &Dbg);
-} // namespace irmemorymap
-
-} // namespace opts
-
-template <typename... Args>
-static Error make_string_error(const char *Format, Args &&... args) {
- return llvm::make_error<llvm::StringError>(
- llvm::formatv(Format, std::forward<Args>(args)...).str(),
- llvm::inconvertibleErrorCode());
-}
-
-TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
- TargetSP Target;
- Status ST = Dbg.GetTargetList().CreateTarget(
- Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
- /*platform_options*/ nullptr, Target);
- if (ST.Fail()) {
- errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
- exit(1);
- }
- return Target;
-}
-
-std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) {
- auto MB = MemoryBuffer::getFileOrSTDIN(Filename);
- if (!MB) {
- errs() << formatv("Could not open file '{0}: {1}\n", Filename,
- MB.getError().message());
- exit(1);
- }
- return std::move(*MB);
-}
-
-void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
- P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
- if (List.GetSize() > 0)
- P.formatLine("At least one breakpoint.");
- for (size_t i = 0, e = List.GetSize(); i < e; ++i) {
- BreakpointSP BP = List.GetBreakpointAtIndex(i);
- P.formatLine("Breakpoint ID {0}:", BP->GetID());
- AutoIndent Indent(P, 2);
- P.formatLine("{0} location{1}.", BP->GetNumLocations(),
- plural(BP->GetNumLocations()));
- if (BP->GetNumLocations() > 0)
- P.formatLine("At least one location.");
- P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(),
- plural(BP->GetNumResolvedLocations()));
- if (BP->GetNumResolvedLocations() > 0)
- P.formatLine("At least one resolved location.");
- for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) {
- BreakpointLocationSP Loc = BP->GetLocationAtIndex(l);
- P.formatLine("Location ID {0}:", Loc->GetID());
- AutoIndent Indent(P, 2);
- P.formatLine("Enabled: {0}", Loc->IsEnabled());
- P.formatLine("Resolved: {0}", Loc->IsResolved());
- SymbolContext sc;
- Loc->GetAddress().CalculateSymbolContext(&sc);
- lldb_private::StreamString S;
- sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(),
- Loc->GetAddress(), false, true, false, true, true);
- P.formatLine("Address: {0}", S.GetString());
- }
- }
- P.NewLine();
-}
-
-std::string opts::breakpoint::substitute(StringRef Cmd) {
- std::string Result;
- raw_string_ostream OS(Result);
- while (!Cmd.empty()) {
- switch (Cmd[0]) {
- case '%':
- if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) {
- OS << sys::path::parent_path(breakpoint::CommandFile);
- break;
- }
- LLVM_FALLTHROUGH;
- default:
- size_t pos = Cmd.find('%');
- OS << Cmd.substr(0, pos);
- Cmd = Cmd.substr(pos);
- break;
- }
- }
- return std::move(OS.str());
-}
-
-int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
- TargetSP Target = opts::createTarget(Dbg, breakpoint::Target);
- std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile);
-
- LinePrinter P(4, outs());
- StringRef Rest = MB->getBuffer();
- int HadErrors = 0;
- while (!Rest.empty()) {
- StringRef Line;
- std::tie(Line, Rest) = Rest.split('\n');
- Line = Line.ltrim();
- if (Line.empty() || Line[0] == '#')
- continue;
-
- if (!Persistent)
- Target->RemoveAllBreakpoints(/*internal_also*/ true);
-
- std::string Command = substitute(Line);
- P.formatLine("Command: {0}", Command);
- CommandReturnObject Result;
- if (!Dbg.GetCommandInterpreter().HandleCommand(
- Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
- P.formatLine("Failed: {0}", Result.GetErrorData());
- HadErrors = 1;
- continue;
- }
-
- dumpState(Target->GetBreakpointList(/*internal*/ false), P);
- }
- return HadErrors;
-}
-
-Expected<CompilerDeclContext>
-opts::symbols::getDeclContext(SymbolVendor &Vendor) {
- if (Context.empty())
- return CompilerDeclContext();
- VariableList List;
- Vendor.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List);
- if (List.Empty())
- return make_string_error("Context search didn't find a match.");
- if (List.GetSize() > 1)
- return make_string_error("Context search found multiple matches.");
- return List.GetVariableAtIndex(0)->GetDeclContext();
-}
-
-Error opts::symbols::findFunctions(lldb_private::Module &Module) {
- SymbolVendor &Vendor = *Module.GetSymbolVendor();
- SymbolContextList List;
- if (!File.empty()) {
- assert(Line != 0);
-
- FileSpec src_file(File);
- size_t cu_count = Module.GetNumCompileUnits();
- for (size_t i = 0; i < cu_count; i++) {
- lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
- if (!cu_sp)
- continue;
-
- LineEntry le;
- cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
- if (!le.IsValid())
- continue;
-
- auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
- if (!addr.IsValid())
- continue;
-
- SymbolContext sc;
- uint32_t resolved =
- addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
- if (resolved & eSymbolContextFunction)
- List.Append(sc);
- }
- } else if (Regex) {
- RegularExpression RE(Name);
- assert(RE.IsValid());
- Vendor.FindFunctions(RE, true, false, List);
- } else {
- Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
- if (!ContextOr)
- return ContextOr.takeError();
- CompilerDeclContext *ContextPtr =
- ContextOr->IsValid() ? &*ContextOr : nullptr;
-
- Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
- true, false, List);
- }
- outs() << formatv("Found {0} functions:\n", List.GetSize());
- StreamString Stream;
- List.Dump(&Stream, nullptr);
- outs() << Stream.GetData() << "\n";
- return Error::success();
-}
-
-Error opts::symbols::findBlocks(lldb_private::Module &Module) {
- assert(!Regex);
- assert(!File.empty());
- assert(Line != 0);
-
- SymbolContextList List;
-
- FileSpec src_file(File);
- size_t cu_count = Module.GetNumCompileUnits();
- for (size_t i = 0; i < cu_count; i++) {
- lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
- if (!cu_sp)
- continue;
-
- LineEntry le;
- cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
- if (!le.IsValid())
- continue;
-
- auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
- if (!addr.IsValid())
- continue;
-
- SymbolContext sc;
- uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
- if (resolved & eSymbolContextBlock)
- List.Append(sc);
- }
-
- outs() << formatv("Found {0} blocks:\n", List.GetSize());
- StreamString Stream;
- List.Dump(&Stream, nullptr);
- outs() << Stream.GetData() << "\n";
- return Error::success();
-}
-
-Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
- SymbolVendor &Vendor = *Module.GetSymbolVendor();
- Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
- if (!ContextOr)
- return ContextOr.takeError();
- CompilerDeclContext *ContextPtr =
- ContextOr->IsValid() ? &*ContextOr : nullptr;
-
- CompilerDeclContext Result =
- Vendor.FindNamespace(ConstString(Name), ContextPtr);
- if (Result)
- outs() << "Found namespace: "
- << Result.GetScopeQualifiedName().GetStringRef() << "\n";
- else
- outs() << "Namespace not found.\n";
- return Error::success();
-}
-
-Error opts::symbols::findTypes(lldb_private::Module &Module) {
- SymbolVendor &Vendor = *Module.GetSymbolVendor();
- Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
- if (!ContextOr)
- return ContextOr.takeError();
- CompilerDeclContext *ContextPtr =
- ContextOr->IsValid() ? &*ContextOr : nullptr;
-
- DenseSet<SymbolFile *> SearchedFiles;
- TypeMap Map;
- Vendor.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX,
- SearchedFiles, Map);
-
- outs() << formatv("Found {0} types:\n", Map.GetSize());
- StreamString Stream;
- Map.Dump(&Stream, false);
- outs() << Stream.GetData() << "\n";
- return Error::success();
-}
-
-Error opts::symbols::findVariables(lldb_private::Module &Module) {
- SymbolVendor &Vendor = *Module.GetSymbolVendor();
- VariableList List;
- if (Regex) {
- RegularExpression RE(Name);
- assert(RE.IsValid());
- Vendor.FindGlobalVariables(RE, UINT32_MAX, List);
- } else if (!File.empty()) {
- CompUnitSP CU;
- for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) {
- CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind);
- if (!Candidate || Candidate->GetFilename().GetStringRef() != File)
- continue;
- if (CU)
- return make_string_error("Multiple compile units for file `{0}` found.",
- File);
- CU = std::move(Candidate);
- }
-
- if (!CU)
- return make_string_error("Compile unit `{0}` not found.", File);
-
- List.AddVariables(CU->GetVariableList(true).get());
- } else {
- Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
- if (!ContextOr)
- return ContextOr.takeError();
- CompilerDeclContext *ContextPtr =
- ContextOr->IsValid() ? &*ContextOr : nullptr;
-
- Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List);
- }
- outs() << formatv("Found {0} variables:\n", List.GetSize());
- StreamString Stream;
- List.Dump(&Stream, false);
- outs() << Stream.GetData() << "\n";
- return Error::success();
-}
-
-Error opts::symbols::dumpModule(lldb_private::Module &Module) {
- StreamString Stream;
- Module.ParseAllDebugSymbols();
- Module.Dump(&Stream);
- outs() << Stream.GetData() << "\n";
- return Error::success();
-}
-
-Error opts::symbols::dumpAST(lldb_private::Module &Module) {
- SymbolVendor &plugin = *Module.GetSymbolVendor();
- Module.ParseAllDebugSymbols();
-
- auto symfile = plugin.GetSymbolFile();
- if (!symfile)
- return make_string_error("Module has no symbol file.");
-
- auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
- symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
- if (!clang_ast_ctx)
- return make_string_error("Can't retrieve Clang AST context.");
-
- auto ast_ctx = clang_ast_ctx->getASTContext();
- if (!ast_ctx)
- return make_string_error("Can't retrieve AST context.");
-
- auto tu = ast_ctx->getTranslationUnitDecl();
- if (!tu)
- return make_string_error("Can't retrieve translation unit declaration.");
-
- tu->print(outs());
-
- return Error::success();
-}
-
-Error opts::symbols::verify(lldb_private::Module &Module) {
- SymbolVendor &plugin = *Module.GetSymbolVendor();
-
- SymbolFile *symfile = plugin.GetSymbolFile();
- if (!symfile)
- return make_string_error("Module has no symbol file.");
-
- uint32_t comp_units_count = symfile->GetNumCompileUnits();
-
- outs() << "Found " << comp_units_count << " compile units.\n";
-
- for (uint32_t i = 0; i < comp_units_count; i++) {
- lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
- if (!comp_unit)
- return make_string_error("Connot parse compile unit {0}.", i);
-
- outs() << "Processing '" << comp_unit->GetFilename().AsCString()
- << "' compile unit.\n";
-
- LineTable *lt = comp_unit->GetLineTable();
- if (!lt)
- return make_string_error("Can't get a line table of a compile unit.");
-
- uint32_t count = lt->GetSize();
-
- outs() << "The line table contains " << count << " entries.\n";
-
- if (count == 0)
- continue;
-
- LineEntry le;
- if (!lt->GetLineEntryAtIndex(0, le))
- return make_string_error("Can't get a line entry of a compile unit.");
-
- for (uint32_t i = 1; i < count; i++) {
- lldb::addr_t curr_end =
- le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
-
- if (!lt->GetLineEntryAtIndex(i, le))
- return make_string_error("Can't get a line entry of a compile unit");
-
- if (curr_end > le.range.GetBaseAddress().GetFileAddress())
- return make_string_error(
- "Line table of a compile unit is inconsistent.");
- }
- }
-
- outs() << "The symbol information is verified.\n";
-
- return Error::success();
-}
-
-Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
- if (Verify && DumpAST)
- return make_string_error(
- "Cannot both verify symbol information and dump AST.");
-
- if (Verify) {
- if (Find != FindType::None)
- return make_string_error(
- "Cannot both search and verify symbol information.");
- if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
- Line != 0)
- return make_string_error(
- "-regex, -context, -name, -file and -line options are not "
- "applicable for symbol verification.");
- return verify;
- }
-
- if (DumpAST) {
- if (Find != FindType::None)
- return make_string_error("Cannot both search and dump AST.");
- if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
- Line != 0)
- return make_string_error(
- "-regex, -context, -name, -file and -line options are not "
- "applicable for dumping AST.");
- return dumpAST;
- }
-
- if (Regex && !Context.empty())
- return make_string_error(
- "Cannot search using both regular expressions and context.");
-
- if (Regex && !RegularExpression(Name).IsValid())
- return make_string_error("`{0}` is not a valid regular expression.", Name);
-
- if (Regex + !Context.empty() + !File.empty() >= 2)
- return make_string_error(
- "Only one of -regex, -context and -file may be used simultaneously.");
- if (Regex && Name.empty())
- return make_string_error("-regex used without a -name");
-
- switch (Find) {
- case FindType::None:
- if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
- return make_string_error(
- "Specify search type (-find) to use search options.");
- return dumpModule;
-
- case FindType::Function:
- if (!File.empty() + (Line != 0) == 1)
- return make_string_error("Both file name and line number must be "
- "specified when searching a function "
- "by file position.");
- if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
- return make_string_error("Only one of regular expression, function-flags "
- "and file position may be used simultaneously "
- "when searching a function.");
- return findFunctions;
-
- case FindType::Block:
- if (File.empty() || Line == 0)
- return make_string_error("Both file name and line number must be "
- "specified when searching a block.");
- if (Regex || getFunctionNameFlags() != 0)
- return make_string_error("Cannot use regular expression or "
- "function-flags for searching a block.");
- return findBlocks;
-
- case FindType::Namespace:
- if (Regex || !File.empty() || Line != 0)
- return make_string_error("Cannot search for namespaces using regular "
- "expressions, file names or line numbers.");
- return findNamespaces;
-
- case FindType::Type:
- if (Regex || !File.empty() || Line != 0)
- return make_string_error("Cannot search for types using regular "
- "expressions, file names or line numbers.");
- return findTypes;
-
- case FindType::Variable:
- if (Line != 0)
- return make_string_error("Cannot search for variables "
- "using line numbers.");
- return findVariables;
- }
-
- llvm_unreachable("Unsupported symbol action.");
-}
-
-int opts::symbols::dumpSymbols(Debugger &Dbg) {
- auto ActionOr = getAction();
- if (!ActionOr) {
- logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), "");
- return 1;
- }
- auto Action = *ActionOr;
-
- outs() << "Module: " << InputFile << "\n";
- ModuleSpec Spec{FileSpec(InputFile)};
- StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
- Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
-
- auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
- SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
- if (!Vendor) {
- WithColor::error() << "Module has no symbol vendor.\n";
- return 1;
- }
-
- if (Error E = Action(*ModulePtr)) {
- WithColor::error() << toString(std::move(E)) << "\n";
- return 1;
- }
-
- return 0;
-}
-
-static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
- size_t Count = List.GetNumSections(0);
- if (Count == 0) {
- Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
- return;
- }
- Printer.formatLine("Showing {0} {1}sections", Count,
- is_subsection ? "sub" : "");
- for (size_t I = 0; I < Count; ++I) {
- auto S = List.GetSectionAtIndex(I);
- assert(S);
- AutoIndent Indent(Printer, 2);
- Printer.formatLine("Index: {0}", I);
- Printer.formatLine("ID: {0:x}", S->GetID());
- Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
- Printer.formatLine("Type: {0}", S->GetTypeAsCString());
- Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
- Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
- Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
- Printer.formatLine("VM size: {0}", S->GetByteSize());
- Printer.formatLine("File size: {0}", S->GetFileSize());
-
- if (opts::object::SectionContents) {
- DataExtractor Data;
- S->GetSectionData(Data);
- ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
- Printer.formatBinary("Data: ", Bytes, 0);
- }
-
- if (S->GetType() == eSectionTypeContainer)
- dumpSectionList(Printer, S->GetChildren(), true);
- Printer.NewLine();
- }
-}
-
-static int dumpObjectFiles(Debugger &Dbg) {
- LinePrinter Printer(4, llvm::outs());
-
- int HadErrors = 0;
- for (const auto &File : opts::object::InputFilenames) {
- ModuleSpec Spec{FileSpec(File)};
-
- auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
-
- ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
- if (!ObjectPtr) {
- WithColor::error() << File << " not recognised as an object file\n";
- HadErrors = 1;
- continue;
- }
-
- // Fetch symbol vendor before we get the section list to give the symbol
- // vendor a chance to populate it.
- ModulePtr->GetSymbolVendor();
- SectionList *Sections = ModulePtr->GetSectionList();
- if (!Sections) {
- llvm::errs() << "Could not load sections for module " << File << "\n";
- HadErrors = 1;
- continue;
- }
-
- Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
- Printer.formatLine("Architecture: {0}",
- ModulePtr->GetArchitecture().GetTriple().getTriple());
- Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
- Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
- Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
- Printer.formatLine("Type: {0}", ObjectPtr->GetType());
- Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
- Printer.formatLine("Base VM address: {0:x}",
- ObjectPtr->GetBaseAddress().GetFileAddress());
-
- dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
-
- if (opts::object::SectionDependentModules) {
- // A non-empty section list ensures a valid object file.
- auto Obj = ModulePtr->GetObjectFile();
- FileSpecList Files;
- auto Count = Obj->GetDependentModules(Files);
- Printer.formatLine("Showing {0} dependent module(s)", Count);
- for (size_t I = 0; I < Files.GetSize(); ++I) {
- AutoIndent Indent(Printer, 2);
- Printer.formatLine("Name: {0}",
- Files.GetFileSpecAtIndex(I).GetCString());
- }
- Printer.NewLine();
- }
- }
- return HadErrors;
-}
-
-bool opts::irmemorymap::evalMalloc(StringRef Line,
- IRMemoryMapTestState &State) {
- // ::= <label> = malloc <size> <alignment>
- StringRef Label;
- std::tie(Label, Line) = Line.split('=');
- if (Line.empty())
- return false;
- Label = Label.trim();
- Line = Line.trim();
- size_t Size;
- uint8_t Alignment;
- int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment);
- if (Matches != 2)
- return false;
-
- outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label,
- Size, Alignment);
- if (!isPowerOf2_32(Alignment)) {
- outs() << "Malloc error: alignment is not a power of 2\n";
- exit(1);
- }
-
- IRMemoryMap::AllocationPolicy AP =
- UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly
- : IRMemoryMap::eAllocationPolicyProcessOnly;
-
- // Issue the malloc in the target process with "-rw" permissions.
- const uint32_t Permissions = 0x3;
- const bool ZeroMemory = false;
- Status ST;
- addr_t Addr =
- State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST);
- if (ST.Fail()) {
- outs() << formatv("Malloc error: {0}\n", ST);
- return true;
- }
-
- // Print the result of the allocation before checking its validity.
- outs() << formatv("Malloc: address = {0:x}\n", Addr);
-
- // Check that the allocation is aligned.
- if (!Addr || Addr % Alignment != 0) {
- outs() << "Malloc error: zero or unaligned allocation detected\n";
- exit(1);
- }
-
- // In case of Size == 0, we still expect the returned address to be unique and
- // non-overlapping.
- addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
- if (State.Allocations.overlaps(Addr, EndOfRegion)) {
- auto I = State.Allocations.find(Addr);
- outs() << "Malloc error: overlapping allocation detected"
- << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
- I.stop());
- exit(1);
- }
-
- // Insert the new allocation into the interval map. Use unique allocation
- // IDs to inhibit interval coalescing.
- static unsigned AllocationID = 0;
- State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
-
- // Store the label -> address mapping.
- State.Label2AddrMap[Label] = Addr;
-
- return true;
-}
-
-bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) {
- // ::= free <label>
- if (!Line.consume_front("free"))
- return false;
- StringRef Label = Line.trim();
-
- outs() << formatv("Command: free({0})\n", Label);
- auto LabelIt = State.Label2AddrMap.find(Label);
- if (LabelIt == State.Label2AddrMap.end()) {
- outs() << "Free error: Invalid allocation label\n";
- exit(1);
- }
-
- Status ST;
- addr_t Addr = LabelIt->getValue();
- State.Map.Free(Addr, ST);
- if (ST.Fail()) {
- outs() << formatv("Free error: {0}\n", ST);
- exit(1);
- }
-
- // Erase the allocation from the live interval map.
- auto Interval = State.Allocations.find(Addr);
- if (Interval != State.Allocations.end()) {
- outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(),
- Interval.stop());
- Interval.erase();
- }
-
- return true;
-}
-
-int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
- // Set up a Target.
- TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target);
-
- // Set up a Process. In order to allocate memory within a target, this
- // process must be alive and must support JIT'ing.
- CommandReturnObject Result;
- Dbg.SetAsyncExecution(false);
- CommandInterpreter &CI = Dbg.GetCommandInterpreter();
- auto IssueCmd = [&](const char *Cmd) -> bool {
- return CI.HandleCommand(Cmd, eLazyBoolNo, Result);
- };
- if (!IssueCmd("b main") || !IssueCmd("run")) {
- outs() << formatv("Failed: {0}\n", Result.GetErrorData());
- exit(1);
- }
-
- ProcessSP Process = Target->GetProcessSP();
- if (!Process || !Process->IsAlive() || !Process->CanJIT()) {
- outs() << "Cannot use process to test IRMemoryMap\n";
- exit(1);
- }
-
- // Set up an IRMemoryMap and associated testing state.
- IRMemoryMapTestState State(Target);
-
- // Parse and apply commands from the command file.
- std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile);
- StringRef Rest = MB->getBuffer();
- while (!Rest.empty()) {
- StringRef Line;
- std::tie(Line, Rest) = Rest.split('\n');
- Line = Line.ltrim();
-
- if (Line.empty() || Line[0] == '#')
- continue;
-
- if (evalMalloc(Line, State))
- continue;
-
- if (evalFree(Line, State))
- continue;
-
- errs() << "Could not parse line: " << Line << "\n";
- exit(1);
- }
- return 0;
-}
-
-int main(int argc, const char *argv[]) {
- StringRef ToolName = argv[0];
- sys::PrintStackTraceOnErrorSignal(ToolName);
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y;
-
- cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
-
- SystemLifetimeManager DebuggerLifetime;
- if (auto e = DebuggerLifetime.Initialize(
- llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) {
- WithColor::error() << "initialization failed: " << toString(std::move(e))
- << '\n';
- return 1;
- }
-
- CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
-
- auto Dbg = lldb_private::Debugger::CreateInstance();
-
- if (!opts::Log.empty())
- Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs());
-
- if (opts::BreakpointSubcommand)
- return opts::breakpoint::evaluateBreakpoints(*Dbg);
- if (opts::ObjectFileSubcommand)
- return dumpObjectFiles(*Dbg);
- if (opts::SymbolsSubcommand)
- return opts::symbols::dumpSymbols(*Dbg);
- if (opts::IRMemoryMapSubcommand)
- return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg);
-
- WithColor::error() << "No command specified.\n";
- return 1;
-}