diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
| commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
| tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /lldb/source/Target/Process.cpp | |
| parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
Diffstat (limited to 'lldb/source/Target/Process.cpp')
| -rw-r--r-- | lldb/source/Target/Process.cpp | 281 |
1 files changed, 56 insertions, 225 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index d777a2713911..518a6934059e 100644 --- a/lldb/source/Target/Process.cpp +++ b/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) { |
