aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Target
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Target')
-rw-r--r--contrib/llvm-project/lldb/source/Target/ABI.cpp16
-rw-r--r--contrib/llvm-project/lldb/source/Target/AssertFrameRecognizer.cpp28
-rw-r--r--contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp13
-rw-r--r--contrib/llvm-project/lldb/source/Target/MemoryRegionInfo.cpp4
-rw-r--r--contrib/llvm-project/lldb/source/Target/OperatingSystem.cpp2
-rw-r--r--contrib/llvm-project/lldb/source/Target/Platform.cpp32
-rw-r--r--contrib/llvm-project/lldb/source/Target/Process.cpp281
-rw-r--r--contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp134
-rw-r--r--contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp19
-rw-r--r--contrib/llvm-project/lldb/source/Target/StackFrame.cpp34
-rw-r--r--contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp221
-rw-r--r--contrib/llvm-project/lldb/source/Target/SystemRuntime.cpp6
-rw-r--r--contrib/llvm-project/lldb/source/Target/Target.cpp649
-rw-r--r--contrib/llvm-project/lldb/source/Target/TargetList.cpp530
-rw-r--r--contrib/llvm-project/lldb/source/Target/TargetProperties.td20
-rw-r--r--contrib/llvm-project/lldb/source/Target/Thread.cpp32
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp4
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp6
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanPython.cpp12
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp18
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanStepInRange.cpp16
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp4
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp8
-rw-r--r--contrib/llvm-project/lldb/source/Target/ThreadTrace.cpp39
-rw-r--r--contrib/llvm-project/lldb/source/Target/Trace.cpp268
-rw-r--r--contrib/llvm-project/lldb/source/Target/TraceSessionFileParser.cpp223
-rw-r--r--contrib/llvm-project/lldb/source/Target/UnixSignals.cpp86
-rw-r--r--contrib/llvm-project/lldb/source/Target/UnwindAssembly.cpp2
28 files changed, 1671 insertions, 1036 deletions
diff --git a/contrib/llvm-project/lldb/source/Target/ABI.cpp b/contrib/llvm-project/lldb/source/Target/ABI.cpp
index 4320eb93adfc..f6a531136dcb 100644
--- a/contrib/llvm-project/lldb/source/Target/ABI.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ABI.cpp
@@ -42,27 +42,22 @@ ABI::FindPlugin(lldb::ProcessSP process_sp, const ArchSpec &arch) {
ABI::~ABI() = default;
-bool RegInfoBasedABI::GetRegisterInfoByName(ConstString name, RegisterInfo &info) {
+bool RegInfoBasedABI::GetRegisterInfoByName(llvm::StringRef name,
+ RegisterInfo &info) {
uint32_t count = 0;
const RegisterInfo *register_info_array = GetRegisterInfoArray(count);
if (register_info_array) {
- const char *unique_name_cstr = name.GetCString();
uint32_t i;
for (i = 0; i < count; ++i) {
const char *reg_name = register_info_array[i].name;
- assert(ConstString(reg_name).GetCString() == reg_name &&
- "register_info_array[i].name not from a ConstString?");
- if (reg_name == unique_name_cstr) {
+ if (reg_name == name) {
info = register_info_array[i];
return true;
}
}
for (i = 0; i < count; ++i) {
const char *reg_alt_name = register_info_array[i].alt_name;
- assert((reg_alt_name == nullptr ||
- ConstString(reg_alt_name).GetCString() == reg_alt_name) &&
- "register_info_array[i].alt_name not from a ConstString?");
- if (reg_alt_name == unique_name_cstr) {
+ if (reg_alt_name == name) {
info = register_info_array[i];
return true;
}
@@ -130,7 +125,6 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
// we don't do anything with these for now
break;
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
expr_variable_sp->m_flags |=
ExpressionVariable::EVIsFreezeDried;
expr_variable_sp->m_flags |=
@@ -224,7 +218,7 @@ void RegInfoBasedABI::AugmentRegisterInfo(RegisterInfo &info) {
return;
RegisterInfo abi_info;
- if (!GetRegisterInfoByName(ConstString(info.name), abi_info))
+ if (!GetRegisterInfoByName(info.name, abi_info))
return;
if (info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM)
diff --git a/contrib/llvm-project/lldb/source/Target/AssertFrameRecognizer.cpp b/contrib/llvm-project/lldb/source/Target/AssertFrameRecognizer.cpp
index d87459ac2fdd..cb671040d14f 100644
--- a/contrib/llvm-project/lldb/source/Target/AssertFrameRecognizer.cpp
+++ b/contrib/llvm-project/lldb/source/Target/AssertFrameRecognizer.cpp
@@ -86,20 +86,17 @@ bool GetAssertLocation(llvm::Triple::OSType os, SymbolLocation &location) {
}
void RegisterAssertFrameRecognizer(Process *process) {
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, [process]() {
- Target &target = process->GetTarget();
- llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
- SymbolLocation location;
-
- if (!GetAbortLocation(os, location))
- return;
-
- StackFrameRecognizerManager::AddRecognizer(
- StackFrameRecognizerSP(new AssertFrameRecognizer()),
- location.module_spec.GetFilename(), location.symbols,
- /*first_instruction_only*/ false);
- });
+ Target &target = process->GetTarget();
+ llvm::Triple::OSType os = target.GetArchitecture().GetTriple().getOS();
+ SymbolLocation location;
+
+ if (!GetAbortLocation(os, location))
+ return;
+
+ target.GetFrameRecognizerManager().AddRecognizer(
+ StackFrameRecognizerSP(new AssertFrameRecognizer()),
+ location.module_spec.GetFilename(), location.symbols,
+ /*first_instruction_only*/ false);
}
} // namespace lldb_private
@@ -133,7 +130,8 @@ AssertFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
SymbolContext sym_ctx =
prev_frame_sp->GetSymbolContext(eSymbolContextEverything);
- if (!sym_ctx.module_sp->GetFileSpec().FileEquals(location.module_spec))
+ if (!sym_ctx.module_sp ||
+ !sym_ctx.module_sp->GetFileSpec().FileEquals(location.module_spec))
continue;
ConstString func_name = sym_ctx.GetFunctionName();
diff --git a/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp
index 58ad70c2b902..f2e2febf8b88 100644
--- a/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp
+++ b/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp
@@ -202,26 +202,19 @@ protected:
LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
lldb::LanguageType language) {
- std::unique_ptr<LanguageRuntime> language_runtime_up;
LanguageRuntimeCreateInstance create_callback;
-
for (uint32_t idx = 0;
(create_callback =
PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
nullptr;
++idx) {
- language_runtime_up.reset(create_callback(process, language));
-
- if (language_runtime_up)
- return language_runtime_up.release();
+ if (LanguageRuntime *runtime = create_callback(process, language))
+ return runtime;
}
-
return nullptr;
}
-LanguageRuntime::LanguageRuntime(Process *process) : m_process(process) {}
-
-LanguageRuntime::~LanguageRuntime() = default;
+LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}
BreakpointPreconditionSP
LanguageRuntime::GetExceptionPrecondition(LanguageType language,
diff --git a/contrib/llvm-project/lldb/source/Target/MemoryRegionInfo.cpp b/contrib/llvm-project/lldb/source/Target/MemoryRegionInfo.cpp
index c7fb349ee1cc..0d5ebbdbe238 100644
--- a/contrib/llvm-project/lldb/source/Target/MemoryRegionInfo.cpp
+++ b/contrib/llvm-project/lldb/source/Target/MemoryRegionInfo.cpp
@@ -13,12 +13,12 @@ using namespace lldb_private;
llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS,
const MemoryRegionInfo &Info) {
return OS << llvm::formatv("MemoryRegionInfo([{0}, {1}), {2:r}{3:w}{4:x}, "
- "{5}, `{6}`, {7}, {8})",
+ "{5}, `{6}`, {7}, {8}, {9})",
Info.GetRange().GetRangeBase(),
Info.GetRange().GetRangeEnd(), Info.GetReadable(),
Info.GetWritable(), Info.GetExecutable(),
Info.GetMapped(), Info.GetName(), Info.GetFlash(),
- Info.GetBlocksize());
+ Info.GetBlocksize(), Info.GetMemoryTagged());
}
void llvm::format_provider<MemoryRegionInfo::OptionalBool>::format(
diff --git a/contrib/llvm-project/lldb/source/Target/OperatingSystem.cpp b/contrib/llvm-project/lldb/source/Target/OperatingSystem.cpp
index ddffab4553cc..033a806460da 100644
--- a/contrib/llvm-project/lldb/source/Target/OperatingSystem.cpp
+++ b/contrib/llvm-project/lldb/source/Target/OperatingSystem.cpp
@@ -44,8 +44,6 @@ OperatingSystem *OperatingSystem::FindPlugin(Process *process,
OperatingSystem::OperatingSystem(Process *process) : m_process(process) {}
-OperatingSystem::~OperatingSystem() = default;
-
bool OperatingSystem::IsOperatingSystemPluginThread(
const lldb::ThreadSP &thread_sp) {
if (thread_sp)
diff --git a/contrib/llvm-project/lldb/source/Target/Platform.cpp b/contrib/llvm-project/lldb/source/Target/Platform.cpp
index e5afb4c7b8d7..a77ecddfbab6 100644
--- a/contrib/llvm-project/lldb/source/Target/Platform.cpp
+++ b/contrib/llvm-project/lldb/source/Target/Platform.cpp
@@ -85,7 +85,7 @@ PlatformProperties::PlatformProperties() {
return;
llvm::SmallString<64> user_home_dir;
- if (!llvm::sys::path::home_directory(user_home_dir))
+ if (!FileSystem::Instance().GetHomeDirectory(user_home_dir))
return;
module_cache_dir = FileSpec(user_home_dir.c_str());
@@ -1020,7 +1020,6 @@ Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);
if (launch_info.GetFlags().Test(eLaunchFlagLaunchInShell)) {
- const bool is_localhost = true;
const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
const bool first_arg_is_full_shell_command = false;
uint32_t num_resumes = GetResumeCountForLaunchInfo(launch_info);
@@ -1034,8 +1033,7 @@ Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
}
if (!launch_info.ConvertArgumentsForLaunchingInShell(
- error, is_localhost, will_debug, first_arg_is_full_shell_command,
- num_resumes))
+ error, will_debug, first_arg_is_full_shell_command, num_resumes))
return error;
} else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
error = ShellExpandArguments(launch_info);
@@ -1318,7 +1316,23 @@ MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,
}
lldb_private::Status Platform::RunShellCommand(
- const char *command, // Shouldn't be nullptr
+ llvm::StringRef command,
+ const FileSpec &
+ working_dir, // Pass empty FileSpec to use the current working directory
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the
+ // process to exit
+ std::string
+ *command_output, // Pass nullptr if you don't want the command output
+ const Timeout<std::micro> &timeout) {
+ return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
+ signo_ptr, command_output, timeout);
+}
+
+lldb_private::Status Platform::RunShellCommand(
+ llvm::StringRef shell, // Pass empty if you want to use the default
+ // shell interpreter
+ llvm::StringRef command, // Shouldn't be empty
const FileSpec &
working_dir, // Pass empty FileSpec to use the current working directory
int *status_ptr, // Pass nullptr if you don't want the process exit status
@@ -1328,8 +1342,8 @@ lldb_private::Status Platform::RunShellCommand(
*command_output, // Pass nullptr if you don't want the command output
const Timeout<std::micro> &timeout) {
if (IsHost())
- return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
- command_output, timeout);
+ return Host::RunShellCommand(shell, command, working_dir, status_ptr,
+ signo_ptr, command_output, timeout);
else
return Status("unimplemented");
}
@@ -1817,10 +1831,8 @@ lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,
if (!target || error.Fail())
return nullptr;
- debugger.GetTargetList().SetSelectedTarget(target);
-
lldb::ProcessSP process_sp =
- target->CreateProcess(debugger.GetListener(), plugin_name, nullptr);
+ target->CreateProcess(debugger.GetListener(), plugin_name, nullptr, true);
if (!process_sp)
return nullptr;
diff --git a/contrib/llvm-project/lldb/source/Target/Process.cpp b/contrib/llvm-project/lldb/source/Target/Process.cpp
index d777a2713911..518a6934059e 100644
--- a/contrib/llvm-project/lldb/source/Target/Process.cpp
+++ b/contrib/llvm-project/lldb/source/Target/Process.cpp
@@ -278,6 +278,12 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
return std::chrono::seconds(value);
}
+bool ProcessProperties::GetSteppingRunsAllThreads() const {
+ const uint32_t idx = ePropertySteppingRunsAllThreads;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+}
+
bool ProcessProperties::GetOSPluginReportsAllThreads() const {
const bool fail_value = true;
const Property *exp_property =
@@ -301,179 +307,11 @@ void ProcessProperties::SetOSPluginReportsAllThreads(bool does_report) {
nullptr, ePropertyOSPluginReportsAllThreads, does_report);
}
-Status ProcessLaunchCommandOptions::SetOptionValue(
- uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option) {
- case 's': // Stop at program entry point
- launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
- break;
-
- case 'i': // STDIN for read only
- {
- FileAction action;
- if (action.Open(STDIN_FILENO, FileSpec(option_arg), true, false))
- launch_info.AppendFileAction(action);
- break;
- }
-
- case 'o': // Open STDOUT for write only
- {
- FileAction action;
- if (action.Open(STDOUT_FILENO, FileSpec(option_arg), false, true))
- launch_info.AppendFileAction(action);
- break;
- }
-
- case 'e': // STDERR for write only
- {
- FileAction action;
- if (action.Open(STDERR_FILENO, FileSpec(option_arg), false, true))
- launch_info.AppendFileAction(action);
- break;
- }
-
- case 'p': // Process plug-in name
- launch_info.SetProcessPluginName(option_arg);
- break;
-
- case 'n': // Disable STDIO
- {
- FileAction action;
- const FileSpec dev_null(FileSystem::DEV_NULL);
- if (action.Open(STDIN_FILENO, dev_null, true, false))
- launch_info.AppendFileAction(action);
- if (action.Open(STDOUT_FILENO, dev_null, false, true))
- launch_info.AppendFileAction(action);
- if (action.Open(STDERR_FILENO, dev_null, false, true))
- launch_info.AppendFileAction(action);
- break;
- }
-
- case 'w':
- launch_info.SetWorkingDirectory(FileSpec(option_arg));
- break;
-
- case 't': // Open process in new terminal window
- launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);
- break;
-
- case 'a': {
- TargetSP target_sp =
- execution_context ? execution_context->GetTargetSP() : TargetSP();
- PlatformSP platform_sp =
- target_sp ? target_sp->GetPlatform() : PlatformSP();
- launch_info.GetArchitecture() =
- Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
- } break;
-
- case 'A': // Disable ASLR.
- {
- bool success;
- const bool disable_aslr_arg =
- OptionArgParser::ToBoolean(option_arg, true, &success);
- if (success)
- disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo;
- else
- error.SetErrorStringWithFormat(
- "Invalid boolean value for disable-aslr option: '%s'",
- option_arg.empty() ? "<null>" : option_arg.str().c_str());
- break;
- }
-
- case 'X': // shell expand args.
- {
- bool success;
- const bool expand_args =
- OptionArgParser::ToBoolean(option_arg, true, &success);
- if (success)
- launch_info.SetShellExpandArguments(expand_args);
- else
- error.SetErrorStringWithFormat(
- "Invalid boolean value for shell-expand-args option: '%s'",
- option_arg.empty() ? "<null>" : option_arg.str().c_str());
- break;
- }
-
- case 'c':
- if (!option_arg.empty())
- launch_info.SetShell(FileSpec(option_arg));
- else
- launch_info.SetShell(HostInfo::GetDefaultShell());
- break;
-
- case 'v':
- launch_info.GetEnvironment().insert(option_arg);
- break;
-
- default:
- error.SetErrorStringWithFormat("unrecognized short option character '%c'",
- short_option);
- break;
- }
- return error;
-}
-
-static constexpr OptionDefinition g_process_launch_options[] = {
- {LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument,
- nullptr, {}, 0, eArgTypeNone,
- "Stop at the entry point of the program when launching a process."},
- {LLDB_OPT_SET_ALL, false, "disable-aslr", 'A',
- OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
- "Set whether to disable address space layout randomization when launching "
- "a process."},
- {LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument,
- nullptr, {}, 0, eArgTypePlugin,
- "Name of the process plugin you want to use."},
- {LLDB_OPT_SET_ALL, false, "working-dir", 'w',
- OptionParser::eRequiredArgument, nullptr, {}, 0,
- eArgTypeDirectoryName,
- "Set the current working directory to <path> when running the inferior."},
- {LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument,
- nullptr, {}, 0, eArgTypeArchitecture,
- "Set the architecture for the process to launch when ambiguous."},
- {LLDB_OPT_SET_ALL, false, "environment", 'v',
- OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone,
- "Specify an environment variable name/value string (--environment "
- "NAME=VALUE). Can be specified multiple times for subsequent environment "
- "entries."},
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "shell", 'c',
- OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeFilename,
- "Run the process in a shell (not supported on all platforms)."},
-
- {LLDB_OPT_SET_1, false, "stdin", 'i', OptionParser::eRequiredArgument,
- nullptr, {}, 0, eArgTypeFilename,
- "Redirect stdin for the process to <filename>."},
- {LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument,
- nullptr, {}, 0, eArgTypeFilename,
- "Redirect stdout for the process to <filename>."},
- {LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument,
- nullptr, {}, 0, eArgTypeFilename,
- "Redirect stderr for the process to <filename>."},
-
- {LLDB_OPT_SET_2, false, "tty", 't', OptionParser::eNoArgument, nullptr,
- {}, 0, eArgTypeNone,
- "Start the process in a terminal (not supported on all platforms)."},
-
- {LLDB_OPT_SET_3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr,
- {}, 0, eArgTypeNone,
- "Do not set up for terminal I/O to go to running process."},
- {LLDB_OPT_SET_4, false, "shell-expand-args", 'X',
- OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
- "Set whether to shell expand arguments to the process when launching."},
-};
-
-llvm::ArrayRef<OptionDefinition> ProcessLaunchCommandOptions::GetDefinitions() {
- return llvm::makeArrayRef(g_process_launch_options);
-}
-
ProcessSP Process::FindPlugin(lldb::TargetSP target_sp,
llvm::StringRef plugin_name,
ListenerSP listener_sp,
- const FileSpec *crash_file_path) {
+ const FileSpec *crash_file_path,
+ bool can_connect) {
static uint32_t g_process_unique_id = 0;
ProcessSP process_sp;
@@ -483,7 +321,8 @@ ProcessSP Process::FindPlugin(lldb::TargetSP target_sp,
create_callback =
PluginManager::GetProcessCreateCallbackForPluginName(const_plugin_name);
if (create_callback) {
- process_sp = create_callback(target_sp, listener_sp, crash_file_path);
+ process_sp = create_callback(target_sp, listener_sp, crash_file_path,
+ can_connect);
if (process_sp) {
if (process_sp->CanDebug(target_sp, true)) {
process_sp->m_process_unique_id = ++g_process_unique_id;
@@ -496,7 +335,8 @@ ProcessSP Process::FindPlugin(lldb::TargetSP target_sp,
(create_callback =
PluginManager::GetProcessCreateCallbackAtIndex(idx)) != nullptr;
++idx) {
- process_sp = create_callback(target_sp, listener_sp, crash_file_path);
+ process_sp = create_callback(target_sp, listener_sp, crash_file_path,
+ can_connect);
if (process_sp) {
if (process_sp->CanDebug(target_sp, false)) {
process_sp->m_process_unique_id = ++g_process_unique_id;
@@ -523,7 +363,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp)
Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
const UnixSignalsSP &unix_signals_sp)
- : ProcessProperties(this), UserID(LLDB_INVALID_PROCESS_ID),
+ : ProcessProperties(this),
Broadcaster((target_sp->GetDebugger().GetBroadcasterManager()),
Process::GetStaticBroadcasterClass().AsCString()),
m_target_wp(target_sp), m_public_state(eStateUnloaded),
@@ -547,7 +387,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
m_profile_data_comm_mutex(), m_profile_data(), m_iohandler_sync(0),
m_memory_cache(*this), m_allocated_memory_cache(*this),
m_should_detach(false), m_next_event_action_up(), m_public_run_lock(),
- m_private_run_lock(), m_finalizing(false), m_finalize_called(false),
+ m_private_run_lock(), m_finalizing(false),
m_clear_thread_plans_on_stop(false), m_force_next_event_delivery(false),
m_last_broadcast_state(eStateInvalid), m_destroy_in_process(false),
m_can_interpret_function_calls(false), m_warnings_issued(),
@@ -623,7 +463,8 @@ const ProcessPropertiesSP &Process::GetGlobalProperties() {
}
void Process::Finalize() {
- m_finalizing = true;
+ if (m_finalizing.exchange(true))
+ return;
// Destroy this process if needed
switch (GetPrivateState()) {
@@ -635,7 +476,7 @@ void Process::Finalize() {
case eStateStepping:
case eStateCrashed:
case eStateSuspended:
- Destroy(false);
+ DestroyImpl(false);
break;
case eStateInvalid:
@@ -698,7 +539,6 @@ void Process::Finalize() {
m_private_run_lock.TrySetRunning(); // This will do nothing if already locked
m_private_run_lock.SetStopped();
m_structured_data_plugin_map.clear();
- m_finalize_called = true;
}
void Process::RegisterNotificationCallbacks(const Notifications &callbacks) {
@@ -1239,6 +1079,12 @@ bool Process::SetProcessExitStatus(
return false;
}
+bool Process::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ m_thread_plans.ClearThreadCache();
+ return DoUpdateThreadList(old_thread_list, new_thread_list);
+}
+
void Process::UpdateThreadListIfNeeded() {
const uint32_t stop_id = GetStopID();
if (m_thread_list.GetSize(false) == 0 ||
@@ -1507,7 +1353,7 @@ bool Process::StateChangedIsHijackedForSynchronousResume() {
StateType Process::GetPrivateState() { return m_private_state.GetValue(); }
void Process::SetPrivateState(StateType new_state) {
- if (m_finalize_called)
+ if (m_finalizing)
return;
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE |
@@ -1557,11 +1403,7 @@ void Process::SetPrivateState(StateType new_state) {
StateAsCString(new_state), m_mod_id.GetStopID());
}
- // Use our target to get a shared pointer to ourselves...
- if (m_finalize_called && !PrivateStateThreadIsValid())
- BroadcastEvent(event_sp);
- else
- m_private_state_broadcaster.BroadcastEvent(event_sp);
+ m_private_state_broadcaster.BroadcastEvent(event_sp);
} else {
LLDB_LOGF(log,
"Process::SetPrivateState (%s) state didn't change. Ignoring...",
@@ -2291,6 +2133,9 @@ size_t Process::WriteMemory(addr_t addr, const void *buf, size_t size,
if (error.Fail())
return;
+ if (bp->GetType() != BreakpointSite::eSoftware)
+ return;
+
addr_t intersect_addr;
size_t intersect_size;
size_t opcode_offset;
@@ -3068,13 +2913,8 @@ void Process::CompleteAttach() {
}
}
// Figure out which one is the executable, and set that in our target:
- const ModuleList &target_modules = GetTarget().GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- size_t num_modules = target_modules.GetSize();
ModuleSP new_executable_module_sp;
-
- for (size_t i = 0; i < num_modules; i++) {
- ModuleSP module_sp(target_modules.GetModuleAtIndexUnlocked(i));
+ for (ModuleSP module_sp : GetTarget().GetImages().Modules()) {
if (module_sp && module_sp->IsExecutable()) {
if (GetTarget().GetExecutableModulePointer() != module_sp.get())
new_executable_module_sp = module_sp;
@@ -3154,7 +2994,7 @@ Status Process::PrivateResume() {
if (m_thread_list.WillResume()) {
// Last thing, do the PreResumeActions.
if (!RunPreResumeActions()) {
- error.SetErrorStringWithFormat(
+ error.SetErrorString(
"Process::PrivateResume PreResumeActions failed, not resuming.");
} else {
m_mod_id.BumpResumeID();
@@ -3333,9 +3173,12 @@ Status Process::Detach(bool keep_stopped) {
Status Process::Destroy(bool force_kill) {
// If we've already called Process::Finalize then there's nothing useful to
// be done here. Finalize has actually called Destroy already.
- if (m_finalize_called)
+ if (m_finalizing)
return {};
+ return DestroyImpl(force_kill);
+}
+Status Process::DestroyImpl(bool force_kill) {
// Tell ourselves we are in the process of destroying the process, so that we
// don't do any unnecessary work that might hinder the destruction. Remember
// to set this back to false when we are done. That way if the attempt
@@ -4169,8 +4012,7 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
// public (or SyncResume) broadcasters. StopHooks are just for
// real public stops. They might also restart the target,
// so watch for that.
- process_sp->GetTarget().RunStopHooks();
- if (process_sp->GetPrivateState() == eStateRunning)
+ if (process_sp->GetTarget().RunStopHooks())
SetRestarted(true);
}
}
@@ -5757,41 +5599,25 @@ addr_t Process::ResolveIndirectFunction(const Address *address, Status &error) {
}
void Process::ModulesDidLoad(ModuleList &module_list) {
+ // Inform the system runtime of the modified modules.
SystemRuntime *sys_runtime = GetSystemRuntime();
- if (sys_runtime) {
+ if (sys_runtime)
sys_runtime->ModulesDidLoad(module_list);
- }
GetJITLoaders().ModulesDidLoad(module_list);
- // Give runtimes a chance to be created.
+ // Give the instrumentation runtimes a chance to be created before informing
+ // them of the modified modules.
InstrumentationRuntime::ModulesDidLoad(module_list, this,
m_instrumentation_runtimes);
+ for (auto &runtime : m_instrumentation_runtimes)
+ runtime.second->ModulesDidLoad(module_list);
- // Tell runtimes about new modules.
- for (auto pos = m_instrumentation_runtimes.begin();
- pos != m_instrumentation_runtimes.end(); ++pos) {
- InstrumentationRuntimeSP runtime = pos->second;
- runtime->ModulesDidLoad(module_list);
- }
-
- // Let any language runtimes we have already created know about the modules
- // that loaded.
-
- // Iterate over a copy of this language runtime list in case the language
- // runtime ModulesDidLoad somehow causes the language runtime to be
- // unloaded.
- {
- std::lock_guard<std::recursive_mutex> guard(m_language_runtimes_mutex);
- LanguageRuntimeCollection language_runtimes(m_language_runtimes);
- for (const auto &pair : language_runtimes) {
- // We must check language_runtime_sp to make sure it is not nullptr as we
- // might cache the fact that we didn't have a language runtime for a
- // language.
- LanguageRuntimeSP language_runtime_sp = pair.second;
- if (language_runtime_sp)
- language_runtime_sp->ModulesDidLoad(module_list);
- }
+ // Give the language runtimes a chance to be created before informing them of
+ // the modified modules.
+ for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {
+ if (LanguageRuntime *runtime = GetLanguageRuntime(lang_type))
+ runtime->ModulesDidLoad(module_list);
}
// If we don't have an operating system plug-in, try to load one since
@@ -5799,7 +5625,7 @@ void Process::ModulesDidLoad(ModuleList &module_list) {
if (!m_os_up)
LoadOperatingSystemPlugin(false);
- // Give structured-data plugins a chance to see the modified modules.
+ // Inform the structured-data plugins of the modified modules.
for (auto pair : m_structured_data_plugin_map) {
if (pair.second)
pair.second->ModulesDidLoad(*this, module_list);
@@ -5960,10 +5786,8 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
return retval;
}
- uint32_t branch_index =
- insn_list->GetIndexOfNextBranchInstruction(insn_offset, target,
- false /* ignore_calls*/,
- nullptr);
+ uint32_t branch_index = insn_list->GetIndexOfNextBranchInstruction(
+ insn_offset, false /* ignore_calls*/, nullptr);
if (branch_index == UINT32_MAX) {
return retval;
}
@@ -6138,6 +5962,13 @@ UtilityFunction *Process::GetLoadImageUtilityFunction(
return m_dlopen_utility_func_up.get();
}
+llvm::Expected<TraceTypeInfo> Process::GetSupportedTraceType() {
+ if (!IsLiveDebugSession())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Can't trace a non-live process.");
+ return llvm::make_error<UnimplementedError>();
+}
+
bool Process::CallVoidArgVoidPtrReturn(const Address *address,
addr_t &returned_func,
bool trap_exceptions) {
diff --git a/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp
new file mode 100644
index 000000000000..95f87745b724
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp
@@ -0,0 +1,134 @@
+//===-- ProcessTrace.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ProcessTrace.h"
+
+#include <memory>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ConstString ProcessTrace::GetPluginNameStatic() {
+ static ConstString g_name("trace");
+ return g_name;
+}
+
+const char *ProcessTrace::GetPluginDescriptionStatic() {
+ return "Trace process plug-in.";
+}
+
+void ProcessTrace::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessTrace::CreateInstance);
+}
+
+ProcessSP ProcessTrace::CreateInstance(TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file,
+ bool can_connect) {
+ if (can_connect)
+ return nullptr;
+ return std::make_shared<ProcessTrace>(target_sp, listener_sp);
+}
+
+bool ProcessTrace::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {
+ return plugin_specified_by_name;
+}
+
+ProcessTrace::ProcessTrace(TargetSP target_sp, ListenerSP listener_sp)
+ : PostMortemProcess(target_sp, listener_sp) {}
+
+ProcessTrace::~ProcessTrace() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize();
+}
+
+ConstString ProcessTrace::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ProcessTrace::GetPluginVersion() { return 1; }
+
+void ProcessTrace::DidAttach(ArchSpec &process_arch) {
+ ListenerSP listener_sp(
+ Listener::MakeListener("lldb.process_trace.did_attach_listener"));
+ HijackProcessEvents(listener_sp);
+
+ SetCanJIT(false);
+ StartPrivateStateThread();
+ SetPrivateState(eStateStopped);
+
+ EventSP event_sp;
+ WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp);
+
+ RestoreProcessEvents();
+
+ Process::DidAttach(process_arch);
+}
+
+bool ProcessTrace::DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ return false;
+}
+
+void ProcessTrace::RefreshStateAfterStop() {}
+
+Status ProcessTrace::DoDestroy() { return Status(); }
+
+bool ProcessTrace::IsAlive() { return true; }
+
+size_t ProcessTrace::ReadMemory(addr_t addr, void *buf, size_t size,
+ Status &error) {
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // we have it all cached in the trace files.
+ return DoReadMemory(addr, buf, size, error);
+}
+
+void ProcessTrace::Clear() { m_thread_list.Clear(); }
+
+void ProcessTrace::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+ArchSpec ProcessTrace::GetArchitecture() {
+ return GetTarget().GetArchitecture();
+}
+
+bool ProcessTrace::GetProcessInfo(ProcessInstanceInfo &info) {
+ info.Clear();
+ info.SetProcessID(GetID());
+ info.SetArchitecture(GetArchitecture());
+ ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (module_sp) {
+ const bool add_exe_file_as_first_arg = false;
+ info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
+ add_exe_file_as_first_arg);
+ }
+ return true;
+}
+
+size_t ProcessTrace::DoReadMemory(addr_t addr, void *buf, size_t size,
+ Status &error) {
+ Address resolved_address;
+ GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, resolved_address);
+
+ return GetTarget().ReadMemoryFromFileCache(resolved_address, buf, size,
+ error);
+}
diff --git a/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp b/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp
index f53158b06b8f..3a186adca04c 100644
--- a/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp
+++ b/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp
@@ -171,15 +171,24 @@ Status RemoteAwarePlatform::ResolveExecutable(
}
Status RemoteAwarePlatform::RunShellCommand(
- const char *command, const FileSpec &working_dir, int *status_ptr,
+ llvm::StringRef command, const FileSpec &working_dir, int *status_ptr,
int *signo_ptr, std::string *command_output,
const Timeout<std::micro> &timeout) {
+ return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
+ signo_ptr, command_output, timeout);
+}
+
+Status RemoteAwarePlatform::RunShellCommand(
+ llvm::StringRef shell, llvm::StringRef command, const FileSpec &working_dir,
+ int *status_ptr, int *signo_ptr, std::string *command_output,
+ const Timeout<std::micro> &timeout) {
if (IsHost())
- return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
- command_output, timeout);
+ return Host::RunShellCommand(shell, command, working_dir, status_ptr,
+ signo_ptr, command_output, timeout);
if (m_remote_platform_sp)
- return m_remote_platform_sp->RunShellCommand(
- command, working_dir, status_ptr, signo_ptr, command_output, timeout);
+ return m_remote_platform_sp->RunShellCommand(shell, command, working_dir,
+ status_ptr, signo_ptr,
+ command_output, timeout);
return Status("unable to run a remote command without a platform");
}
diff --git a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp
index 3d6cc5dc90b3..131581567d73 100644
--- a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp
+++ b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp
@@ -229,21 +229,16 @@ bool StackFrame::ChangePC(addr_t pc) {
const char *StackFrame::Disassemble() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_disassembly.Empty()) {
- ExecutionContext exe_ctx(shared_from_this());
- Target *target = exe_ctx.GetTargetPtr();
- if (target) {
- const char *plugin_name = nullptr;
- const char *flavor = nullptr;
- Disassembler::Disassemble(target->GetDebugger(),
- target->GetArchitecture(), plugin_name, flavor,
- exe_ctx, 0, false, 0, 0, m_disassembly);
- }
- if (m_disassembly.Empty())
- return nullptr;
+ if (!m_disassembly.Empty())
+ return m_disassembly.GetData();
+
+ ExecutionContext exe_ctx(shared_from_this());
+ if (Target *target = exe_ctx.GetTargetPtr()) {
+ Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(),
+ *this, m_disassembly);
}
- return m_disassembly.GetData();
+ return m_disassembly.Empty() ? nullptr : m_disassembly.GetData();
}
Block *StackFrame::GetFrameBlock() {
@@ -1408,7 +1403,7 @@ ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
}
int64_t child_offset = child_sp->GetByteOffset();
- int64_t child_size = child_sp->GetByteSize();
+ int64_t child_size = child_sp->GetByteSize().getValueOr(0);
if (offset >= child_offset && offset < (child_offset + child_size)) {
return GetValueForOffset(frame, child_sp, offset - child_offset);
@@ -1441,8 +1436,8 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
}
if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) {
- int64_t index = offset / pointee->GetByteSize();
- offset = offset % pointee->GetByteSize();
+ int64_t index = offset / pointee->GetByteSize().getValueOr(1);
+ offset = offset % pointee->GetByteSize().getValueOr(1);
const bool can_create = true;
pointee = base->GetSyntheticArrayMember(index, can_create);
}
@@ -1956,8 +1951,11 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
if (!m_recognized_frame_sp) {
- m_recognized_frame_sp =
- StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame());
+ m_recognized_frame_sp = GetThread()
+ ->GetProcess()
+ ->GetTarget()
+ .GetFrameRecognizerManager()
+ .RecognizeFrame(CalculateStackFrame());
}
return m_recognized_frame_sp;
}
diff --git a/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp b/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp
index 7dc6e9d1e490..73d22d5bb4e6 100644
--- a/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp
@@ -6,12 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include <vector>
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Core/Module.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Utility/RegularExpression.h"
using namespace lldb;
@@ -48,158 +47,108 @@ ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
new ScriptedRecognizedStackFrame(args_synthesized));
}
-class StackFrameRecognizerManagerImpl {
-public:
- void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString module,
- llvm::ArrayRef<ConstString> symbols,
- bool first_instruction_only) {
- m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer,
- false, module, RegularExpressionSP(), symbols,
- RegularExpressionSP(), first_instruction_only});
- }
-
- void AddRecognizer(StackFrameRecognizerSP recognizer,
- RegularExpressionSP module, RegularExpressionSP symbol,
- bool first_instruction_only) {
- m_recognizers.push_front(
- {(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(),
- module, std::vector<ConstString>(), symbol, first_instruction_only});
- }
-
- void ForEach(std::function<
- void(uint32_t recognized_id, std::string recognizer_name,
- std::string module, llvm::ArrayRef<ConstString> symbols,
- bool regexp)> const &callback) {
- for (auto entry : m_recognizers) {
- if (entry.is_regexp) {
- std::string module_name;
- std::string symbol_name;
-
- if (entry.module_regexp)
- module_name = entry.module_regexp->GetText().str();
- if (entry.symbol_regexp)
- symbol_name = entry.symbol_regexp->GetText().str();
-
- callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
- llvm::makeArrayRef(ConstString(symbol_name)), true);
-
- } else {
- callback(entry.recognizer_id, entry.recognizer->GetName(),
- entry.module.GetCString(), entry.symbols, false);
- }
- }
- }
-
- bool RemoveRecognizerWithID(uint32_t recognizer_id) {
- if (recognizer_id >= m_recognizers.size()) return false;
- if (m_recognizers[recognizer_id].deleted) return false;
- m_recognizers[recognizer_id].deleted = true;
- return true;
- }
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, ConstString module,
+ llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, false,
+ module, RegularExpressionSP(), symbols,
+ RegularExpressionSP(), first_instruction_only});
+}
- void RemoveAllRecognizers() {
- m_recognizers.clear();
- }
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, RegularExpressionSP module,
+ RegularExpressionSP symbol, bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), recognizer, true,
+ ConstString(), module, std::vector<ConstString>(),
+ symbol, first_instruction_only});
+}
- StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) {
- const SymbolContext &symctx = frame->GetSymbolContext(
- eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
- ConstString function_name = symctx.GetFunctionName();
- ModuleSP module_sp = symctx.module_sp;
- if (!module_sp) return StackFrameRecognizerSP();
- ConstString module_name = module_sp->GetFileSpec().GetFilename();
- Symbol *symbol = symctx.symbol;
- if (!symbol) return StackFrameRecognizerSP();
- Address start_addr = symbol->GetAddress();
- Address current_addr = frame->GetFrameCodeAddress();
-
- for (auto entry : m_recognizers) {
- if (entry.deleted) continue;
- if (entry.module)
- if (entry.module != module_name) continue;
+void StackFrameRecognizerManager::ForEach(
+ const std::function<void(uint32_t, std::string, std::string,
+ llvm::ArrayRef<ConstString>, bool)> &callback) {
+ for (auto entry : m_recognizers) {
+ if (entry.is_regexp) {
+ std::string module_name;
+ std::string symbol_name;
if (entry.module_regexp)
- if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue;
-
- if (!entry.symbols.empty())
- if (!llvm::is_contained(entry.symbols, function_name))
- continue;
-
+ module_name = entry.module_regexp->GetText().str();
if (entry.symbol_regexp)
- if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
- continue;
+ symbol_name = entry.symbol_regexp->GetText().str();
- if (entry.first_instruction_only)
- if (start_addr != current_addr) continue;
+ callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
+ llvm::makeArrayRef(ConstString(symbol_name)), true);
- return entry.recognizer;
+ } else {
+ callback(entry.recognizer_id, entry.recognizer->GetName(),
+ entry.module.GetCString(), entry.symbols, false);
}
- return StackFrameRecognizerSP();
}
-
- RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) {
- auto recognizer = GetRecognizerForFrame(frame);
- if (!recognizer) return RecognizedStackFrameSP();
- return recognizer->RecognizeFrame(frame);
- }
-
- private:
- struct RegisteredEntry {
- uint32_t recognizer_id;
- bool deleted;
- StackFrameRecognizerSP recognizer;
- bool is_regexp;
- ConstString module;
- RegularExpressionSP module_regexp;
- std::vector<ConstString> symbols;
- RegularExpressionSP symbol_regexp;
- bool first_instruction_only;
- };
-
- std::deque<RegisteredEntry> m_recognizers;
-};
-
-StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() {
- static StackFrameRecognizerManagerImpl instance =
- StackFrameRecognizerManagerImpl();
- return instance;
}
-void StackFrameRecognizerManager::AddRecognizer(
- StackFrameRecognizerSP recognizer, ConstString module,
- llvm::ArrayRef<ConstString> symbols, bool first_instruction_only) {
- GetStackFrameRecognizerManagerImpl().AddRecognizer(
- recognizer, module, symbols, first_instruction_only);
+bool StackFrameRecognizerManager::RemoveRecognizerWithID(
+ uint32_t recognizer_id) {
+ if (recognizer_id >= m_recognizers.size())
+ return false;
+ auto found =
+ llvm::find_if(m_recognizers, [recognizer_id](const RegisteredEntry &e) {
+ return e.recognizer_id == recognizer_id;
+ });
+ if (found == m_recognizers.end())
+ return false;
+ m_recognizers.erase(found);
+ return true;
}
-void StackFrameRecognizerManager::AddRecognizer(
- StackFrameRecognizerSP recognizer, RegularExpressionSP module,
- RegularExpressionSP symbol, bool first_instruction_only) {
- GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
- first_instruction_only);
+void StackFrameRecognizerManager::RemoveAllRecognizers() {
+ m_recognizers.clear();
}
-void StackFrameRecognizerManager::ForEach(
- std::function<void(uint32_t recognized_id, std::string recognizer_name,
- std::string module, llvm::ArrayRef<ConstString> symbols,
- bool regexp)> const &callback) {
- GetStackFrameRecognizerManagerImpl().ForEach(callback);
-}
+StackFrameRecognizerSP
+StackFrameRecognizerManager::GetRecognizerForFrame(StackFrameSP frame) {
+ const SymbolContext &symctx = frame->GetSymbolContext(
+ eSymbolContextModule | eSymbolContextFunction | eSymbolContextSymbol);
+ ConstString function_name = symctx.GetFunctionName();
+ ModuleSP module_sp = symctx.module_sp;
+ if (!module_sp)
+ return StackFrameRecognizerSP();
+ ConstString module_name = module_sp->GetFileSpec().GetFilename();
+ Symbol *symbol = symctx.symbol;
+ if (!symbol)
+ return StackFrameRecognizerSP();
+ Address start_addr = symbol->GetAddress();
+ Address current_addr = frame->GetFrameCodeAddress();
-void StackFrameRecognizerManager::RemoveAllRecognizers() {
- GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers();
-}
+ for (auto entry : m_recognizers) {
+ if (entry.module)
+ if (entry.module != module_name)
+ continue;
-bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) {
- return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id);
-}
+ if (entry.module_regexp)
+ if (!entry.module_regexp->Execute(module_name.GetStringRef()))
+ continue;
-RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame(
- StackFrameSP frame) {
- return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame);
+ if (!entry.symbols.empty())
+ if (!llvm::is_contained(entry.symbols, function_name))
+ continue;
+
+ if (entry.symbol_regexp)
+ if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
+ continue;
+
+ if (entry.first_instruction_only)
+ if (start_addr != current_addr)
+ continue;
+
+ return entry.recognizer;
+ }
+ return StackFrameRecognizerSP();
}
-StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame(
- lldb::StackFrameSP frame) {
- return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame);
+RecognizedStackFrameSP
+StackFrameRecognizerManager::RecognizeFrame(StackFrameSP frame) {
+ auto recognizer = GetRecognizerForFrame(frame);
+ if (!recognizer)
+ return RecognizedStackFrameSP();
+ return recognizer->RecognizeFrame(frame);
}
diff --git a/contrib/llvm-project/lldb/source/Target/SystemRuntime.cpp b/contrib/llvm-project/lldb/source/Target/SystemRuntime.cpp
index cd3d8ba2c7b0..6d8a2ef55225 100644
--- a/contrib/llvm-project/lldb/source/Target/SystemRuntime.cpp
+++ b/contrib/llvm-project/lldb/source/Target/SystemRuntime.cpp
@@ -27,9 +27,7 @@ SystemRuntime *SystemRuntime::FindPlugin(Process *process) {
return nullptr;
}
-// SystemRuntime constructor
-SystemRuntime::SystemRuntime(Process *process)
- : m_process(process), m_types() {}
+SystemRuntime::SystemRuntime(Process *process) : Runtime(process), m_types() {}
SystemRuntime::~SystemRuntime() = default;
@@ -39,7 +37,7 @@ void SystemRuntime::DidLaunch() {}
void SystemRuntime::Detach() {}
-void SystemRuntime::ModulesDidLoad(ModuleList &module_list) {}
+void SystemRuntime::ModulesDidLoad(const ModuleList &module_list) {}
const std::vector<ConstString> &SystemRuntime::GetExtendedBacktraceTypes() {
return m_types;
diff --git a/contrib/llvm-project/lldb/source/Target/Target.cpp b/contrib/llvm-project/lldb/source/Target/Target.cpp
index 19d0c3d477eb..736864e021bb 100644
--- a/contrib/llvm-project/lldb/source/Target/Target.cpp
+++ b/contrib/llvm-project/lldb/source/Target/Target.cpp
@@ -27,9 +27,11 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -45,6 +47,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
@@ -94,6 +97,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
m_valid(true), m_suppress_stop_hooks(false),
m_is_dummy_target(is_dummy_target),
+ m_frame_recognizer_manager_up(
+ std::make_unique<StackFrameRecognizerManager>()),
m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))
{
@@ -123,13 +128,10 @@ Target::~Target() {
DeleteCurrentProcess();
}
-void Target::PrimeFromDummyTarget(Target *target) {
- if (!target)
- return;
-
- m_stop_hooks = target->m_stop_hooks;
+void Target::PrimeFromDummyTarget(Target &target) {
+ m_stop_hooks = target.m_stop_hooks;
- for (const auto &breakpoint_sp : target->m_breakpoint_list.Breakpoints()) {
+ for (const auto &breakpoint_sp : target.m_breakpoint_list.Breakpoints()) {
if (breakpoint_sp->IsInternal())
continue;
@@ -138,11 +140,14 @@ void Target::PrimeFromDummyTarget(Target *target) {
AddBreakpoint(std::move(new_bp), false);
}
- for (auto bp_name_entry : target->m_breakpoint_names) {
+ for (auto bp_name_entry : target.m_breakpoint_names) {
BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second);
AddBreakpointName(new_bp_name);
}
+
+ m_frame_recognizer_manager_up = std::make_unique<StackFrameRecognizerManager>(
+ *target.m_frame_recognizer_manager_up);
}
void Target::Dump(Stream *s, lldb::DescriptionLevel description_level) {
@@ -194,12 +199,13 @@ void Target::DeleteCurrentProcess() {
const lldb::ProcessSP &Target::CreateProcess(ListenerSP listener_sp,
llvm::StringRef plugin_name,
- const FileSpec *crash_file) {
+ const FileSpec *crash_file,
+ bool can_connect) {
if (!listener_sp)
listener_sp = GetDebugger().GetListener();
DeleteCurrentProcess();
m_process_sp = Process::FindPlugin(shared_from_this(), plugin_name,
- listener_sp, crash_file);
+ listener_sp, crash_file, can_connect);
return m_process_sp;
}
@@ -1394,9 +1400,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
ClearModules(false);
if (executable_sp) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Target::SetExecutableModule (executable = '%s')",
+ LLDB_SCOPED_TIMERF("Target::SetExecutableModule (executable = '%s')",
executable_sp->GetFileSpec().GetPath().c_str());
const bool notify = true;
@@ -2290,27 +2294,29 @@ FunctionCaller *Target::GetFunctionCallerForLanguage(
return persistent_fn;
}
-UtilityFunction *
-Target::GetUtilityFunctionForLanguage(const char *text,
- lldb::LanguageType language,
- const char *name, Status &error) {
+llvm::Expected<std::unique_ptr<UtilityFunction>>
+Target::CreateUtilityFunction(std::string expression, std::string name,
+ lldb::LanguageType language,
+ ExecutionContext &exe_ctx) {
auto type_system_or_err = GetScratchTypeSystemForLanguage(language);
+ if (!type_system_or_err)
+ return type_system_or_err.takeError();
- if (auto err = type_system_or_err.takeError()) {
- error.SetErrorStringWithFormat(
- "Could not find type system for language %s: %s",
- Language::GetNameForLanguageType(language),
- llvm::toString(std::move(err)).c_str());
- return nullptr;
- }
-
- auto *utility_fn = type_system_or_err->GetUtilityFunction(text, name);
+ std::unique_ptr<UtilityFunction> utility_fn =
+ type_system_or_err->CreateUtilityFunction(std::move(expression),
+ std::move(name));
if (!utility_fn)
- error.SetErrorStringWithFormat(
- "Could not create an expression for language %s",
- Language::GetNameForLanguageType(language));
+ return llvm::make_error<llvm::StringError>(
+ llvm::StringRef("Could not create an expression for language") +
+ Language::GetNameForLanguageType(language),
+ llvm::inconvertibleErrorCode());
- return utility_fn;
+ DiagnosticManager diagnostics;
+ if (!utility_fn->Install(diagnostics, exe_ctx))
+ return llvm::make_error<llvm::StringError>(diagnostics.GetString(),
+ llvm::inconvertibleErrorCode());
+
+ return std::move(utility_fn);
}
void Target::SettingsInitialize() { Process::SettingsInitialize(); }
@@ -2532,13 +2538,28 @@ ClangModulesDeclVendor *Target::GetClangModulesDeclVendor() {
return m_clang_modules_decl_vendor_up.get();
}
-Target::StopHookSP Target::CreateStopHook() {
+Target::StopHookSP Target::CreateStopHook(StopHook::StopHookKind kind) {
lldb::user_id_t new_uid = ++m_stop_hook_next_id;
- Target::StopHookSP stop_hook_sp(new StopHook(shared_from_this(), new_uid));
+ Target::StopHookSP stop_hook_sp;
+ switch (kind) {
+ case StopHook::StopHookKind::CommandBased:
+ stop_hook_sp.reset(new StopHookCommandLine(shared_from_this(), new_uid));
+ break;
+ case StopHook::StopHookKind::ScriptBased:
+ stop_hook_sp.reset(new StopHookScripted(shared_from_this(), new_uid));
+ break;
+ }
m_stop_hooks[new_uid] = stop_hook_sp;
return stop_hook_sp;
}
+void Target::UndoCreateStopHook(lldb::user_id_t user_id) {
+ if (!RemoveStopHookByID(user_id))
+ return;
+ if (user_id == m_stop_hook_next_id)
+ m_stop_hook_next_id--;
+}
+
bool Target::RemoveStopHookByID(lldb::user_id_t user_id) {
size_t num_removed = m_stop_hooks.erase(user_id);
return (num_removed != 0);
@@ -2574,45 +2595,39 @@ void Target::SetAllStopHooksActiveState(bool active_state) {
}
}
-void Target::RunStopHooks() {
+bool Target::RunStopHooks() {
if (m_suppress_stop_hooks)
- return;
+ return false;
if (!m_process_sp)
- return;
+ return false;
// Somebody might have restarted the process:
+ // Still return false, the return value is about US restarting the target.
if (m_process_sp->GetState() != eStateStopped)
- return;
+ return false;
// <rdar://problem/12027563> make sure we check that we are not stopped
// because of us running a user expression since in that case we do not want
// to run the stop-hooks
if (m_process_sp->GetModIDRef().IsLastResumeForUserExpression())
- return;
+ return false;
if (m_stop_hooks.empty())
- return;
-
- StopHookCollection::iterator pos, end = m_stop_hooks.end();
+ return false;
// If there aren't any active stop hooks, don't bother either.
- // Also see if any of the active hooks want to auto-continue.
bool any_active_hooks = false;
- bool auto_continue = false;
for (auto hook : m_stop_hooks) {
if (hook.second->IsActive()) {
any_active_hooks = true;
- auto_continue |= hook.second->GetAutoContinue();
+ break;
}
}
if (!any_active_hooks)
- return;
-
- CommandReturnObject result(m_debugger.GetUseColor());
+ return false;
std::vector<ExecutionContext> exc_ctx_with_reasons;
- std::vector<SymbolContext> sym_ctx_with_reasons;
ThreadList &cur_threadlist = m_process_sp->GetThreadList();
size_t num_threads = cur_threadlist.GetSize();
@@ -2620,103 +2635,127 @@ void Target::RunStopHooks() {
lldb::ThreadSP cur_thread_sp = cur_threadlist.GetThreadAtIndex(i);
if (cur_thread_sp->ThreadStoppedForAReason()) {
lldb::StackFrameSP cur_frame_sp = cur_thread_sp->GetStackFrameAtIndex(0);
- exc_ctx_with_reasons.push_back(ExecutionContext(
- m_process_sp.get(), cur_thread_sp.get(), cur_frame_sp.get()));
- sym_ctx_with_reasons.push_back(
- cur_frame_sp->GetSymbolContext(eSymbolContextEverything));
+ exc_ctx_with_reasons.emplace_back(m_process_sp.get(), cur_thread_sp.get(),
+ cur_frame_sp.get());
}
}
// If no threads stopped for a reason, don't run the stop-hooks.
size_t num_exe_ctx = exc_ctx_with_reasons.size();
if (num_exe_ctx == 0)
- return;
+ return false;
- result.SetImmediateOutputStream(m_debugger.GetAsyncOutputStream());
- result.SetImmediateErrorStream(m_debugger.GetAsyncErrorStream());
+ StreamSP output_sp = m_debugger.GetAsyncOutputStream();
- bool keep_going = true;
+ bool auto_continue = false;
bool hooks_ran = false;
bool print_hook_header = (m_stop_hooks.size() != 1);
bool print_thread_header = (num_exe_ctx != 1);
- bool did_restart = false;
+ bool should_stop = false;
+ bool somebody_restarted = false;
- for (pos = m_stop_hooks.begin(); keep_going && pos != end; pos++) {
- // result.Clear();
- StopHookSP cur_hook_sp = (*pos).second;
+ for (auto stop_entry : m_stop_hooks) {
+ StopHookSP cur_hook_sp = stop_entry.second;
if (!cur_hook_sp->IsActive())
continue;
bool any_thread_matched = false;
- for (size_t i = 0; keep_going && i < num_exe_ctx; i++) {
- if ((cur_hook_sp->GetSpecifier() == nullptr ||
- cur_hook_sp->GetSpecifier()->SymbolContextMatches(
- sym_ctx_with_reasons[i])) &&
- (cur_hook_sp->GetThreadSpecifier() == nullptr ||
- cur_hook_sp->GetThreadSpecifier()->ThreadPassesBasicTests(
- exc_ctx_with_reasons[i].GetThreadRef()))) {
- if (!hooks_ran) {
- hooks_ran = true;
- }
- if (print_hook_header && !any_thread_matched) {
- const char *cmd =
- (cur_hook_sp->GetCommands().GetSize() == 1
- ? cur_hook_sp->GetCommands().GetStringAtIndex(0)
- : nullptr);
- if (cmd)
- result.AppendMessageWithFormat("\n- Hook %" PRIu64 " (%s)\n",
- cur_hook_sp->GetID(), cmd);
- else
- result.AppendMessageWithFormat("\n- Hook %" PRIu64 "\n",
- cur_hook_sp->GetID());
- any_thread_matched = true;
- }
+ for (auto exc_ctx : exc_ctx_with_reasons) {
+ // We detect somebody restarted in the stop-hook loop, and broke out of
+ // that loop back to here. So break out of here too.
+ if (somebody_restarted)
+ break;
- if (print_thread_header)
- result.AppendMessageWithFormat(
- "-- Thread %d\n",
- exc_ctx_with_reasons[i].GetThreadPtr()->GetIndexID());
-
- CommandInterpreterRunOptions options;
- options.SetStopOnContinue(true);
- options.SetStopOnError(true);
- options.SetEchoCommands(false);
- options.SetPrintResults(true);
- options.SetPrintErrors(true);
- options.SetAddToHistory(false);
-
- // Force Async:
- bool old_async = GetDebugger().GetAsyncExecution();
- GetDebugger().SetAsyncExecution(true);
- GetDebugger().GetCommandInterpreter().HandleCommands(
- cur_hook_sp->GetCommands(), &exc_ctx_with_reasons[i], options,
- result);
- GetDebugger().SetAsyncExecution(old_async);
- // If the command started the target going again, we should bag out of
- // running the stop hooks.
- if ((result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
- (result.GetStatus() == eReturnStatusSuccessContinuingResult)) {
- // But only complain if there were more stop hooks to do:
- StopHookCollection::iterator tmp = pos;
- if (++tmp != end)
- result.AppendMessageWithFormat(
- "\nAborting stop hooks, hook %" PRIu64
- " set the program running.\n"
- " Consider using '-G true' to make "
- "stop hooks auto-continue.\n",
- cur_hook_sp->GetID());
- keep_going = false;
- did_restart = true;
- }
+ if (!cur_hook_sp->ExecutionContextPasses(exc_ctx))
+ continue;
+
+ // We only consult the auto-continue for a stop hook if it matched the
+ // specifier.
+ auto_continue |= cur_hook_sp->GetAutoContinue();
+
+ if (!hooks_ran)
+ hooks_ran = true;
+
+ if (print_hook_header && !any_thread_matched) {
+ StreamString s;
+ cur_hook_sp->GetDescription(&s, eDescriptionLevelBrief);
+ if (s.GetSize() != 0)
+ output_sp->Printf("\n- Hook %" PRIu64 " (%s)\n", cur_hook_sp->GetID(),
+ s.GetData());
+ else
+ output_sp->Printf("\n- Hook %" PRIu64 "\n", cur_hook_sp->GetID());
+ any_thread_matched = true;
+ }
+
+ if (print_thread_header)
+ output_sp->Printf("-- Thread %d\n",
+ exc_ctx.GetThreadPtr()->GetIndexID());
+
+ StopHook::StopHookResult this_result =
+ cur_hook_sp->HandleStop(exc_ctx, output_sp);
+ bool this_should_stop = true;
+
+ switch (this_result) {
+ case StopHook::StopHookResult::KeepStopped:
+ // If this hook is set to auto-continue that should override the
+ // HandleStop result...
+ if (cur_hook_sp->GetAutoContinue())
+ this_should_stop = false;
+ else
+ this_should_stop = true;
+
+ break;
+ case StopHook::StopHookResult::RequestContinue:
+ this_should_stop = false;
+ break;
+ case StopHook::StopHookResult::AlreadyContinued:
+ // We don't have a good way to prohibit people from restarting the
+ // target willy nilly in a stop hook. If the hook did so, give a
+ // gentle suggestion here and bag out if the hook processing.
+ output_sp->Printf("\nAborting stop hooks, hook %" PRIu64
+ " set the program running.\n"
+ " Consider using '-G true' to make "
+ "stop hooks auto-continue.\n",
+ cur_hook_sp->GetID());
+ somebody_restarted = true;
+ break;
}
+ // If we're already restarted, stop processing stop hooks.
+ // FIXME: if we are doing non-stop mode for real, we would have to
+ // check that OUR thread was restarted, otherwise we should keep
+ // processing stop hooks.
+ if (somebody_restarted)
+ break;
+
+ // If anybody wanted to stop, we should all stop.
+ if (!should_stop)
+ should_stop = this_should_stop;
}
}
+
+ output_sp->Flush();
+
+ // If one of the commands in the stop hook already restarted the target,
+ // report that fact.
+ if (somebody_restarted)
+ return true;
+
// Finally, if auto-continue was requested, do it now:
- if (!did_restart && auto_continue)
- m_process_sp->PrivateResume();
+ // We only compute should_stop against the hook results if a hook got to run
+ // which is why we have to do this conjoint test.
+ if ((hooks_ran && !should_stop) || auto_continue) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Status error = m_process_sp->PrivateResume();
+ if (error.Success()) {
+ LLDB_LOG(log, "Resuming from RunStopHooks");
+ return true;
+ } else {
+ LLDB_LOG(log, "Resuming from RunStopHooks failed: {0}", error);
+ return false;
+ }
+ }
- result.GetImmediateOutputStream()->Flush();
- result.GetImmediateErrorStream()->Flush();
+ return false;
}
const TargetPropertiesSP &Target::GetGlobalProperties() {
@@ -2935,7 +2974,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
} else {
// Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess(launch_info.GetListener(), plugin_name, nullptr);
+ CreateProcess(launch_info.GetListener(), plugin_name, nullptr, false);
}
// Since we didn't have a platform launch the process, launch it here.
@@ -2943,80 +2982,79 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
error = m_process_sp->Launch(launch_info);
}
- if (!m_process_sp) {
- if (error.Success())
- error.SetErrorString("failed to launch or debug process");
+ if (!m_process_sp && error.Success())
+ error.SetErrorString("failed to launch or debug process");
+
+ if (!error.Success())
return error;
- }
- if (error.Success()) {
- if (synchronous_execution ||
- !launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)) {
- ListenerSP hijack_listener_sp(launch_info.GetHijackListener());
- if (!hijack_listener_sp) {
- hijack_listener_sp =
- Listener::MakeListener("lldb.Target.Launch.hijack");
- launch_info.SetHijackListener(hijack_listener_sp);
- m_process_sp->HijackProcessEvents(hijack_listener_sp);
- }
+ auto at_exit =
+ llvm::make_scope_exit([&]() { m_process_sp->RestoreProcessEvents(); });
- StateType state = m_process_sp->WaitForProcessToStop(
- llvm::None, nullptr, false, hijack_listener_sp, nullptr);
-
- if (state == eStateStopped) {
- if (!launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)) {
- if (synchronous_execution) {
- // Now we have handled the stop-from-attach, and we are just
- // switching to a synchronous resume. So we should switch to the
- // SyncResume hijacker.
- m_process_sp->RestoreProcessEvents();
- m_process_sp->ResumeSynchronous(stream);
- } else {
- m_process_sp->RestoreProcessEvents();
- error = m_process_sp->PrivateResume();
- }
- if (!error.Success()) {
- Status error2;
- error2.SetErrorStringWithFormat(
- "process resume at entry point failed: %s", error.AsCString());
- error = error2;
- }
- }
- } else if (state == eStateExited) {
- bool with_shell = !!launch_info.GetShell();
- const int exit_status = m_process_sp->GetExitStatus();
- const char *exit_desc = m_process_sp->GetExitDescription();
-#define LAUNCH_SHELL_MESSAGE \
- "\n'r' and 'run' are aliases that default to launching through a " \
- "shell.\nTry launching without going through a shell by using 'process " \
- "launch'."
- if (exit_desc && exit_desc[0]) {
- if (with_shell)
- error.SetErrorStringWithFormat(
- "process exited with status %i (%s)" LAUNCH_SHELL_MESSAGE,
- exit_status, exit_desc);
- else
- error.SetErrorStringWithFormat("process exited with status %i (%s)",
- exit_status, exit_desc);
- } else {
- if (with_shell)
- error.SetErrorStringWithFormat(
- "process exited with status %i" LAUNCH_SHELL_MESSAGE,
- exit_status);
- else
- error.SetErrorStringWithFormat("process exited with status %i",
- exit_status);
- }
- } else {
- error.SetErrorStringWithFormat(
- "initial process state wasn't stopped: %s", StateAsCString(state));
- }
+ if (!synchronous_execution &&
+ launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
+ return error;
+
+ ListenerSP hijack_listener_sp(launch_info.GetHijackListener());
+ if (!hijack_listener_sp) {
+ hijack_listener_sp = Listener::MakeListener("lldb.Target.Launch.hijack");
+ launch_info.SetHijackListener(hijack_listener_sp);
+ m_process_sp->HijackProcessEvents(hijack_listener_sp);
+ }
+
+ switch (m_process_sp->WaitForProcessToStop(llvm::None, nullptr, false,
+ hijack_listener_sp, nullptr)) {
+ case eStateStopped: {
+ if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
+ break;
+ if (synchronous_execution) {
+ // Now we have handled the stop-from-attach, and we are just
+ // switching to a synchronous resume. So we should switch to the
+ // SyncResume hijacker.
+ m_process_sp->RestoreProcessEvents();
+ m_process_sp->ResumeSynchronous(stream);
+ } else {
+ m_process_sp->RestoreProcessEvents();
+ error = m_process_sp->PrivateResume();
+ }
+ if (!error.Success()) {
+ Status error2;
+ error2.SetErrorStringWithFormat(
+ "process resume at entry point failed: %s", error.AsCString());
+ error = error2;
}
- m_process_sp->RestoreProcessEvents();
+ } break;
+ case eStateExited: {
+ bool with_shell = !!launch_info.GetShell();
+ const int exit_status = m_process_sp->GetExitStatus();
+ const char *exit_desc = m_process_sp->GetExitDescription();
+ std::string desc;
+ if (exit_desc && exit_desc[0])
+ desc = " (" + std::string(exit_desc) + ')';
+ if (with_shell)
+ error.SetErrorStringWithFormat(
+ "process exited with status %i%s\n"
+ "'r' and 'run' are aliases that default to launching through a "
+ "shell.\n"
+ "Try launching without going through a shell by using "
+ "'process launch'.",
+ exit_status, desc.c_str());
+ else
+ error.SetErrorStringWithFormat("process exited with status %i%s",
+ exit_status, desc.c_str());
+ } break;
+ default:
+ error.SetErrorStringWithFormat("initial process state wasn't stopped: %s",
+ StateAsCString(state));
+ break;
}
return error;
}
+void Target::SetTrace(const TraceSP &trace_sp) { m_trace_sp = trace_sp; }
+
+const TraceSP &Target::GetTrace() { return m_trace_sp; }
+
Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
auto state = eStateInvalid;
auto process_sp = GetProcessSP();
@@ -3064,7 +3102,7 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
const char *plugin_name = attach_info.GetProcessPluginName();
process_sp =
CreateProcess(attach_info.GetListenerForProcess(GetDebugger()),
- plugin_name, nullptr);
+ plugin_name, nullptr, false);
if (process_sp == nullptr) {
error.SetErrorStringWithFormat(
"failed to create process using plugin %s",
@@ -3181,20 +3219,17 @@ void Target::FinalizeFileActions(ProcessLaunchInfo &info) {
// Target::StopHook
Target::StopHook::StopHook(lldb::TargetSP target_sp, lldb::user_id_t uid)
- : UserID(uid), m_target_sp(target_sp), m_commands(), m_specifier_sp(),
+ : UserID(uid), m_target_sp(target_sp), m_specifier_sp(),
m_thread_spec_up() {}
Target::StopHook::StopHook(const StopHook &rhs)
: UserID(rhs.GetID()), m_target_sp(rhs.m_target_sp),
- m_commands(rhs.m_commands), m_specifier_sp(rhs.m_specifier_sp),
- m_thread_spec_up(), m_active(rhs.m_active),
- m_auto_continue(rhs.m_auto_continue) {
+ m_specifier_sp(rhs.m_specifier_sp), m_thread_spec_up(),
+ m_active(rhs.m_active), m_auto_continue(rhs.m_auto_continue) {
if (rhs.m_thread_spec_up)
m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
}
-Target::StopHook::~StopHook() = default;
-
void Target::StopHook::SetSpecifier(SymbolContextSpecifier *specifier) {
m_specifier_sp.reset(specifier);
}
@@ -3203,8 +3238,31 @@ void Target::StopHook::SetThreadSpecifier(ThreadSpec *specifier) {
m_thread_spec_up.reset(specifier);
}
+bool Target::StopHook::ExecutionContextPasses(const ExecutionContext &exc_ctx) {
+ SymbolContextSpecifier *specifier = GetSpecifier();
+ if (!specifier)
+ return true;
+
+ bool will_run = true;
+ if (exc_ctx.GetFramePtr())
+ will_run = GetSpecifier()->SymbolContextMatches(
+ exc_ctx.GetFramePtr()->GetSymbolContext(eSymbolContextEverything));
+ if (will_run && GetThreadSpecifier() != nullptr)
+ will_run =
+ GetThreadSpecifier()->ThreadPassesBasicTests(exc_ctx.GetThreadRef());
+
+ return will_run;
+}
+
void Target::StopHook::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
+
+ // For brief descriptions, only print the subclass description:
+ if (level == eDescriptionLevelBrief) {
+ GetSubclassDescription(s, level);
+ return;
+ }
+
unsigned indent_level = s->GetIndentLevel();
s->SetIndentLevel(indent_level + 2);
@@ -3235,15 +3293,155 @@ void Target::StopHook::GetDescription(Stream *s,
s->PutCString("\n");
s->SetIndentLevel(indent_level + 2);
}
+ GetSubclassDescription(s, level);
+}
+void Target::StopHookCommandLine::GetSubclassDescription(
+ Stream *s, lldb::DescriptionLevel level) const {
+ // The brief description just prints the first command.
+ if (level == eDescriptionLevelBrief) {
+ if (m_commands.GetSize() == 1)
+ s->PutCString(m_commands.GetStringAtIndex(0));
+ return;
+ }
s->Indent("Commands: \n");
- s->SetIndentLevel(indent_level + 4);
+ s->SetIndentLevel(s->GetIndentLevel() + 4);
uint32_t num_commands = m_commands.GetSize();
for (uint32_t i = 0; i < num_commands; i++) {
s->Indent(m_commands.GetStringAtIndex(i));
s->PutCString("\n");
}
- s->SetIndentLevel(indent_level);
+ s->SetIndentLevel(s->GetIndentLevel() - 4);
+}
+
+// Target::StopHookCommandLine
+void Target::StopHookCommandLine::SetActionFromString(const std::string &string) {
+ GetCommands().SplitIntoLines(string);
+}
+
+void Target::StopHookCommandLine::SetActionFromStrings(
+ const std::vector<std::string> &strings) {
+ for (auto string : strings)
+ GetCommands().AppendString(string.c_str());
+}
+
+Target::StopHook::StopHookResult
+Target::StopHookCommandLine::HandleStop(ExecutionContext &exc_ctx,
+ StreamSP output_sp) {
+ assert(exc_ctx.GetTargetPtr() && "Can't call PerformAction on a context "
+ "with no target");
+
+ if (!m_commands.GetSize())
+ return StopHookResult::KeepStopped;
+
+ CommandReturnObject result(false);
+ result.SetImmediateOutputStream(output_sp);
+ result.SetInteractive(false);
+ Debugger &debugger = exc_ctx.GetTargetPtr()->GetDebugger();
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue(true);
+ options.SetStopOnError(true);
+ options.SetEchoCommands(false);
+ options.SetPrintResults(true);
+ options.SetPrintErrors(true);
+ options.SetAddToHistory(false);
+
+ // Force Async:
+ bool old_async = debugger.GetAsyncExecution();
+ debugger.SetAsyncExecution(true);
+ debugger.GetCommandInterpreter().HandleCommands(GetCommands(), &exc_ctx,
+ options, result);
+ debugger.SetAsyncExecution(old_async);
+ lldb::ReturnStatus status = result.GetStatus();
+ if (status == eReturnStatusSuccessContinuingNoResult ||
+ status == eReturnStatusSuccessContinuingResult)
+ return StopHookResult::AlreadyContinued;
+ return StopHookResult::KeepStopped;
+}
+
+// Target::StopHookScripted
+Status Target::StopHookScripted::SetScriptCallback(
+ std::string class_name, StructuredData::ObjectSP extra_args_sp) {
+ Status error;
+
+ ScriptInterpreter *script_interp =
+ GetTarget()->GetDebugger().GetScriptInterpreter();
+ if (!script_interp) {
+ error.SetErrorString("No script interpreter installed.");
+ return error;
+ }
+
+ m_class_name = class_name;
+
+ m_extra_args = new StructuredDataImpl();
+
+ if (extra_args_sp)
+ m_extra_args->SetObjectSP(extra_args_sp);
+
+ m_implementation_sp = script_interp->CreateScriptedStopHook(
+ GetTarget(), m_class_name.c_str(), m_extra_args, error);
+
+ return error;
+}
+
+Target::StopHook::StopHookResult
+Target::StopHookScripted::HandleStop(ExecutionContext &exc_ctx,
+ StreamSP output_sp) {
+ assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context "
+ "with no target");
+
+ ScriptInterpreter *script_interp =
+ GetTarget()->GetDebugger().GetScriptInterpreter();
+ if (!script_interp)
+ return StopHookResult::KeepStopped;
+
+ bool should_stop = script_interp->ScriptedStopHookHandleStop(
+ m_implementation_sp, exc_ctx, output_sp);
+
+ return should_stop ? StopHookResult::KeepStopped
+ : StopHookResult::RequestContinue;
+}
+
+void Target::StopHookScripted::GetSubclassDescription(
+ Stream *s, lldb::DescriptionLevel level) const {
+ if (level == eDescriptionLevelBrief) {
+ s->PutCString(m_class_name);
+ return;
+ }
+ s->Indent("Class:");
+ s->Printf("%s\n", m_class_name.c_str());
+
+ // Now print the extra args:
+ // FIXME: We should use StructuredData.GetDescription on the m_extra_args
+ // but that seems to rely on some printing plugin that doesn't exist.
+ if (!m_extra_args->IsValid())
+ return;
+ StructuredData::ObjectSP object_sp = m_extra_args->GetObjectSP();
+ if (!object_sp || !object_sp->IsValid())
+ return;
+
+ StructuredData::Dictionary *as_dict = object_sp->GetAsDictionary();
+ if (!as_dict || !as_dict->IsValid())
+ return;
+
+ uint32_t num_keys = as_dict->GetSize();
+ if (num_keys == 0)
+ return;
+
+ s->Indent("Args:\n");
+ s->SetIndentLevel(s->GetIndentLevel() + 4);
+
+ auto print_one_element = [&s](ConstString key,
+ StructuredData::Object *object) {
+ s->Indent();
+ s->Printf("%s : %s\n", key.GetCString(),
+ object->GetStringValue().str().c_str());
+ return true;
+ };
+
+ as_dict->ForEach(print_one_element);
+
+ s->SetIndentLevel(s->GetIndentLevel() - 4);
}
static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
@@ -3316,6 +3514,28 @@ static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
},
};
+static constexpr OptionEnumValueElement g_import_std_module_value_types[] = {
+ {
+ eImportStdModuleFalse,
+ "false",
+ "Never import the 'std' C++ module in the expression parser.",
+ },
+ {
+ eImportStdModuleFallback,
+ "fallback",
+ "Retry evaluating expressions with an imported 'std' C++ module if they"
+ " failed to parse without the module. This allows evaluating more "
+ "complex expressions involving C++ standard library types."
+ },
+ {
+ eImportStdModuleTrue,
+ "true",
+ "Always import the 'std' C++ module. This allows evaluating more "
+ "complex expressions involving C++ standard library types. This feature"
+ " is experimental."
+ },
+};
+
static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = {
{
Disassembler::eHexStyleC,
@@ -3478,6 +3698,8 @@ TargetProperties::TargetProperties(Target *target)
m_collection_sp->SetValueChangedCallback(
ePropertyDisableASLR, [this] { DisableASLRValueChangedCallback(); });
m_collection_sp->SetValueChangedCallback(
+ ePropertyInheritTCC, [this] { InheritTCCValueChangedCallback(); });
+ m_collection_sp->SetValueChangedCallback(
ePropertyDisableSTDIO, [this] { DisableSTDIOValueChangedCallback(); });
m_experimental_properties_up =
@@ -3515,6 +3737,7 @@ void TargetProperties::UpdateLaunchInfoFromProperties() {
ErrorPathValueChangedCallback();
DetachOnErrorValueChangedCallback();
DisableASLRValueChangedCallback();
+ InheritTCCValueChangedCallback();
DisableSTDIOValueChangedCallback();
}
@@ -3597,6 +3820,17 @@ void TargetProperties::SetDisableASLR(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
+bool TargetProperties::GetInheritTCC() const {
+ const uint32_t idx = ePropertyInheritTCC;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetInheritTCC(bool b) {
+ const uint32_t idx = ePropertyInheritTCC;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
bool TargetProperties::GetDetachOnError() const {
const uint32_t idx = ePropertyDetachOnError;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -3755,10 +3989,10 @@ bool TargetProperties::GetEnableAutoImportClangModules() const {
nullptr, idx, g_target_properties[idx].default_uint_value != 0);
}
-bool TargetProperties::GetEnableImportStdModule() const {
+ImportStdModule TargetProperties::GetImportStdModule() const {
const uint32_t idx = ePropertyImportStdModule;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return (ImportStdModule)m_collection_sp->GetPropertyAtIndexAsEnumeration(
+ nullptr, idx, g_target_properties[idx].default_uint_value);
}
bool TargetProperties::GetEnableAutoApplyFixIts() const {
@@ -3869,6 +4103,12 @@ llvm::StringRef TargetProperties::GetExpressionPrefixContents() {
return "";
}
+uint64_t TargetProperties::GetExprErrorLimit() const {
+ const uint32_t idx = ePropertyExprErrorLimit;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_target_properties[idx].default_uint_value);
+}
+
bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() {
const uint32_t idx = ePropertyBreakpointUseAvoidList;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -3988,6 +4228,8 @@ void TargetProperties::SetProcessLaunchInfo(
}
SetDetachOnError(launch_info.GetFlags().Test(lldb::eLaunchFlagDetachOnError));
SetDisableASLR(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableASLR));
+ SetInheritTCC(
+ launch_info.GetFlags().Test(lldb::eLaunchFlagInheritTCCFromParent));
SetDisableSTDIO(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableSTDIO));
}
@@ -4051,6 +4293,13 @@ void TargetProperties::DisableASLRValueChangedCallback() {
m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableASLR);
}
+void TargetProperties::InheritTCCValueChangedCallback() {
+ if (GetInheritTCC())
+ m_launch_info.GetFlags().Set(lldb::eLaunchFlagInheritTCCFromParent);
+ else
+ m_launch_info.GetFlags().Clear(lldb::eLaunchFlagInheritTCCFromParent);
+}
+
void TargetProperties::DisableSTDIOValueChangedCallback() {
if (GetDisableSTDIO())
m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableSTDIO);
diff --git a/contrib/llvm-project/lldb/source/Target/TargetList.cpp b/contrib/llvm-project/lldb/source/Target/TargetList.cpp
index 3974cb5de419..1e5856dd0b22 100644
--- a/contrib/llvm-project/lldb/source/Target/TargetList.cpp
+++ b/contrib/llvm-project/lldb/source/Target/TargetList.cpp
@@ -42,21 +42,19 @@ TargetList::TargetList(Debugger &debugger)
CheckInWithManager();
}
-// Destructor
-TargetList::~TargetList() {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- m_target_list.clear();
-}
-
Status TargetList::CreateTarget(Debugger &debugger,
llvm::StringRef user_exe_path,
llvm::StringRef triple_str,
LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
TargetSP &target_sp) {
- return CreateTargetInternal(debugger, user_exe_path, triple_str,
- load_dependent_files, platform_options, target_sp,
- false);
+ auto result = TargetList::CreateTargetInternal(
+ debugger, user_exe_path, triple_str, load_dependent_files,
+ platform_options, target_sp);
+
+ if (target_sp && result.Success())
+ AddTargetInternal(target_sp, /*do_select*/ true);
+ return result;
}
Status TargetList::CreateTarget(Debugger &debugger,
@@ -64,66 +62,72 @@ Status TargetList::CreateTarget(Debugger &debugger,
const ArchSpec &specified_arch,
LoadDependentFiles load_dependent_files,
PlatformSP &platform_sp, TargetSP &target_sp) {
- return CreateTargetInternal(debugger, user_exe_path, specified_arch,
- load_dependent_files, platform_sp, target_sp,
- false);
+ auto result = TargetList::CreateTargetInternal(
+ debugger, user_exe_path, specified_arch, load_dependent_files,
+ platform_sp, target_sp);
+
+ if (target_sp && result.Success())
+ AddTargetInternal(target_sp, /*do_select*/ true);
+ return result;
}
Status TargetList::CreateTargetInternal(
Debugger &debugger, llvm::StringRef user_exe_path,
llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
- const OptionGroupPlatform *platform_options, TargetSP &target_sp,
- bool is_dummy_target) {
+ const OptionGroupPlatform *platform_options, TargetSP &target_sp) {
Status error;
- PlatformSP platform_sp;
- // This is purposely left empty unless it is specified by triple_cstr. If not
- // initialized via triple_cstr, then the currently selected platform will set
- // the architecture correctly.
+ // Let's start by looking at the selected platform.
+ PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
+
+ // This variable corresponds to the architecture specified by the triple
+ // string. If that string was empty the currently selected platform will
+ // determine the architecture.
const ArchSpec arch(triple_str);
- if (!triple_str.empty()) {
- if (!arch.IsValid()) {
- error.SetErrorStringWithFormat("invalid triple '%s'",
- triple_str.str().c_str());
- return error;
- }
+ if (!triple_str.empty() && !arch.IsValid()) {
+ error.SetErrorStringWithFormat("invalid triple '%s'",
+ triple_str.str().c_str());
+ return error;
}
ArchSpec platform_arch(arch);
- bool prefer_platform_arch = false;
-
- CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
-
- // let's see if there is already an existing platform before we go creating
- // another...
- platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
+ // Create a new platform if a platform was specified in the platform options
+ // and doesn't match the selected platform.
+ if (platform_options && platform_options->PlatformWasSpecified() &&
+ !platform_options->PlatformMatches(platform_sp)) {
+ const bool select_platform = true;
+ platform_sp = platform_options->CreatePlatformWithOptions(
+ debugger.GetCommandInterpreter(), arch, select_platform, error,
+ platform_arch);
+ if (!platform_sp)
+ return error;
+ }
- if (platform_options && platform_options->PlatformWasSpecified()) {
- // Create a new platform if it doesn't match the selected platform
- if (!platform_options->PlatformMatches(platform_sp)) {
- const bool select_platform = true;
- platform_sp = platform_options->CreatePlatformWithOptions(
- interpreter, arch, select_platform, error, platform_arch);
- if (!platform_sp)
- return error;
+ bool prefer_platform_arch = false;
+ auto update_platform_arch = [&](const ArchSpec &module_arch) {
+ // If the OS or vendor weren't specified, then adopt the module's
+ // architecture so that the platform matching can be more accurate.
+ if (!platform_arch.TripleOSWasSpecified() ||
+ !platform_arch.TripleVendorWasSpecified()) {
+ prefer_platform_arch = true;
+ platform_arch = module_arch;
}
- }
+ };
if (!user_exe_path.empty()) {
- ModuleSpecList module_specs;
- ModuleSpec module_spec;
- module_spec.GetFileSpec().SetFile(user_exe_path, FileSpec::Style::native);
+ ModuleSpec module_spec(FileSpec(user_exe_path, FileSpec::Style::native));
FileSystem::Instance().Resolve(module_spec.GetFileSpec());
-
// Resolve the executable in case we are given a path to a application
- // bundle like a .app bundle on MacOSX
+ // bundle like a .app bundle on MacOSX.
Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
lldb::offset_t file_offset = 0;
lldb::offset_t file_size = 0;
+ ModuleSpecList module_specs;
const size_t num_specs = ObjectFile::GetModuleSpecifications(
module_spec.GetFileSpec(), file_offset, file_size, module_specs);
+
if (num_specs > 0) {
ModuleSpec matching_module_spec;
@@ -134,12 +138,8 @@ Status TargetList::CreateTargetInternal(
matching_module_spec.GetArchitecture())) {
// If the OS or vendor weren't specified, then adopt the module's
// architecture so that the platform matching can be more
- // accurate
- if (!platform_arch.TripleOSWasSpecified() ||
- !platform_arch.TripleVendorWasSpecified()) {
- prefer_platform_arch = true;
- platform_arch = matching_module_spec.GetArchitecture();
- }
+ // accurate.
+ update_platform_arch(matching_module_spec.GetArchitecture());
} else {
StreamString platform_arch_strm;
StreamString module_arch_strm;
@@ -155,128 +155,119 @@ Status TargetList::CreateTargetInternal(
return error;
}
} else {
- // Only one arch and none was specified
+ // Only one arch and none was specified.
prefer_platform_arch = true;
platform_arch = matching_module_spec.GetArchitecture();
}
}
+ } else if (arch.IsValid()) {
+ // Fat binary. A (valid) architecture was specified.
+ module_spec.GetArchitecture() = arch;
+ if (module_specs.FindMatchingModuleSpec(module_spec,
+ matching_module_spec))
+ update_platform_arch(matching_module_spec.GetArchitecture());
} else {
- if (arch.IsValid()) {
- module_spec.GetArchitecture() = arch;
- if (module_specs.FindMatchingModuleSpec(module_spec,
- matching_module_spec)) {
- prefer_platform_arch = true;
- platform_arch = matching_module_spec.GetArchitecture();
- }
- } else {
- // No architecture specified, check if there is only one platform for
- // all of the architectures.
-
- typedef std::vector<PlatformSP> PlatformList;
- PlatformList platforms;
- PlatformSP host_platform_sp = Platform::GetHostPlatform();
- for (size_t i = 0; i < num_specs; ++i) {
- ModuleSpec module_spec;
- if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
- // See if there was a selected platform and check that first
- // since the user may have specified it.
- if (platform_sp) {
- if (platform_sp->IsCompatibleArchitecture(
- module_spec.GetArchitecture(), false, nullptr)) {
- platforms.push_back(platform_sp);
- continue;
- }
- }
-
- // Next check the host platform it if wasn't already checked
- // above
- if (host_platform_sp &&
- (!platform_sp ||
- host_platform_sp->GetName() != platform_sp->GetName())) {
- if (host_platform_sp->IsCompatibleArchitecture(
- module_spec.GetArchitecture(), false, nullptr)) {
- platforms.push_back(host_platform_sp);
- continue;
- }
+ // Fat binary. No architecture specified, check if there is
+ // only one platform for all of the architectures.
+ PlatformSP host_platform_sp = Platform::GetHostPlatform();
+ std::vector<PlatformSP> platforms;
+ for (size_t i = 0; i < num_specs; ++i) {
+ ModuleSpec module_spec;
+ if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
+ // First consider the platform specified by the user, if any, and
+ // the selected platform otherwise.
+ if (platform_sp) {
+ if (platform_sp->IsCompatibleArchitecture(
+ module_spec.GetArchitecture(), false, nullptr)) {
+ platforms.push_back(platform_sp);
+ continue;
}
+ }
- // Just find a platform that matches the architecture in the
- // executable file
- PlatformSP fallback_platform_sp(
- Platform::GetPlatformForArchitecture(
- module_spec.GetArchitecture(), nullptr));
- if (fallback_platform_sp) {
- platforms.push_back(fallback_platform_sp);
+ // Now consider the host platform if it is different from the
+ // specified/selected platform.
+ if (host_platform_sp &&
+ (!platform_sp ||
+ host_platform_sp->GetName() != platform_sp->GetName())) {
+ if (host_platform_sp->IsCompatibleArchitecture(
+ module_spec.GetArchitecture(), false, nullptr)) {
+ platforms.push_back(host_platform_sp);
+ continue;
}
}
- }
- Platform *platform_ptr = nullptr;
- bool more_than_one_platforms = false;
- for (const auto &the_platform_sp : platforms) {
- if (platform_ptr) {
- if (platform_ptr->GetName() != the_platform_sp->GetName()) {
- more_than_one_platforms = true;
- platform_ptr = nullptr;
- break;
- }
- } else {
- platform_ptr = the_platform_sp.get();
+ // Finally find a platform that matches the architecture in the
+ // executable file.
+ PlatformSP fallback_platform_sp(
+ Platform::GetPlatformForArchitecture(
+ module_spec.GetArchitecture(), nullptr));
+ if (fallback_platform_sp) {
+ platforms.push_back(fallback_platform_sp);
}
}
+ }
+ Platform *platform_ptr = nullptr;
+ bool more_than_one_platforms = false;
+ for (const auto &the_platform_sp : platforms) {
if (platform_ptr) {
- // All platforms for all modules in the executable match, so we can
- // select this platform
- platform_sp = platforms.front();
- } else if (!more_than_one_platforms) {
- // No platforms claim to support this file
- error.SetErrorString("No matching platforms found for this file, "
- "specify one with the --platform option");
- return error;
+ if (platform_ptr->GetName() != the_platform_sp->GetName()) {
+ more_than_one_platforms = true;
+ platform_ptr = nullptr;
+ break;
+ }
} else {
- // More than one platform claims to support this file, so the
- // --platform option must be specified
- StreamString error_strm;
- std::set<Platform *> platform_set;
- error_strm.Printf(
- "more than one platform supports this executable (");
- for (const auto &the_platform_sp : platforms) {
- if (platform_set.find(the_platform_sp.get()) ==
- platform_set.end()) {
- if (!platform_set.empty())
- error_strm.PutCString(", ");
- error_strm.PutCString(the_platform_sp->GetName().GetCString());
- platform_set.insert(the_platform_sp.get());
- }
+ platform_ptr = the_platform_sp.get();
+ }
+ }
+
+ if (platform_ptr) {
+ // All platforms for all modules in the executable match, so we can
+ // select this platform.
+ platform_sp = platforms.front();
+ } else if (!more_than_one_platforms) {
+ // No platforms claim to support this file.
+ error.SetErrorString("no matching platforms found for this file");
+ return error;
+ } else {
+ // More than one platform claims to support this file.
+ StreamString error_strm;
+ std::set<Platform *> platform_set;
+ error_strm.Printf(
+ "more than one platform supports this executable (");
+ for (const auto &the_platform_sp : platforms) {
+ if (platform_set.find(the_platform_sp.get()) ==
+ platform_set.end()) {
+ if (!platform_set.empty())
+ error_strm.PutCString(", ");
+ error_strm.PutCString(the_platform_sp->GetName().GetCString());
+ platform_set.insert(the_platform_sp.get());
}
- error_strm.Printf(
- "), use the --platform option to specify a platform");
- error.SetErrorString(error_strm.GetString());
- return error;
}
+ error_strm.Printf("), specify an architecture to disambiguate");
+ error.SetErrorString(error_strm.GetString());
+ return error;
}
}
}
}
// If we have a valid architecture, make sure the current platform is
- // compatible with that architecture
+ // compatible with that architecture.
if (!prefer_platform_arch && arch.IsValid()) {
- if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
+ if (!platform_sp->IsCompatibleArchitecture(arch, false, nullptr)) {
platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
- if (!is_dummy_target && platform_sp)
+ if (platform_sp)
debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
}
} else if (platform_arch.IsValid()) {
- // if "arch" isn't valid, yet "platform_arch" is, it means we have an
- // executable file with a single architecture which should be used
+ // If "arch" isn't valid, yet "platform_arch" is, it means we have an
+ // executable file with a single architecture which should be used.
ArchSpec fixed_platform_arch;
- if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
- &fixed_platform_arch)) {
+ if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, nullptr)) {
platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
&fixed_platform_arch);
- if (!is_dummy_target && platform_sp)
+ if (platform_sp)
debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
}
}
@@ -284,32 +275,9 @@ Status TargetList::CreateTargetInternal(
if (!platform_arch.IsValid())
platform_arch = arch;
- error = TargetList::CreateTargetInternal(
- debugger, user_exe_path, platform_arch, load_dependent_files, platform_sp,
- target_sp, is_dummy_target);
- return error;
-}
-
-lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
- // FIXME: Maybe the dummy target should be per-Debugger
- if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
- ArchSpec arch(Target::GetDefaultArchitecture());
- if (!arch.IsValid())
- arch = HostInfo::GetArchitecture();
- Status err = CreateDummyTarget(
- debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
- }
-
- return m_dummy_target_sp;
-}
-
-Status TargetList::CreateDummyTarget(Debugger &debugger,
- llvm::StringRef specified_arch_name,
- lldb::TargetSP &target_sp) {
- PlatformSP host_platform_sp(Platform::GetHostPlatform());
- return CreateTargetInternal(
- debugger, (const char *)nullptr, specified_arch_name, eLoadDependentsNo,
- (const OptionGroupPlatform *)nullptr, target_sp, true);
+ return TargetList::CreateTargetInternal(debugger, user_exe_path,
+ platform_arch, load_dependent_files,
+ platform_sp, target_sp);
}
Status TargetList::CreateTargetInternal(Debugger &debugger,
@@ -317,13 +285,12 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
const ArchSpec &specified_arch,
LoadDependentFiles load_dependent_files,
lldb::PlatformSP &platform_sp,
- lldb::TargetSP &target_sp,
- bool is_dummy_target) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')",
- user_exe_path.str().c_str(), specified_arch.GetArchitectureName());
+ lldb::TargetSP &target_sp) {
+ LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')",
+ user_exe_path.str().c_str(),
+ specified_arch.GetArchitectureName());
Status error;
+ const bool is_dummy_target = false;
ArchSpec arch(specified_arch);
@@ -407,117 +374,106 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
}
- if (target_sp) {
- // Set argv0 with what the user typed, unless the user specified a
- // directory. If the user specified a directory, then it is probably a
- // bundle that was resolved and we need to use the resolved bundle path
- if (!user_exe_path.empty()) {
- // Use exactly what the user typed as the first argument when we exec or
- // posix_spawn
- if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
- target_sp->SetArg0(resolved_bundle_exe_path);
- } else {
- // Use resolved path
- target_sp->SetArg0(file.GetPath().c_str());
- }
- }
- if (file.GetDirectory()) {
- FileSpec file_dir;
- file_dir.GetDirectory() = file.GetDirectory();
- target_sp->AppendExecutableSearchPaths(file_dir);
- }
+ if (!target_sp)
+ return error;
- // Don't put the dummy target in the target list, it's held separately.
- if (!is_dummy_target) {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- m_selected_target_idx = m_target_list.size();
- m_target_list.push_back(target_sp);
- // Now prime this from the dummy target:
- target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
+ // Set argv0 with what the user typed, unless the user specified a
+ // directory. If the user specified a directory, then it is probably a
+ // bundle that was resolved and we need to use the resolved bundle path
+ if (!user_exe_path.empty()) {
+ // Use exactly what the user typed as the first argument when we exec or
+ // posix_spawn
+ if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
+ target_sp->SetArg0(resolved_bundle_exe_path);
} else {
- m_dummy_target_sp = target_sp;
+ // Use resolved path
+ target_sp->SetArg0(file.GetPath().c_str());
}
}
+ if (file.GetDirectory()) {
+ FileSpec file_dir;
+ file_dir.GetDirectory() = file.GetDirectory();
+ target_sp->AppendExecutableSearchPaths(file_dir);
+ }
+
+ // Now prime this from the dummy target:
+ target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
return error;
}
bool TargetList::DeleteTarget(TargetSP &target_sp) {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- collection::iterator pos, end = m_target_list.end();
+ auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
+ if (it == m_target_list.end())
+ return false;
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- if (pos->get() == target_sp.get()) {
- m_target_list.erase(pos);
- return true;
- }
- }
- return false;
+ m_target_list.erase(it);
+ return true;
}
TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- TargetSP target_sp;
- collection::const_iterator pos, end = m_target_list.end();
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- Module *exe_module = (*pos)->GetExecutableModulePointer();
-
- if (exe_module) {
- if (FileSpec::Match(exe_file_spec, exe_module->GetFileSpec())) {
- if (exe_arch_ptr) {
- if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
- continue;
- }
- target_sp = *pos;
- break;
- }
- }
- }
- return target_sp;
+ auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
+ [&exe_file_spec, exe_arch_ptr](const TargetSP &item) {
+ Module *exe_module = item->GetExecutableModulePointer();
+ if (!exe_module ||
+ !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec()))
+ return false;
+
+ return !exe_arch_ptr ||
+ exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture());
+ });
+
+ if (it != m_target_list.end())
+ return *it;
+
+ return TargetSP();
}
TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- TargetSP target_sp;
- collection::const_iterator pos, end = m_target_list.end();
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- Process *process = (*pos)->GetProcessSP().get();
- if (process && process->GetID() == pid) {
- target_sp = *pos;
- break;
- }
- }
- return target_sp;
+ auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
+ [pid](const TargetSP &item) {
+ auto *process_ptr = item->GetProcessSP().get();
+ return process_ptr && (process_ptr->GetID() == pid);
+ });
+
+ if (it != m_target_list.end())
+ return *it;
+
+ return TargetSP();
}
TargetSP TargetList::FindTargetWithProcess(Process *process) const {
TargetSP target_sp;
- if (process) {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- collection::const_iterator pos, end = m_target_list.end();
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- if (process == (*pos)->GetProcessSP().get()) {
- target_sp = *pos;
- break;
- }
- }
- }
+ if (!process)
+ return target_sp;
+
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
+ [process](const TargetSP &item) {
+ return item->GetProcessSP().get() == process;
+ });
+
+ if (it != m_target_list.end())
+ target_sp = *it;
+
return target_sp;
}
TargetSP TargetList::GetTargetSP(Target *target) const {
TargetSP target_sp;
- if (target) {
- std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- collection::const_iterator pos, end = m_target_list.end();
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- if (target == (*pos).get()) {
- target_sp = *pos;
- break;
- }
- }
- }
+ if (!target)
+ return target_sp;
+
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
+ [target](const TargetSP &item) { return item.get() == target; });
+ if (it != m_target_list.end())
+ target_sp = *it;
+
return target_sp;
}
@@ -548,14 +504,11 @@ uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
if (pid == LLDB_INVALID_PROCESS_ID) {
// Signal all processes with signal
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- collection::iterator pos, end = m_target_list.end();
- for (pos = m_target_list.begin(); pos != end; ++pos) {
- process = (*pos)->GetProcessSP().get();
- if (process) {
- if (process->IsAlive()) {
- ++num_signals_sent;
- process->Signal(signo);
- }
+ for (const auto &target_sp : m_target_list) {
+ process = target_sp->GetProcessSP().get();
+ if (process && process->IsAlive()) {
+ ++num_signals_sent;
+ process->Signal(signo);
}
}
} else {
@@ -563,11 +516,9 @@ uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
TargetSP target_sp(FindTargetWithProcessID(pid));
if (target_sp) {
process = target_sp->GetProcessSP().get();
- if (process) {
- if (process->IsAlive()) {
- ++num_signals_sent;
- process->Signal(signo);
- }
+ if (process && process->IsAlive()) {
+ ++num_signals_sent;
+ process->Signal(signo);
}
}
}
@@ -589,26 +540,35 @@ lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- size_t num_targets = m_target_list.size();
- for (size_t idx = 0; idx < num_targets; idx++) {
- if (target_sp == m_target_list[idx])
- return idx;
- }
+ auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
+ if (it != m_target_list.end())
+ return std::distance(m_target_list.begin(), it);
return UINT32_MAX;
}
-uint32_t TargetList::SetSelectedTarget(Target *target) {
+void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
+ lldbassert(std::find(m_target_list.begin(), m_target_list.end(), target_sp) ==
+ m_target_list.end() &&
+ "target already exists it the list");
+ m_target_list.push_back(std::move(target_sp));
+ if (do_select)
+ SetSelectedTargetInternal(m_target_list.size() - 1);
+}
+
+void TargetList::SetSelectedTargetInternal(uint32_t index) {
+ lldbassert(!m_target_list.empty());
+ m_selected_target_idx = index < m_target_list.size() ? index : 0;
+}
+
+void TargetList::SetSelectedTarget(uint32_t index) {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
- collection::const_iterator pos, begin = m_target_list.begin(),
- end = m_target_list.end();
- for (pos = begin; pos != end; ++pos) {
- if (pos->get() == target) {
- m_selected_target_idx = std::distance(begin, pos);
- return m_selected_target_idx;
- }
- }
- m_selected_target_idx = 0;
- return m_selected_target_idx;
+ SetSelectedTargetInternal(index);
+}
+
+void TargetList::SetSelectedTarget(const TargetSP &target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
+ SetSelectedTargetInternal(std::distance(m_target_list.begin(), it));
}
lldb::TargetSP TargetList::GetSelectedTarget() {
diff --git a/contrib/llvm-project/lldb/source/Target/TargetProperties.td b/contrib/llvm-project/lldb/source/Target/TargetProperties.td
index ae3abe354856..2d6a4358082a 100644
--- a/contrib/llvm-project/lldb/source/Target/TargetProperties.td
+++ b/contrib/llvm-project/lldb/source/Target/TargetProperties.td
@@ -20,6 +20,10 @@ let Definition = "target" in {
def ExprPrefix: Property<"expr-prefix", "FileSpec">,
DefaultStringValue<"">,
Desc<"Path to a file containing expressions to be prepended to all expressions.">;
+ def ExprErrorLimit: Property<"expr-error-limit", "UInt64">,
+ DefaultUnsignedValue<5>,
+ Desc<"The maximum amount of errors to emit while parsing an expression. "
+ "A value of 0 means to always continue parsing if possible.">;
def PreferDynamic: Property<"prefer-dynamic-value", "Enum">,
DefaultEnumValue<"eDynamicDontRunTarget">,
EnumValues<"OptionEnumValues(g_dynamic_value_types)">,
@@ -32,7 +36,7 @@ let Definition = "target" in {
Desc<"Skip function prologues when setting breakpoints by name.">;
def SourceMap: Property<"source-map", "PathMap">,
DefaultStringValue<"">,
- Desc<"Source path remappings are used to track the change of location between a source file when built, and where it exists on the current system. It consists of an array of duples, the first element of each duple is some part (starting at the root) of the path to the file when it was built, and the second is where the remainder of the original build hierarchy is rooted on the local system. Each element of the array is checked in order and the first one that results in a match wins.">;
+ Desc<"Source path remappings apply substitutions to the paths of source files, typically needed to debug from a different host than the one that built the target. The source-map property consists of an array of pairs, the first element is a path prefix, and the second is its replacement. The syntax is `prefix1 replacement1 prefix2 replacement2...`. The pairs are checked in order, the first prefix that matches is used, and that prefix is substituted with the replacement. A common pattern is to use source-map in conjunction with the clang -fdebug-prefix-map flag. In the build, use `-fdebug-prefix-map=/path/to/build_dir=.` to rewrite the host specific build directory to `.`. Then for debugging, use `settings set target.source-map . /path/to/local_dir` to convert `.` to a valid local path.">;
def ExecutableSearchPaths: Property<"exec-search-paths", "FileSpecList">,
DefaultStringValue<"">,
Desc<"Executable search paths to use when locating executable files whose paths don't match the local file system.">;
@@ -45,9 +49,11 @@ let Definition = "target" in {
def AutoImportClangModules: Property<"auto-import-clang-modules", "Boolean">,
DefaultTrue,
Desc<"Automatically load Clang modules referred to by the program.">;
- def ImportStdModule: Property<"import-std-module", "Boolean">,
- DefaultFalse,
- Desc<"Import the C++ std module to improve debugging STL containers.">;
+ def ImportStdModule: Property<"import-std-module", "Enum">,
+ DefaultEnumValue<"eImportStdModuleFalse">,
+ EnumValues<"OptionEnumValues(g_import_std_module_value_types)">,
+ Desc<"Import the 'std' C++ module to improve expression parsing involving "
+ " C++ standard library types.">;
def AutoApplyFixIts: Property<"auto-apply-fixits", "Boolean">,
DefaultTrue,
Desc<"Automatically apply fix-it hints to expressions.">;
@@ -111,6 +117,9 @@ let Definition = "target" in {
def DisableSTDIO: Property<"disable-stdio", "Boolean">,
DefaultFalse,
Desc<"Disable stdin/stdout for process (e.g. for a GUI application)">;
+ def InheritTCC: Property<"inherit-tcc", "Boolean">,
+ DefaultFalse,
+ Desc<"Inherit the TCC permissions from the inferior's parent instead of making the process itself responsible.">;
def InlineStrategy: Property<"inline-breakpoint-strategy", "Enum">,
DefaultEnumValue<"eInlineBreakpointsAlways">,
EnumValues<"OptionEnumValues(g_inline_breakpoint_enums)">,
@@ -214,6 +223,9 @@ let Definition = "process" in {
def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">,
DefaultUnsignedValue<15>,
Desc<"The time in seconds to wait for LLDB-internal utility expressions.">;
+ def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">,
+ DefaultFalse,
+ Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">;
}
let Definition = "platform" in {
diff --git a/contrib/llvm-project/lldb/source/Target/Thread.cpp b/contrib/llvm-project/lldb/source/Target/Thread.cpp
index 24cf4bf3ee1e..049e458d8b19 100644
--- a/contrib/llvm-project/lldb/source/Target/Thread.cpp
+++ b/contrib/llvm-project/lldb/source/Target/Thread.cpp
@@ -1103,6 +1103,22 @@ void Thread::DiscardPlan() {
discarded_plan_sp->GetThread().GetID());
}
+void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const {
+ const ThreadPlanStack &plans = GetPlans();
+ if (!plans.AnyPlans())
+ return;
+
+ // Iterate from the second plan (index: 1) to skip the base plan.
+ ThreadPlanSP p;
+ uint32_t i = 1;
+ while ((p = plans.GetPlanByIndex(i, false))) {
+ StreamString strm;
+ p->GetDescription(&strm, eDescriptionLevelInitial);
+ request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
+ i++;
+ }
+}
+
ThreadPlan *Thread::GetCurrentPlan() const {
return GetPlans().GetCurrentPlan().get();
}
@@ -1380,7 +1396,7 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name,
extra_args_impl));
-
+ thread_plan_sp->SetStopOthers(stop_other_threads);
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1661,7 +1677,7 @@ Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr);
}
-const char *Thread::StopReasonAsCString(lldb::StopReason reason) {
+std::string Thread::StopReasonAsString(lldb::StopReason reason) {
switch (reason) {
case eStopReasonInvalid:
return "invalid";
@@ -1687,13 +1703,10 @@ const char *Thread::StopReasonAsCString(lldb::StopReason reason) {
return "instrumentation break";
}
- static char unknown_state_string[64];
- snprintf(unknown_state_string, sizeof(unknown_state_string),
- "StopReason = %i", reason);
- return unknown_state_string;
+ return "StopReason = " + std::to_string(reason);
}
-const char *Thread::RunModeAsCString(lldb::RunMode mode) {
+std::string Thread::RunModeAsString(lldb::RunMode mode) {
switch (mode) {
case eOnlyThisThread:
return "only this thread";
@@ -1703,10 +1716,7 @@ const char *Thread::RunModeAsCString(lldb::RunMode mode) {
return "only during stepping";
}
- static char unknown_state_string[64];
- snprintf(unknown_state_string, sizeof(unknown_state_string), "RunMode = %i",
- mode);
- return unknown_state_string;
+ return "RunMode = " + std::to_string(mode);
}
size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp
index d8e92b8fd0de..c7a00e2450c8 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp
@@ -99,6 +99,8 @@ Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
return m_run_vote;
}
+void ThreadPlan::ClearThreadCache() { m_thread = nullptr; }
+
bool ThreadPlan::StopOthers() {
ThreadPlan *prev_plan;
prev_plan = GetPreviousPlan();
@@ -134,7 +136,7 @@ bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
}
}
bool success = DoWillResume(resume_state, current_plan);
- m_thread = nullptr; // We don't cache the thread pointer over resumes. This
+ ClearThreadCache(); // We don't cache the thread pointer over resumes. This
// Thread might go away, and another Thread represent
// the same underlying object on a later stop.
return success;
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp
index dbe26f42c9bf..f525173f8a51 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -260,9 +260,9 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
stop_reason = eStopReasonNone;
else
stop_reason = m_real_stop_info_sp->GetStopReason();
- LLDB_LOGF(log,
- "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.",
- Thread::StopReasonAsCString(stop_reason));
+ LLDB_LOG(log,
+ "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - {0}.",
+ Thread::StopReasonAsString(stop_reason));
if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
return true;
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanPython.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanPython.cpp
index 8171186319f5..e83f0e9e715e 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanPython.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanPython.cpp
@@ -25,11 +25,12 @@ using namespace lldb_private;
// ThreadPlanPython
-ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
+ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
StructuredDataImpl *args_data)
: ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_class_name(class_name), m_args_data(args_data), m_did_push(false) {
+ m_class_name(class_name), m_args_data(args_data), m_did_push(false),
+ m_stop_others(false) {
SetIsMasterPlan(true);
SetOkayToDiscard(true);
SetPrivate(false);
@@ -162,13 +163,6 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
}
// The ones below are not currently exported to Python.
-
-bool ThreadPlanPython::StopOthers() {
- // For now Python plans run all threads, but we should add some controls for
- // this.
- return false;
-}
-
void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
s->Printf("Python thread plan implemented by class %s.",
m_class_name.c_str());
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp
index 1cfc41dcd390..ad37669c31fd 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp
@@ -369,24 +369,16 @@ ThreadPlan *ThreadPlanStack::GetInnermostExpression() const {
return nullptr;
}
+void ThreadPlanStack::ClearThreadCache() {
+ for (lldb::ThreadPlanSP thread_plan_sp : m_plans)
+ thread_plan_sp->ClearThreadCache();
+}
+
void ThreadPlanStack::WillResume() {
m_completed_plans.clear();
m_discarded_plans.clear();
}
-const ThreadPlanStack::PlanStack &
-ThreadPlanStack::GetStackOfKind(ThreadPlanStack::StackKind kind) const {
- switch (kind) {
- case ePlans:
- return m_plans;
- case eCompletedPlans:
- return m_completed_plans;
- case eDiscardedPlans:
- return m_discarded_plans;
- }
- llvm_unreachable("Invalid StackKind value");
-}
-
void ThreadPlanStackMap::Update(ThreadList &current_threads,
bool delete_missing,
bool check_for_new) {
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepInRange.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepInRange.cpp
index c5f81d6665a1..a03bd93ac638 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -47,22 +47,6 @@ ThreadPlanStepInRange::ThreadPlanStepInRange(
step_out_avoids_code_without_debug_info);
}
-ThreadPlanStepInRange::ThreadPlanStepInRange(
- Thread &thread, const AddressRange &range,
- const SymbolContext &addr_context, const char *step_into_target,
- lldb::RunMode stop_others, LazyBool step_in_avoids_code_without_debug_info,
- LazyBool step_out_avoids_code_without_debug_info)
- : ThreadPlanStepRange(ThreadPlan::eKindStepInRange,
- "Step Range stepping in", thread, range, addr_context,
- stop_others),
- ThreadPlanShouldStopHere(this), m_step_past_prologue(true),
- m_virtual_step(false), m_step_into_target(step_into_target) {
- SetCallbacks();
- SetFlagsToDefault();
- SetupAvoidNoDebug(step_in_avoids_code_without_debug_info,
- step_out_avoids_code_without_debug_info);
-}
-
ThreadPlanStepInRange::~ThreadPlanStepInRange() = default;
void ThreadPlanStepInRange::SetupAvoidNoDebug(
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
index f3d35a91fcbc..f188d827faae 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -62,8 +62,8 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) {
StopReason reason = stop_info_sp->GetStopReason();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- LLDB_LOGF(log, "Step over breakpoint stopped for reason: %s.",
- Thread::StopReasonAsCString(reason));
+ LLDB_LOG(log, "Step over breakpoint stopped for reason: {0}.",
+ Thread::StopReasonAsString(reason));
switch (reason) {
case eStopReasonTrace:
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp
index f4b2ee3d08a2..3c42cd750dad 100644
--- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -327,13 +327,9 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
if (instructions == nullptr)
return false;
else {
- Target &target = GetThread().GetProcess()->GetTarget();
const bool ignore_calls = GetKind() == eKindStepOverRange;
- uint32_t branch_index =
- instructions->GetIndexOfNextBranchInstruction(pc_index, target,
- ignore_calls,
- &m_found_calls);
-
+ uint32_t branch_index = instructions->GetIndexOfNextBranchInstruction(
+ pc_index, ignore_calls, &m_found_calls);
Address run_to_address;
// If we didn't find a branch, run to the end of the range.
diff --git a/contrib/llvm-project/lldb/source/Target/ThreadTrace.cpp b/contrib/llvm-project/lldb/source/Target/ThreadTrace.cpp
new file mode 100644
index 000000000000..346f36a737d7
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Target/ThreadTrace.cpp
@@ -0,0 +1,39 @@
+//===-- ThreadTrace.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadTrace.h"
+
+#include <memory>
+
+#include "Plugins/Process/Utility/RegisterContextHistory.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void ThreadTrace::RefreshStateAfterStop() {}
+
+RegisterContextSP ThreadTrace::GetRegisterContext() {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
+
+ return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadTrace::CreateRegisterContextForFrame(StackFrame *frame) {
+ // Eventually this will calculate the register context based on the current
+ // trace position.
+ return std::make_shared<RegisterContextHistory>(
+ *this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS);
+}
+
+bool ThreadTrace::CalculateStopInfo() { return false; }
+
+const FileSpec &ThreadTrace::GetTraceFile() const { return m_trace_file; }
diff --git a/contrib/llvm-project/lldb/source/Target/Trace.cpp b/contrib/llvm-project/lldb/source/Target/Trace.cpp
new file mode 100644
index 000000000000..d19115b2d1f9
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Target/Trace.cpp
@@ -0,0 +1,268 @@
+//===-- Trace.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Trace.h"
+
+#include "llvm/Support/Format.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+// Helper structs used to extract the type of a trace session json without
+// having to parse the entire object.
+
+struct JSONSimplePluginSettings {
+ std::string type;
+};
+
+struct JSONSimpleTraceSession {
+ JSONSimplePluginSettings trace;
+};
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value, JSONSimplePluginSettings &plugin_settings,
+ Path path) {
+ json::ObjectMapper o(value, path);
+ return o && o.map("type", plugin_settings.type);
+}
+
+bool fromJSON(const Value &value, JSONSimpleTraceSession &session, Path path) {
+ json::ObjectMapper o(value, path);
+ return o && o.map("trace", session.trace);
+}
+
+} // namespace json
+} // namespace llvm
+
+static Error createInvalidPlugInError(StringRef plugin_name) {
+ return createStringError(
+ std::errc::invalid_argument,
+ "no trace plug-in matches the specified type: \"%s\"",
+ plugin_name.data());
+}
+
+Expected<lldb::TraceSP> Trace::FindPlugin(Debugger &debugger,
+ const json::Value &trace_session_file,
+ StringRef session_file_dir) {
+ JSONSimpleTraceSession json_session;
+ json::Path::Root root("traceSession");
+ if (!json::fromJSON(trace_session_file, json_session, root))
+ return root.getError();
+
+ ConstString plugin_name(json_session.trace.type);
+ if (auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name))
+ return create_callback(trace_session_file, session_file_dir, debugger);
+
+ return createInvalidPlugInError(json_session.trace.type);
+}
+
+Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
+ ConstString plugin_name(name);
+ StringRef schema = PluginManager::GetTraceSchema(plugin_name);
+ if (!schema.empty())
+ return schema;
+
+ return createInvalidPlugInError(name);
+}
+
+static int GetNumberOfDigits(size_t num) {
+ return num == 0 ? 1 : static_cast<int>(log10(num)) + 1;
+}
+
+/// Dump the symbol context of the given instruction address if it's different
+/// from the symbol context of the previous instruction in the trace.
+///
+/// \param[in] prev_sc
+/// The symbol context of the previous instruction in the trace.
+///
+/// \param[in] address
+/// The address whose symbol information will be dumped.
+///
+/// \return
+/// The symbol context of the current address, which might differ from the
+/// previous one.
+static SymbolContext DumpSymbolContext(Stream &s, const SymbolContext &prev_sc,
+ Target &target, const Address &address) {
+ AddressRange range;
+ if (prev_sc.GetAddressRange(eSymbolContextEverything, 0,
+ /*inline_block_range*/ false, range) &&
+ range.ContainsFileAddress(address))
+ return prev_sc;
+
+ SymbolContext sc;
+ address.CalculateSymbolContext(&sc, eSymbolContextEverything);
+
+ if (!prev_sc.module_sp && !sc.module_sp)
+ return sc;
+ if (prev_sc.module_sp == sc.module_sp && !sc.function && !sc.symbol &&
+ !prev_sc.function && !prev_sc.symbol)
+ return sc;
+
+ s.Printf(" ");
+
+ if (!sc.module_sp)
+ s.Printf("(none)");
+ else if (!sc.function && !sc.symbol)
+ s.Printf("%s`(none)",
+ sc.module_sp->GetFileSpec().GetFilename().AsCString());
+ else
+ sc.DumpStopContext(&s, &target, address, /*show_fullpath*/ false,
+ /*show_module*/ true, /*show_inlined_frames*/ false,
+ /*show_function_arguments*/ true,
+ /*show_function_name*/ true,
+ /*show_inline_callsite_line_info*/ false);
+ s.Printf("\n");
+ return sc;
+}
+
+/// Dump an instruction given by its address using a given disassembler, unless
+/// the instruction is not present in the disassembler.
+///
+/// \param[in] disassembler
+/// A disassembler containing a certain instruction list.
+///
+/// \param[in] address
+/// The address of the instruction to dump.
+///
+/// \return
+/// \b true if the information could be dumped, \b false otherwise.
+static bool TryDumpInstructionInfo(Stream &s,
+ const DisassemblerSP &disassembler,
+ const ExecutionContext &exe_ctx,
+ const Address &address) {
+ if (!disassembler)
+ return false;
+
+ if (InstructionSP instruction =
+ disassembler->GetInstructionList().GetInstructionAtAddress(address)) {
+ instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
+ /*max_opcode_byte_size*/ 0, &exe_ctx,
+ /*sym_ctx*/ nullptr, /*prev_sym_ctx*/ nullptr,
+ /*disassembly_addr_format*/ nullptr,
+ /*max_address_text_size*/ 0);
+ return true;
+ }
+
+ return false;
+}
+
+/// Dump an instruction instruction given by its address.
+///
+/// \param[in] prev_disassembler
+/// The disassembler that was used to dump the previous instruction in the
+/// trace. It is useful to avoid recomputations.
+///
+/// \param[in] address
+/// The address of the instruction to dump.
+///
+/// \return
+/// A disassembler that contains the given instruction, which might differ
+/// from the previous disassembler.
+static DisassemblerSP
+DumpInstructionInfo(Stream &s, const SymbolContext &sc,
+ const DisassemblerSP &prev_disassembler,
+ ExecutionContext &exe_ctx, const Address &address) {
+ // We first try to use the previous disassembler
+ if (TryDumpInstructionInfo(s, prev_disassembler, exe_ctx, address))
+ return prev_disassembler;
+
+ // Now we try using the current function's disassembler
+ if (sc.function) {
+ DisassemblerSP disassembler =
+ sc.function->GetInstructions(exe_ctx, nullptr, true);
+ if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
+ return disassembler;
+ }
+
+ // We fallback to disassembly one instruction
+ Target &target = exe_ctx.GetTargetRef();
+ const ArchSpec &arch = target.GetArchitecture();
+ AddressRange range(address, arch.GetMaximumOpcodeByteSize() * 1);
+ DisassemblerSP disassembler = Disassembler::DisassembleRange(
+ arch, /*plugin_name*/ nullptr,
+ /*flavor*/ nullptr, target, range, /*prefer_file_cache*/ true);
+ if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
+ return disassembler;
+ return nullptr;
+}
+
+void Trace::DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
+ size_t end_position, bool raw) {
+ size_t instructions_count = GetInstructionCount(thread);
+ s.Printf("thread #%u: tid = %" PRIu64 ", total instructions = %zu\n",
+ thread.GetIndexID(), thread.GetID(), instructions_count);
+
+ if (count == 0 || end_position >= instructions_count)
+ return;
+
+ size_t start_position =
+ end_position + 1 < count ? 0 : end_position + 1 - count;
+
+ int digits_count = GetNumberOfDigits(end_position);
+ auto printInstructionIndex = [&](size_t index) {
+ s.Printf(" [%*zu] ", digits_count, index);
+ };
+
+ bool was_prev_instruction_an_error = false;
+ Target &target = thread.GetProcess()->GetTarget();
+
+ SymbolContext sc;
+ DisassemblerSP disassembler;
+ ExecutionContext exe_ctx;
+ target.CalculateExecutionContext(exe_ctx);
+
+ TraverseInstructions(
+ thread, start_position, TraceDirection::Forwards,
+ [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
+ if (load_address) {
+ // We print an empty line after a sequence of errors to show more
+ // clearly that there's a gap in the trace
+ if (was_prev_instruction_an_error)
+ s.Printf(" ...missing instructions\n");
+
+ Address address;
+ if (!raw) {
+ target.GetSectionLoadList().ResolveLoadAddress(*load_address,
+ address);
+
+ sc = DumpSymbolContext(s, sc, target, address);
+ }
+
+ printInstructionIndex(index);
+ s.Printf("0x%016" PRIx64 " ", *load_address);
+
+ if (!raw) {
+ disassembler =
+ DumpInstructionInfo(s, sc, disassembler, exe_ctx, address);
+ }
+
+ was_prev_instruction_an_error = false;
+ } else {
+ printInstructionIndex(index);
+ s << toString(load_address.takeError());
+ was_prev_instruction_an_error = true;
+ if (!raw)
+ sc = SymbolContext();
+ }
+
+ s.Printf("\n");
+
+ return index < end_position;
+ });
+}
diff --git a/contrib/llvm-project/lldb/source/Target/TraceSessionFileParser.cpp b/contrib/llvm-project/lldb/source/Target/TraceSessionFileParser.cpp
new file mode 100644
index 000000000000..713fadc1eb4f
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Target/TraceSessionFileParser.cpp
@@ -0,0 +1,223 @@
+//===-- TraceSessionFileParser.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===/
+
+#include "lldb/Target/TraceSessionFileParser.h"
+
+#include <sstream>
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadTrace.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+void TraceSessionFileParser::NormalizePath(lldb_private::FileSpec &file_spec) {
+ if (file_spec.IsRelative())
+ file_spec.PrependPathComponent(m_session_file_dir);
+}
+
+Error TraceSessionFileParser::ParseModule(lldb::TargetSP &target_sp,
+ const JSONModule &module) {
+ FileSpec system_file_spec(module.system_path);
+ NormalizePath(system_file_spec);
+
+ FileSpec local_file_spec(module.file.hasValue() ? *module.file
+ : module.system_path);
+ NormalizePath(local_file_spec);
+
+ ModuleSpec module_spec;
+ module_spec.GetFileSpec() = local_file_spec;
+ module_spec.GetPlatformFileSpec() = system_file_spec;
+
+ if (module.uuid.hasValue())
+ module_spec.GetUUID().SetFromStringRef(*module.uuid);
+
+ Status error;
+ ModuleSP module_sp =
+ target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
+
+ if (error.Fail())
+ return error.ToError();
+
+ bool load_addr_changed = false;
+ module_sp->SetLoadAddress(*target_sp, module.load_address.value, false,
+ load_addr_changed);
+ return llvm::Error::success();
+}
+
+Error TraceSessionFileParser::CreateJSONError(json::Path::Root &root,
+ const json::Value &value) {
+ std::string err;
+ raw_string_ostream os(err);
+ root.printErrorContext(value, os);
+ return createStringError(
+ std::errc::invalid_argument, "%s\n\nContext:\n%s\n\nSchema:\n%s",
+ toString(root.getError()).c_str(), os.str().c_str(), m_schema.data());
+}
+
+std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) {
+ std::ostringstream schema_builder;
+ schema_builder << "{\n \"trace\": ";
+ schema_builder << plugin_schema.data() << ",";
+ schema_builder << R"(
+ "processes": [
+ {
+ "pid": integer,
+ "triple": string, // llvm-triple
+ "threads": [
+ {
+ "tid": integer,
+ "traceFile": string
+ }
+ ],
+ "modules": [
+ {
+ "systemPath": string, // original path of the module at runtime
+ "file"?: string, // copy of the file if not available at "systemPath"
+ "loadAddress": string, // string address in hex or decimal form
+ "uuid"?: string,
+ }
+ ]
+ }
+ ]
+ // Notes:
+ // All paths are either absolute or relative to the session file.
+}
+)";
+ return schema_builder.str();
+}
+
+ThreadTraceSP TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
+ const JSONThread &thread) {
+ lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
+
+ FileSpec trace_file(thread.trace_file);
+ NormalizePath(trace_file);
+
+ ThreadTraceSP thread_sp =
+ std::make_shared<ThreadTrace>(*process_sp, tid, trace_file);
+ process_sp->GetThreadList().AddThread(thread_sp);
+ return thread_sp;
+}
+
+Expected<TraceSessionFileParser::ParsedProcess>
+TraceSessionFileParser::ParseProcess(const JSONProcess &process) {
+ TargetSP target_sp;
+ Status error = m_debugger.GetTargetList().CreateTarget(
+ m_debugger, /*user_exe_path*/ StringRef(), process.triple,
+ eLoadDependentsNo,
+ /*platform_options*/ nullptr, target_sp);
+
+ if (!target_sp)
+ return error.ToError();
+
+ ParsedProcess parsed_process;
+ parsed_process.target_sp = target_sp;
+
+ ProcessSP process_sp = target_sp->CreateProcess(
+ /*listener*/ nullptr, "trace",
+ /*crash_file*/ nullptr,
+ /*can_connect*/ false);
+
+ process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
+
+ for (const JSONThread &thread : process.threads)
+ parsed_process.threads.push_back(ParseThread(process_sp, thread));
+
+ for (const JSONModule &module : process.modules)
+ if (Error err = ParseModule(target_sp, module))
+ return std::move(err);
+
+ if (!process.threads.empty())
+ process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
+
+ // We invoke DidAttach to create a correct stopped state for the process and
+ // its threads.
+ ArchSpec process_arch;
+ process_sp->DidAttach(process_arch);
+
+ return parsed_process;
+}
+
+Expected<std::vector<TraceSessionFileParser::ParsedProcess>>
+TraceSessionFileParser::ParseCommonSessionFile(
+ const JSONTraceSessionBase &session) {
+ std::vector<ParsedProcess> parsed_processes;
+
+ auto onError = [&]() {
+ // Delete all targets that were created so far in case of failures
+ for (ParsedProcess &parsed_process : parsed_processes)
+ m_debugger.GetTargetList().DeleteTarget(parsed_process.target_sp);
+ };
+
+ for (const JSONProcess &process : session.processes) {
+ if (Expected<ParsedProcess> parsed_process = ParseProcess(process))
+ parsed_processes.push_back(std::move(*parsed_process));
+ else {
+ onError();
+ return parsed_process.takeError();
+ }
+ }
+ return parsed_processes;
+}
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONAddress &address,
+ Path path) {
+ Optional<StringRef> s = value.getAsString();
+ if (s.hasValue() && !s->getAsInteger(0, address.value))
+ return true;
+
+ path.report("expected numeric string");
+ return false;
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("systemPath", module.system_path) &&
+ o.map("file", module.file) &&
+ o.map("loadAddress", module.load_address) &&
+ o.map("uuid", module.uuid);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
+ o.map("threads", process.threads) && o.map("modules", process.modules);
+}
+
+bool fromJSON(const Value &value,
+ TraceSessionFileParser::JSONTracePluginSettings &plugin_settings,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", plugin_settings.type);
+}
+
+bool fromJSON(const Value &value,
+ TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("processes", session.processes);
+}
+
+} // namespace json
+} // namespace llvm
diff --git a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp
index dce32adbf0a3..4ec2e25c7e3b 100644
--- a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp
+++ b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp
@@ -65,55 +65,49 @@ UnixSignals::UnixSignals(const UnixSignals &rhs) : m_signals(rhs.m_signals) {}
UnixSignals::~UnixSignals() = default;
void UnixSignals::Reset() {
- // This builds one standard set of Unix Signals. If yours aren't quite in
+ // This builds one standard set of Unix Signals. If yours aren't quite in
// this order, you can either subclass this class, and use Add & Remove to
- // change them
- // or you can subclass and build them afresh in your constructor;
+ // change them or you can subclass and build them afresh in your constructor.
//
- // Note: the signals below are the Darwin signals. Do not change these!
+ // Note: the signals below are the Darwin signals. Do not change these!
+
m_signals.clear();
- // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
- // ====== ============ ======== ====== ======
- // ===================================================
- AddSignal(1, "SIGHUP", false, true, true, "hangup");
- AddSignal(2, "SIGINT", true, true, true, "interrupt");
- AddSignal(3, "SIGQUIT", false, true, true, "quit");
- AddSignal(4, "SIGILL", false, true, true, "illegal instruction");
- AddSignal(5, "SIGTRAP", true, true, true,
- "trace trap (not reset when caught)");
- AddSignal(6, "SIGABRT", false, true, true, "abort()");
- AddSignal(7, "SIGEMT", false, true, true, "pollable event");
- AddSignal(8, "SIGFPE", false, true, true, "floating point exception");
- AddSignal(9, "SIGKILL", false, true, true, "kill");
- AddSignal(10, "SIGBUS", false, true, true, "bus error");
- AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation");
- AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call");
- AddSignal(13, "SIGPIPE", false, false, false,
- "write on a pipe with no one to read it");
- AddSignal(14, "SIGALRM", false, false, false, "alarm clock");
- AddSignal(15, "SIGTERM", false, true, true,
- "software termination signal from kill");
- AddSignal(16, "SIGURG", false, false, false,
- "urgent condition on IO channel");
- AddSignal(17, "SIGSTOP", true, true, true,
- "sendable stop signal not from tty");
- AddSignal(18, "SIGTSTP", false, true, true, "stop signal from tty");
- AddSignal(19, "SIGCONT", false, true, true, "continue a stopped process");
- AddSignal(20, "SIGCHLD", false, false, false,
- "to parent on child stop or exit");
- AddSignal(21, "SIGTTIN", false, true, true,
- "to readers process group upon background tty read");
- AddSignal(22, "SIGTTOU", false, true, true,
- "to readers process group upon background tty write");
- AddSignal(23, "SIGIO", false, false, false, "input/output possible signal");
- AddSignal(24, "SIGXCPU", false, true, true, "exceeded CPU time limit");
- AddSignal(25, "SIGXFSZ", false, true, true, "exceeded file size limit");
- AddSignal(26, "SIGVTALRM", false, false, false, "virtual time alarm");
- AddSignal(27, "SIGPROF", false, false, false, "profiling time alarm");
- AddSignal(28, "SIGWINCH", false, false, false, "window size changes");
- AddSignal(29, "SIGINFO", false, true, true, "information request");
- AddSignal(30, "SIGUSR1", false, true, true, "user defined signal 1");
- AddSignal(31, "SIGUSR2", false, true, true, "user defined signal 2");
+
+ // clang-format off
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============== ======== ====== ====== ===================================================
+ AddSignal(1, "SIGHUP", false, true, true, "hangup");
+ AddSignal(2, "SIGINT", true, true, true, "interrupt");
+ AddSignal(3, "SIGQUIT", false, true, true, "quit");
+ AddSignal(4, "SIGILL", false, true, true, "illegal instruction");
+ AddSignal(5, "SIGTRAP", true, true, true, "trace trap (not reset when caught)");
+ AddSignal(6, "SIGABRT", false, true, true, "abort()");
+ AddSignal(7, "SIGEMT", false, true, true, "pollable event");
+ AddSignal(8, "SIGFPE", false, true, true, "floating point exception");
+ AddSignal(9, "SIGKILL", false, true, true, "kill");
+ AddSignal(10, "SIGBUS", false, true, true, "bus error");
+ AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation");
+ AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call");
+ AddSignal(13, "SIGPIPE", false, false, false, "write on a pipe with no one to read it");
+ AddSignal(14, "SIGALRM", false, false, false, "alarm clock");
+ AddSignal(15, "SIGTERM", false, true, true, "software termination signal from kill");
+ AddSignal(16, "SIGURG", false, false, false, "urgent condition on IO channel");
+ AddSignal(17, "SIGSTOP", true, true, true, "sendable stop signal not from tty");
+ AddSignal(18, "SIGTSTP", false, true, true, "stop signal from tty");
+ AddSignal(19, "SIGCONT", false, false, true, "continue a stopped process");
+ AddSignal(20, "SIGCHLD", false, false, false, "to parent on child stop or exit");
+ AddSignal(21, "SIGTTIN", false, true, true, "to readers process group upon background tty read");
+ AddSignal(22, "SIGTTOU", false, true, true, "to readers process group upon background tty write");
+ AddSignal(23, "SIGIO", false, false, false, "input/output possible signal");
+ AddSignal(24, "SIGXCPU", false, true, true, "exceeded CPU time limit");
+ AddSignal(25, "SIGXFSZ", false, true, true, "exceeded file size limit");
+ AddSignal(26, "SIGVTALRM", false, false, false, "virtual time alarm");
+ AddSignal(27, "SIGPROF", false, false, false, "profiling time alarm");
+ AddSignal(28, "SIGWINCH", false, false, false, "window size changes");
+ AddSignal(29, "SIGINFO", false, true, true, "information request");
+ AddSignal(30, "SIGUSR1", false, true, true, "user defined signal 1");
+ AddSignal(31, "SIGUSR2", false, true, true, "user defined signal 2");
+ // clang-format on
}
void UnixSignals::AddSignal(int signo, const char *name, bool default_suppress,
diff --git a/contrib/llvm-project/lldb/source/Target/UnwindAssembly.cpp b/contrib/llvm-project/lldb/source/Target/UnwindAssembly.cpp
index 3a87e3da5bca..75f2b328cef8 100644
--- a/contrib/llvm-project/lldb/source/Target/UnwindAssembly.cpp
+++ b/contrib/llvm-project/lldb/source/Target/UnwindAssembly.cpp
@@ -29,5 +29,3 @@ UnwindAssemblySP UnwindAssembly::FindPlugin(const ArchSpec &arch) {
}
UnwindAssembly::UnwindAssembly(const ArchSpec &arch) : m_arch(arch) {}
-
-UnwindAssembly::~UnwindAssembly() = default;