summaryrefslogtreecommitdiffstats
path: root/lldb/tools/lldb-test/lldb-test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/lldb-test/lldb-test.cpp')
-rw-r--r--lldb/tools/lldb-test/lldb-test.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 1fe2f5b6385..502e555dd7c 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -11,10 +11,13 @@
#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/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/Utility/DataExtractor.h"
@@ -23,6 +26,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include <thread>
@@ -32,10 +36,30 @@ using namespace lldb_private;
using namespace llvm;
namespace opts {
+static cl::SubCommand BreakpointSubcommand("breakpoints",
+ "Test breakpoint resolution");
cl::SubCommand ModuleSubcommand("module-sections",
"Display LLDB Module Information");
cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file");
+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 void evaluateBreakpoints(Debugger &Dbg);
+} // namespace breakpoint
+
namespace module {
cl::opt<bool> SectionContents("contents",
cl::desc("Dump each section's contents"),
@@ -52,6 +76,101 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
static llvm::ManagedStatic<SystemLifetimeManager> DebuggerLifetime;
+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());
+ P.formatLine("Address: {0}+{1:x}",
+ Loc->GetAddress().GetSection()->GetName(),
+ Loc->GetAddress().GetOffset());
+ }
+ }
+ 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(CommandFile);
+ break;
+ }
+ // fall through
+ default:
+ size_t pos = Cmd.find('%');
+ OS << Cmd.substr(0, pos);
+ Cmd = Cmd.substr(pos);
+ break;
+ }
+ }
+ return std::move(OS.str());
+}
+
+void opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
+ TargetSP Target;
+ Status ST =
+ Dbg.GetTargetList().CreateTarget(Dbg, breakpoint::Target, /*triple*/ "",
+ /*get_dependent_modules*/ false,
+ /*platform_options*/ nullptr, Target);
+ if (ST.Fail()) {
+ errs() << formatv("Failed to create target '{0}: {1}\n", breakpoint::Target,
+ ST);
+ exit(1);
+ }
+
+ auto MB = MemoryBuffer::getFileOrSTDIN(CommandFile);
+ if (!MB) {
+ errs() << formatv("Could not open file '{0}: {1}\n", CommandFile,
+ MB.getError().message());
+ exit(1);
+ }
+
+ LinePrinter P(4, outs());
+ 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 (!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());
+ continue;
+ }
+
+ dumpState(Target->GetBreakpointList(/*internal*/ false), P);
+ }
+}
+
static void dumpSymbols(Debugger &Dbg) {
for (const auto &File : opts::symbols::InputFilenames) {
ModuleSpec Spec{FileSpec(File, false)};
@@ -116,6 +235,8 @@ int main(int argc, const char *argv[]) {
auto Dbg = lldb_private::Debugger::CreateInstance();
+ if (opts::BreakpointSubcommand)
+ opts::breakpoint::evaluateBreakpoints(*Dbg);
if (opts::ModuleSubcommand)
dumpModules(*Dbg);
else if (opts::SymbolsSubcommand)
OpenPOWER on IntegriCloud