aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-06-13 19:31:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-06-13 19:37:19 +0000
commite8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch)
tree94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp
parentbb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff)
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp608
1 files changed, 365 insertions, 243 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp
index 7bb71f4d518c..1cb21384fd2a 100644
--- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp
@@ -23,6 +23,8 @@
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
+#include "lldb/Interpreter/OptionGroupPlatform.h"
+#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionGroupUUID.h"
@@ -48,6 +50,7 @@
#include "lldb/Utility/State.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
@@ -206,8 +209,6 @@ private:
#pragma mark CommandObjectTargetCreate
-// "target create"
-
class CommandObjectTargetCreate : public CommandObjectParsed {
public:
CommandObjectTargetCreate(CommandInterpreter &interpreter)
@@ -216,11 +217,9 @@ public:
"Create a target using the argument as the main executable.",
nullptr),
m_option_group(), m_arch_option(),
+ m_platform_options(true), // Include the --platform option.
m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
"Fullpath to a core file to use for this target."),
- m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
- eArgTypePath,
- "Path to the remote file to use for this target."),
m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
eArgTypeFilename,
"Fullpath to a stand alone debug "
@@ -245,8 +244,8 @@ public:
m_arguments.push_back(arg);
m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
@@ -300,8 +299,7 @@ protected:
}
const char *file_path = command.GetArgumentAtIndex(0);
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
+ LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path);
FileSpec file_spec;
if (file_path) {
@@ -317,124 +315,127 @@ protected:
llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
Status error(debugger.GetTargetList().CreateTarget(
debugger, file_path, arch_cstr,
- m_add_dependents.m_load_dependent_files, nullptr, target_sp));
+ m_add_dependents.m_load_dependent_files, &m_platform_options,
+ target_sp));
- if (target_sp) {
- // Only get the platform after we create the target because we might
- // have switched platforms depending on what the arguments were to
- // CreateTarget() we can't rely on the selected platform.
-
- PlatformSP platform_sp = target_sp->GetPlatform();
-
- if (remote_file) {
- if (platform_sp) {
- // I have a remote file.. two possible cases
- if (file_spec && FileSystem::Instance().Exists(file_spec)) {
- // if the remote file does not exist, push it there
- if (!platform_sp->GetFileExists(remote_file)) {
- Status err = platform_sp->PutFile(file_spec, remote_file);
- if (err.Fail()) {
- result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- } else {
- // there is no local file and we need one
- // in order to make the remote ---> local transfer we need a
- // platform
- // TODO: if the user has passed in a --platform argument, use it
- // to fetch the right platform
- if (!platform_sp) {
- result.AppendError(
- "unable to perform remote debugging without a platform");
+ if (!target_sp) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ auto on_error = llvm::make_scope_exit(
+ [&target_list = debugger.GetTargetList(), &target_sp]() {
+ target_list.DeleteTarget(target_sp);
+ });
+
+ // Only get the platform after we create the target because we might
+ // have switched platforms depending on what the arguments were to
+ // CreateTarget() we can't rely on the selected platform.
+
+ PlatformSP platform_sp = target_sp->GetPlatform();
+
+ if (remote_file) {
+ if (platform_sp) {
+ // I have a remote file.. two possible cases
+ if (file_spec && FileSystem::Instance().Exists(file_spec)) {
+ // if the remote file does not exist, push it there
+ if (!platform_sp->GetFileExists(remote_file)) {
+ Status err = platform_sp->PutFile(file_spec, remote_file);
+ if (err.Fail()) {
+ result.AppendError(err.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
}
- if (file_path) {
- // copy the remote file to the local file
- Status err = platform_sp->GetFile(remote_file, file_spec);
- if (err.Fail()) {
- result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- } else {
- // make up a local file
- result.AppendError("remote --> local transfer without local "
- "path is not implemented yet");
+ }
+ } else {
+ // there is no local file and we need one
+ // in order to make the remote ---> local transfer we need a
+ // platform
+ // TODO: if the user has passed in a --platform argument, use it
+ // to fetch the right platform
+ if (file_path) {
+ // copy the remote file to the local file
+ Status err = platform_sp->GetFile(remote_file, file_spec);
+ if (err.Fail()) {
+ result.AppendError(err.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
}
+ } else {
+ // make up a local file
+ result.AppendError("remote --> local transfer without local "
+ "path is not implemented yet");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- } else {
- result.AppendError("no platform found for target");
- result.SetStatus(eReturnStatusFailed);
- return false;
}
+ } else {
+ result.AppendError("no platform found for target");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
+ }
- if (symfile || remote_file) {
- ModuleSP module_sp(target_sp->GetExecutableModule());
- if (module_sp) {
- if (symfile)
- module_sp->SetSymbolFileFileSpec(symfile);
- if (remote_file) {
- std::string remote_path = remote_file.GetPath();
- target_sp->SetArg0(remote_path.c_str());
- module_sp->SetPlatformFileSpec(remote_file);
- }
+ if (symfile || remote_file) {
+ ModuleSP module_sp(target_sp->GetExecutableModule());
+ if (module_sp) {
+ if (symfile)
+ module_sp->SetSymbolFileFileSpec(symfile);
+ if (remote_file) {
+ std::string remote_path = remote_file.GetPath();
+ target_sp->SetArg0(remote_path.c_str());
+ module_sp->SetPlatformFileSpec(remote_file);
}
}
+ }
- debugger.GetTargetList().SetSelectedTarget(target_sp.get());
- if (must_set_platform_path) {
- ModuleSpec main_module_spec(file_spec);
- ModuleSP module_sp =
- target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
- if (module_sp)
- module_sp->SetPlatformFileSpec(remote_file);
- }
+ if (must_set_platform_path) {
+ ModuleSpec main_module_spec(file_spec);
+ ModuleSP module_sp =
+ target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(remote_file);
+ }
- if (core_file) {
- FileSpec core_file_dir;
- core_file_dir.GetDirectory() = core_file.GetDirectory();
- target_sp->AppendExecutableSearchPaths(core_file_dir);
+ if (core_file) {
+ FileSpec core_file_dir;
+ core_file_dir.GetDirectory() = core_file.GetDirectory();
+ target_sp->AppendExecutableSearchPaths(core_file_dir);
- ProcessSP process_sp(target_sp->CreateProcess(
- GetDebugger().GetListener(), llvm::StringRef(), &core_file));
+ ProcessSP process_sp(target_sp->CreateProcess(
+ GetDebugger().GetListener(), llvm::StringRef(), &core_file, false));
- if (process_sp) {
- // Seems weird that we Launch a core file, but that is what we
- // do!
- error = process_sp->LoadCore();
+ if (process_sp) {
+ // Seems weird that we Launch a core file, but that is what we
+ // do!
+ error = process_sp->LoadCore();
- if (error.Fail()) {
- result.AppendError(
- error.AsCString("can't find plug-in for core file"));
- result.SetStatus(eReturnStatusFailed);
- return false;
- } else {
- result.AppendMessageWithFormatv("Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
- target_sp->GetArchitecture().GetArchitectureName());
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- }
- } else {
- result.AppendErrorWithFormatv(
- "Unable to find process plug-in for core file '{0}'\n",
- core_file.GetPath());
+ if (error.Fail()) {
+ result.AppendError(
+ error.AsCString("can't find plug-in for core file"));
result.SetStatus(eReturnStatusFailed);
+ return false;
+ } else {
+ result.AppendMessageWithFormatv(
+ "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
+ target_sp->GetArchitecture().GetArchitectureName());
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ on_error.release();
}
} else {
- result.AppendMessageWithFormat(
- "Current executable set to '%s' (%s).\n",
- file_spec.GetPath().c_str(),
- target_sp->GetArchitecture().GetArchitectureName());
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ result.AppendErrorWithFormatv(
+ "Unable to find process plug-in for core file '{0}'\n",
+ core_file.GetPath());
+ result.SetStatus(eReturnStatusFailed);
}
} else {
- result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
+ result.AppendMessageWithFormat(
+ "Current executable set to '%s' (%s).\n",
+ file_spec.GetPath().c_str(),
+ target_sp->GetArchitecture().GetArchitectureName());
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ on_error.release();
}
} else {
result.AppendErrorWithFormat("'%s' takes exactly one executable path "
@@ -442,14 +443,15 @@ protected:
m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
}
+
return result.Succeeded();
}
private:
OptionGroupOptions m_option_group;
OptionGroupArchitecture m_arch_option;
+ OptionGroupPlatform m_platform_options;
OptionGroupFile m_core_file;
- OptionGroupFile m_platform_path;
OptionGroupFile m_symbol_file;
OptionGroupFile m_remote_file;
OptionGroupDependents m_add_dependents;
@@ -457,8 +459,6 @@ private:
#pragma mark CommandObjectTargetList
-// "target list"
-
class CommandObjectTargetList : public CommandObjectParsed {
public:
CommandObjectTargetList(CommandInterpreter &interpreter)
@@ -490,8 +490,6 @@ protected:
#pragma mark CommandObjectTargetSelect
-// "target select"
-
class CommandObjectTargetSelect : public CommandObjectParsed {
public:
CommandObjectTargetSelect(CommandInterpreter &interpreter)
@@ -511,18 +509,11 @@ protected:
TargetList &target_list = GetDebugger().GetTargetList();
const uint32_t num_targets = target_list.GetNumTargets();
if (target_idx < num_targets) {
- TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
- if (target_sp) {
- Stream &strm = result.GetOutputStream();
- target_list.SetSelectedTarget(target_sp.get());
- bool show_stopped_process_status = false;
- DumpTargetList(target_list, show_stopped_process_status, strm);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- } else {
- result.AppendErrorWithFormat("target #%u is NULL in target list\n",
- target_idx);
- result.SetStatus(eReturnStatusFailed);
- }
+ target_list.SetSelectedTarget(target_idx);
+ Stream &strm = result.GetOutputStream();
+ bool show_stopped_process_status = false;
+ DumpTargetList(target_list, show_stopped_process_status, strm);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
if (num_targets > 0) {
result.AppendErrorWithFormat(
@@ -551,8 +542,6 @@ protected:
#pragma mark CommandObjectTargetDelete
-// "target delete"
-
class CommandObjectTargetDelete : public CommandObjectParsed {
public:
CommandObjectTargetDelete(CommandInterpreter &interpreter)
@@ -697,8 +686,6 @@ protected:
#pragma mark CommandObjectTargetVariable
-// "target variable"
-
class CommandObjectTargetVariable : public CommandObjectParsed {
static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
@@ -917,6 +904,7 @@ protected:
CompileUnit *comp_unit = nullptr;
if (frame) {
SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
+ comp_unit = sc.comp_unit;
if (sc.comp_unit) {
const bool can_create = true;
VariableListSP comp_unit_varlist_sp(
@@ -1167,6 +1155,25 @@ public:
~CommandObjectTargetModulesSearchPathsInsert() override = default;
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ if (!m_exe_ctx.HasTargetScope() || request.GetCursorIndex() != 0)
+ return;
+
+ Target *target = m_exe_ctx.GetTargetPtr();
+ const PathMappingList &list = target->GetImageSearchPathList();
+ const size_t num = list.GetSize();
+ ConstString old_path, new_path;
+ for (size_t i = 0; i < num; ++i) {
+ if (!list.GetPathsAtIndex(i, old_path, new_path))
+ break;
+ StreamString strm;
+ strm << old_path << " -> " << new_path;
+ request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
+ }
+ }
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target *target = &GetSelectedTarget();
@@ -1392,31 +1399,30 @@ static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
}
static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
- size_t num_dumped = 0;
std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
const size_t num_modules = module_list.GetSize();
- if (num_modules > 0) {
- strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
- static_cast<uint64_t>(num_modules));
- strm.IndentMore();
- for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
- Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
- if (module) {
- if (num_dumped++ > 0) {
- strm.EOL();
- strm.EOL();
- }
- ObjectFile *objfile = module->GetObjectFile();
- if (objfile)
- objfile->Dump(&strm);
- else {
- strm.Format("No object file for module: {0:F}\n",
- module->GetFileSpec());
- }
+ if (num_modules == 0)
+ return 0;
+
+ size_t num_dumped = 0;
+ strm.Format("Dumping headers for {0} module(s).\n", num_modules);
+ strm.IndentMore();
+ for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
+ if (module_sp) {
+ if (num_dumped++ > 0) {
+ strm.EOL();
+ strm.EOL();
+ }
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile)
+ objfile->Dump(&strm);
+ else {
+ strm.Format("No object file for module: {0:F}\n",
+ module_sp->GetFileSpec());
}
}
- strm.IndentLess();
}
+ strm.IndentLess();
return num_dumped;
}
@@ -1624,7 +1630,8 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
return 0;
}
-static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
+static size_t LookupTypeInModule(Target *target,
+ CommandInterpreter &interpreter, Stream &strm,
Module *module, const char *name_cstr,
bool name_is_regex) {
TypeList type_list;
@@ -1652,7 +1659,7 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
// Resolve the clang type so that any forward references to types
// that haven't yet been parsed will get parsed.
type_sp->GetFullCompilerType();
- type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
+ type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
// Print all typedef chains
TypeSP typedef_type_sp(type_sp);
TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
@@ -1661,7 +1668,8 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
strm.Printf(" typedef '%s': ",
typedef_type_sp->GetName().GetCString());
typedefed_type_sp->GetFullCompilerType();
- typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
+ typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
+ target);
typedef_type_sp = typedefed_type_sp;
typedefed_type_sp = typedef_type_sp->GetTypedefType();
}
@@ -1671,9 +1679,9 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
return type_list.GetSize();
}
-static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
- Module &module, const char *name_cstr,
- bool name_is_regex) {
+static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
+ Stream &strm, Module &module,
+ const char *name_cstr, bool name_is_regex) {
TypeList type_list;
const uint32_t max_num_matches = UINT32_MAX;
bool name_is_fully_qualified = false;
@@ -1696,8 +1704,8 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
// Resolve the clang type so that any forward references to types that
// haven't yet been parsed will get parsed.
type_sp->GetFullCompilerType();
- type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
- // Print all typedef chains
+ type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
+ // Print all typedef chains.
TypeSP typedef_type_sp(type_sp);
TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
while (typedefed_type_sp) {
@@ -1705,7 +1713,8 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
strm.Printf(" typedef '%s': ",
typedef_type_sp->GetName().GetCString());
typedefed_type_sp->GetFullCompilerType();
- typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
+ typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
+ target);
typedef_type_sp = typedefed_type_sp;
typedefed_type_sp = typedef_type_sp->GetTypedefType();
}
@@ -2015,14 +2024,13 @@ protected:
if (command.GetArgumentCount() == 0) {
// Dump all sections for all modules images
- std::lock_guard<std::recursive_mutex> guard(
- target->GetImages().GetMutex());
- const size_t num_modules = target->GetImages().GetSize();
+ const ModuleList &module_list = target->GetImages();
+ std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
+ const size_t num_modules = module_list.GetSize();
if (num_modules > 0) {
- result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
- " modules.\n",
- (uint64_t)num_modules);
- for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ result.GetOutputStream().Format(
+ "Dumping symbol table for {0} modules.\n", num_modules);
+ for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
if (num_dumped > 0) {
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
@@ -2030,10 +2038,9 @@ protected:
if (m_interpreter.WasInterrupted())
break;
num_dumped++;
- DumpModuleSymtab(
- m_interpreter, result.GetOutputStream(),
- target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
- m_options.m_sort_order, name_preference);
+ DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
+ module_sp.get(), m_options.m_sort_order,
+ name_preference);
}
} else {
result.AppendError("the target has no associated executable images");
@@ -2050,9 +2057,8 @@ protected:
const size_t num_matches =
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
- for (size_t i = 0; i < num_matches; ++i) {
- Module *module = module_list.GetModulePointerAtIndex(i);
- if (module) {
+ for (ModuleSP module_sp : module_list.Modules()) {
+ if (module_sp) {
if (num_dumped > 0) {
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
@@ -2060,8 +2066,9 @@ protected:
if (m_interpreter.WasInterrupted())
break;
num_dumped++;
- DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module,
- m_options.m_sort_order, name_preference);
+ DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
+ module_sp.get(), m_options.m_sort_order,
+ name_preference);
}
}
} else
@@ -2110,23 +2117,22 @@ protected:
if (command.GetArgumentCount() == 0) {
// Dump all sections for all modules images
const size_t num_modules = target->GetImages().GetSize();
- if (num_modules > 0) {
- result.GetOutputStream().Printf("Dumping sections for %" PRIu64
- " modules.\n",
- (uint64_t)num_modules);
- for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
- if (m_interpreter.WasInterrupted())
- break;
- num_dumped++;
- DumpModuleSections(
- m_interpreter, result.GetOutputStream(),
- target->GetImages().GetModulePointerAtIndex(image_idx));
- }
- } else {
+ if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
result.SetStatus(eReturnStatusFailed);
return false;
}
+
+ result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
+ num_modules);
+ for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ if (m_interpreter.WasInterrupted())
+ break;
+ num_dumped++;
+ DumpModuleSections(
+ m_interpreter, result.GetOutputStream(),
+ target->GetImages().GetModulePointerAtIndex(image_idx));
+ }
} else {
// Dump specified images (by basename or fullpath)
const char *arg_cstr;
@@ -2188,7 +2194,8 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target *target = &GetSelectedTarget();
- const size_t num_modules = target->GetImages().GetSize();
+ const ModuleList &module_list = target->GetImages();
+ const size_t num_modules = module_list.GetSize();
if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
result.SetStatus(eReturnStatusFailed);
@@ -2197,14 +2204,12 @@ protected:
if (command.GetArgumentCount() == 0) {
// Dump all ASTs for all modules images
- result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
- " modules.\n",
- (uint64_t)num_modules);
- for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n",
+ num_modules);
+ for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
if (m_interpreter.WasInterrupted())
break;
- Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
- if (SymbolFile *sf = m->GetSymbolFile())
+ if (SymbolFile *sf = module_sp->GetSymbolFile())
sf->DumpClangAST(result.GetOutputStream());
}
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -2269,23 +2274,19 @@ protected:
const ModuleList &target_modules = target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
- if (num_modules > 0) {
- result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
- " modules.\n",
- (uint64_t)num_modules);
- for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
- if (m_interpreter.WasInterrupted())
- break;
- if (DumpModuleSymbolFile(
- result.GetOutputStream(),
- target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
- num_dumped++;
- }
- } else {
+ if (num_modules == 0) {
result.AppendError("the target has no associated executable images");
result.SetStatus(eReturnStatusFailed);
return false;
}
+ result.GetOutputStream().Format(
+ "Dumping debug symbols for {0} modules.\n", num_modules);
+ for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
+ if (m_interpreter.WasInterrupted())
+ break;
+ if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get()))
+ num_dumped++;
+ }
} else {
// Dump specified images (by basename or fullpath)
const char *arg_cstr;
@@ -2363,15 +2364,13 @@ protected:
const ModuleList &target_modules = target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- const size_t num_modules = target_modules.GetSize();
- if (num_modules > 0) {
+ if (target_modules.GetSize() > 0) {
uint32_t num_dumped = 0;
- for (uint32_t i = 0; i < num_modules; ++i) {
+ for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
if (m_interpreter.WasInterrupted())
break;
if (DumpCompileUnitLineTable(
- m_interpreter, result.GetOutputStream(),
- target_modules.GetModulePointerAtIndexUnlocked(i),
+ m_interpreter, result.GetOutputStream(), module_sp.get(),
file_spec,
m_options.m_verbose ? eDescriptionLevelFull
: eDescriptionLevelBrief))
@@ -3409,10 +3408,35 @@ protected:
continue;
result.GetOutputStream().Printf(
- "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
+ "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n",
sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
funcname.AsCString(), start_addr);
+ Args args;
+ target->GetUserSpecifiedTrapHandlerNames(args);
+ size_t count = args.GetArgumentCount();
+ for (size_t i = 0; i < count; i++) {
+ const char *trap_func_name = args.GetArgumentAtIndex(i);
+ if (strcmp(funcname.GetCString(), trap_func_name) == 0)
+ result.GetOutputStream().Printf(
+ "This function is "
+ "treated as a trap handler function via user setting.\n");
+ }
+ PlatformSP platform_sp(target->GetPlatform());
+ if (platform_sp) {
+ const std::vector<ConstString> trap_handler_names(
+ platform_sp->GetTrapHandlerSymbolNames());
+ for (ConstString trap_name : trap_handler_names) {
+ if (trap_name == funcname) {
+ result.GetOutputStream().Printf(
+ "This function's "
+ "name is listed by the platform as a trap handler.\n");
+ }
+ }
+ }
+
+ result.GetOutputStream().Printf("\n");
+
UnwindPlanSP non_callsite_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
if (non_callsite_unwind_plan) {
@@ -3745,9 +3769,9 @@ public:
return false;
case eLookupTypeType:
if (!m_options.m_str.empty()) {
- if (LookupTypeHere(m_interpreter, result.GetOutputStream(),
- *sym_ctx.module_sp, m_options.m_str.c_str(),
- m_options.m_use_regex)) {
+ if (LookupTypeHere(&GetSelectedTarget(), m_interpreter,
+ result.GetOutputStream(), *sym_ctx.module_sp,
+ m_options.m_str.c_str(), m_options.m_use_regex)) {
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
@@ -3817,9 +3841,9 @@ public:
case eLookupTypeType:
if (!m_options.m_str.empty()) {
- if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
- m_options.m_str.c_str(),
- m_options.m_use_regex)) {
+ if (LookupTypeInModule(
+ &GetSelectedTarget(), m_interpreter, result.GetOutputStream(),
+ module, m_options.m_str.c_str(), m_options.m_use_regex)) {
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
@@ -3868,25 +3892,20 @@ protected:
const ModuleList &target_modules = target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- const size_t num_modules = target_modules.GetSize();
- if (num_modules > 0) {
- for (i = 0; i < num_modules && !syntax_error; ++i) {
- Module *module_pointer =
- target_modules.GetModulePointerAtIndexUnlocked(i);
-
- if (module_pointer != current_module.get() &&
- LookupInModule(m_interpreter,
- target_modules.GetModulePointerAtIndexUnlocked(i),
- result, syntax_error)) {
- result.GetOutputStream().EOL();
- num_successful_lookups++;
- }
- }
- } else {
+ if (target_modules.GetSize() == 0) {
result.AppendError("the target has no associated executable images");
result.SetStatus(eReturnStatusFailed);
return false;
}
+
+ for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
+ if (module_sp != current_module &&
+ LookupInModule(m_interpreter, module_sp.get(), result,
+ syntax_error)) {
+ result.GetOutputStream().EOL();
+ num_successful_lookups++;
+ }
+ }
} else {
// Dump specified images (by basename or fullpath)
const char *arg_cstr;
@@ -4332,7 +4351,6 @@ protected:
module_spec.GetSymbolFileSpec() = symfile_spec;
}
- ArchSpec arch;
bool symfile_exists =
FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
@@ -4405,10 +4423,10 @@ private:
class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
public IOHandlerDelegateMultiline {
public:
- class CommandOptions : public Options {
+ class CommandOptions : public OptionGroup {
public:
CommandOptions()
- : Options(), m_line_start(0), m_line_end(UINT_MAX),
+ : OptionGroup(), m_line_start(0), m_line_end(UINT_MAX),
m_func_name_type_mask(eFunctionNameTypeAuto),
m_sym_ctx_specified(false), m_thread_specified(false),
m_use_one_liner(false), m_one_liner() {}
@@ -4422,7 +4440,8 @@ public:
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
- const int short_option = m_getopt_table[option_idx].val;
+ const int short_option =
+ g_target_stop_hook_add_options[option_idx].short_option;
switch (short_option) {
case 'c':
@@ -4552,20 +4571,75 @@ public:
// Instance variables to hold the values for one_liner options.
bool m_use_one_liner;
std::vector<std::string> m_one_liner;
+
bool m_auto_continue;
};
CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "target stop-hook add",
- "Add a hook to be executed when the target stops.",
+ "Add a hook to be executed when the target stops."
+ "The hook can either be a list of commands or an "
+ "appropriately defined Python class. You can also "
+ "add filters so the hook only runs a certain stop "
+ "points.",
"target stop-hook add"),
IOHandlerDelegateMultiline("DONE",
IOHandlerDelegate::Completion::LLDBCommand),
- m_options() {}
+ m_options(), m_python_class_options("scripted stop-hook", true, 'P') {
+ SetHelpLong(
+ R"(
+Command Based stop-hooks:
+-------------------------
+ Stop hooks can run a list of lldb commands by providing one or more
+ --one-line-command options. The commands will get run in the order they are
+ added. Or you can provide no commands, in which case you will enter a
+ command editor where you can enter the commands to be run.
+
+Python Based Stop Hooks:
+------------------------
+ Stop hooks can be implemented with a suitably defined Python class, whose name
+ is passed in the --python-class option.
+
+ When the stop hook is added, the class is initialized by calling:
+
+ def __init__(self, target, extra_args, dict):
+
+ target: The target that the stop hook is being added to.
+ extra_args: An SBStructuredData Dictionary filled with the -key -value
+ option pairs passed to the command.
+ dict: An implementation detail provided by lldb.
+
+ Then when the stop-hook triggers, lldb will run the 'handle_stop' method.
+ The method has the signature:
+
+ def handle_stop(self, exe_ctx, stream):
+
+ exe_ctx: An SBExecutionContext for the thread that has stopped.
+ stream: An SBStream, anything written to this stream will be printed in the
+ the stop message when the process stops.
+
+ Return Value: The method returns "should_stop". If should_stop is false
+ from all the stop hook executions on threads that stopped
+ with a reason, then the process will continue. Note that this
+ will happen only after all the stop hooks are run.
+
+Filter Options:
+---------------
+ Stop hooks can be set to always run, or to only run when the stopped thread
+ matches the filter options passed on the command line. The available filter
+ options include a shared library or a thread or queue specification,
+ a line range in a source file, a function name or a class name.
+ )");
+ m_all_options.Append(&m_python_class_options,
+ LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
+ LLDB_OPT_SET_FROM_TO(4, 6));
+ m_all_options.Append(&m_options);
+ m_all_options.Finalize();
+ }
~CommandObjectTargetStopHookAdd() override = default;
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
protected:
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
@@ -4589,10 +4663,15 @@ protected:
error_sp->Flush();
}
Target *target = GetDebugger().GetSelectedTarget().get();
- if (target)
- target->RemoveStopHookByID(m_stop_hook_sp->GetID());
+ if (target) {
+ target->UndoCreateStopHook(m_stop_hook_sp->GetID());
+ }
} else {
- m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
+ // The IOHandler editor is only for command lines stop hooks:
+ Target::StopHookCommandLine *hook_ptr =
+ static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());
+
+ hook_ptr->SetActionFromString(line);
StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
if (output_sp) {
output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
@@ -4609,7 +4688,10 @@ protected:
m_stop_hook_sp.reset();
Target &target = GetSelectedOrDummyTarget();
- Target::StopHookSP new_hook_sp = target.CreateStopHook();
+ Target::StopHookSP new_hook_sp =
+ target.CreateStopHook(m_python_class_options.GetName().empty() ?
+ Target::StopHook::StopHookKind::CommandBased
+ : Target::StopHook::StopHookKind::ScriptBased);
// First step, make the specifier.
std::unique_ptr<SymbolContextSpecifier> specifier_up;
@@ -4678,11 +4760,30 @@ protected:
new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
if (m_options.m_use_one_liner) {
- // Use one-liners.
- for (auto cmd : m_options.m_one_liner)
- new_hook_sp->GetCommandPointer()->AppendString(cmd.c_str());
+ // This is a command line stop hook:
+ Target::StopHookCommandLine *hook_ptr =
+ static_cast<Target::StopHookCommandLine *>(new_hook_sp.get());
+ hook_ptr->SetActionFromStrings(m_options.m_one_liner);
result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
new_hook_sp->GetID());
+ } else if (!m_python_class_options.GetName().empty()) {
+ // This is a scripted stop hook:
+ Target::StopHookScripted *hook_ptr =
+ static_cast<Target::StopHookScripted *>(new_hook_sp.get());
+ Status error = hook_ptr->SetScriptCallback(
+ m_python_class_options.GetName(),
+ m_python_class_options.GetStructuredData());
+ if (error.Success())
+ result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
+ new_hook_sp->GetID());
+ else {
+ // FIXME: Set the stop hook ID counter back.
+ result.AppendErrorWithFormat("Couldn't add stop hook: %s",
+ error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ target.UndoCreateStopHook(new_hook_sp->GetID());
+ return false;
+ }
} else {
m_stop_hook_sp = new_hook_sp;
m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt
@@ -4695,6 +4796,9 @@ protected:
private:
CommandOptions m_options;
+ OptionGroupPythonClassWithDict m_python_class_options;
+ OptionGroupOptions m_all_options;
+
Target::StopHookSP m_stop_hook_sp;
};
@@ -4711,6 +4815,14 @@ public:
~CommandObjectTargetStopHookDelete() override = default;
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion,
+ request, nullptr);
+ }
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target &target = GetSelectedOrDummyTarget();
@@ -4759,6 +4871,16 @@ public:
~CommandObjectTargetStopHookEnableDisable() override = default;
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ if (request.GetCursorIndex())
+ return;
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion,
+ request, nullptr);
+ }
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target &target = GetSelectedOrDummyTarget();