diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /lldb/source/Target/Process.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'lldb/source/Target/Process.cpp')
| -rw-r--r-- | lldb/source/Target/Process.cpp | 238 |
1 files changed, 176 insertions, 62 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 518a6934059e..8ecc66b592ea 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -10,6 +10,7 @@ #include <memory> #include <mutex> +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/Threading.h" @@ -68,6 +69,7 @@ #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/SelectHelper.h" #include "lldb/Utility/State.h" +#include "lldb/Utility/Timer.h" using namespace lldb; using namespace lldb_private; @@ -83,16 +85,10 @@ using namespace std::chrono; #define DISABLE_MEM_CACHE_DEFAULT true #endif -class ProcessOptionValueProperties : public OptionValueProperties { +class ProcessOptionValueProperties + : public Cloneable<ProcessOptionValueProperties, OptionValueProperties> { public: - ProcessOptionValueProperties(ConstString name) - : OptionValueProperties(name) {} - - // This constructor is used when creating ProcessOptionValueProperties when - // it is part of a new lldb_private::Process instance. It will copy all - // current global property values as needed - ProcessOptionValueProperties(ProcessProperties *global_properties) - : OptionValueProperties(*global_properties->GetValueProperties()) {} + ProcessOptionValueProperties(ConstString name) : Cloneable(name) {} const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, @@ -131,10 +127,12 @@ enum { #include "TargetPropertiesEnum.inc" }; -class ProcessExperimentalOptionValueProperties : public OptionValueProperties { +class ProcessExperimentalOptionValueProperties + : public Cloneable<ProcessExperimentalOptionValueProperties, + OptionValueProperties> { public: ProcessExperimentalOptionValueProperties() - : OptionValueProperties( + : Cloneable( ConstString(Properties::GetExperimentalSettingsName())) {} }; @@ -157,8 +155,8 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process) ConstString("thread"), ConstString("Settings specific to threads."), true, Thread::GetGlobalProperties()->GetValueProperties()); } else { - m_collection_sp = std::make_shared<ProcessOptionValueProperties>( - Process::GetGlobalProperties().get()); + m_collection_sp = + OptionValueProperties::CreateLocalCopy(*Process::GetGlobalProperties()); m_collection_sp->SetValueChangedCallback( ePropertyPythonOSPluginPath, [this] { m_process->LoadOperatingSystemPlugin(true); }); @@ -204,6 +202,16 @@ FileSpec ProcessProperties::GetPythonOSPluginPath() const { return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx); } +uint32_t ProcessProperties::GetVirtualAddressableBits() const { + const uint32_t idx = ePropertyVirtualAddressableBits; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_process_properties[idx].default_uint_value); +} + +void ProcessProperties::SetVirtualAddressableBits(uint32_t bits) { + const uint32_t idx = ePropertyVirtualAddressableBits; + m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, bits); +} void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) { const uint32_t idx = ePropertyPythonOSPluginPath; m_collection_sp->SetPropertyAtIndexAsFileSpec(nullptr, idx, file); @@ -242,6 +250,18 @@ void ProcessProperties::SetStopOnSharedLibraryEvents(bool stop) { m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop); } +bool ProcessProperties::GetDisableLangRuntimeUnwindPlans() const { + const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_process_properties[idx].default_uint_value != 0); +} + +void ProcessProperties::SetDisableLangRuntimeUnwindPlans(bool disable) { + const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, disable); + m_process->Flush(); +} + bool ProcessProperties::GetDetachKeepsStopped() const { const uint32_t idx = ePropertyDetachKeepsStopped; return m_collection_sp->GetPropertyAtIndexAsBoolean( @@ -278,6 +298,13 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const { return std::chrono::seconds(value); } +std::chrono::seconds ProcessProperties::GetInterruptTimeout() const { + const uint32_t idx = ePropertyInterruptTimeout; + uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_process_properties[idx].default_uint_value); + return std::chrono::seconds(value); +} + bool ProcessProperties::GetSteppingRunsAllThreads() const { const uint32_t idx = ePropertySteppingRunsAllThreads; return m_collection_sp->GetPropertyAtIndexAsBoolean( @@ -466,25 +493,9 @@ void Process::Finalize() { if (m_finalizing.exchange(true)) return; - // Destroy this process if needed - switch (GetPrivateState()) { - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateStopped: - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - DestroyImpl(false); - break; - - case eStateInvalid: - case eStateUnloaded: - case eStateDetached: - case eStateExited: - break; - } + // Destroy the process. This will call the virtual function DoDestroy under + // the hood, giving our derived class a chance to do the ncessary tear down. + DestroyImpl(false); // Clear our broadcaster before we proceed with destroying Broadcaster::Clear(); @@ -766,13 +777,30 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp, ThreadSP curr_thread(thread_list.GetSelectedThread()); ThreadSP thread; StopReason curr_thread_stop_reason = eStopReasonInvalid; - if (curr_thread) { + bool prefer_curr_thread = false; + if (curr_thread && curr_thread->IsValid()) { curr_thread_stop_reason = curr_thread->GetStopReason(); + switch (curr_thread_stop_reason) { + case eStopReasonNone: + case eStopReasonInvalid: + // Don't prefer the current thread if it didn't stop for a reason. + break; + case eStopReasonSignal: { + // We need to do the same computation we do for other threads + // below in case the current thread happens to be the one that + // stopped for the no-stop signal. + uint64_t signo = curr_thread->GetStopInfo()->GetValue(); + if (process_sp->GetUnixSignals()->GetShouldStop(signo)) + prefer_curr_thread = true; + } break; + default: + prefer_curr_thread = true; + break; + } curr_thread_stop_info_sp = curr_thread->GetStopInfo(); } - if (!curr_thread || !curr_thread->IsValid() || - curr_thread_stop_reason == eStopReasonInvalid || - curr_thread_stop_reason == eStopReasonNone) { + + if (!prefer_curr_thread) { // Prefer a thread that has just completed its plan over another // thread as current thread. ThreadSP plan_thread; @@ -804,8 +832,12 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp, case eStopReasonWatchpoint: case eStopReasonException: case eStopReasonExec: + case eStopReasonFork: + case eStopReasonVFork: + case eStopReasonVForkDone: case eStopReasonThreadExiting: case eStopReasonInstrumentation: + case eStopReasonProcessorTrace: if (!other_thread) other_thread = thread; break; @@ -1311,8 +1343,8 @@ Status Process::ResumeSynchronous(Stream *stream) { Status error = PrivateResume(); if (error.Success()) { - StateType state = - WaitForProcessToStop(llvm::None, nullptr, true, listener_sp, stream); + StateType state = WaitForProcessToStop(llvm::None, nullptr, true, + listener_sp, stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) @@ -1356,8 +1388,8 @@ void Process::SetPrivateState(StateType new_state) { if (m_finalizing) return; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | - LIBLLDB_LOG_PROCESS)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet( + LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_UNWIND)); bool state_changed = false; LLDB_LOGF(log, "Process::SetPrivateState (%s)", StateAsCString(new_state)); @@ -2022,6 +2054,8 @@ size_t Process::ReadCStringFromMemory(addr_t addr, char *dst, size_t Process::ReadMemoryFromInferior(addr_t addr, void *buf, size_t size, Status &error) { + LLDB_SCOPED_TIMER(); + if (buf == nullptr || size == 0) return 0; @@ -2448,6 +2482,11 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) { if (error.Fail()) return error; + // Listen and queue events that are broadcasted during the process launch. + ListenerSP listener_sp(Listener::MakeListener("LaunchEventHijack")); + HijackProcessEvents(listener_sp); + auto on_exit = llvm::make_scope_exit([this]() { RestoreProcessEvents(); }); + if (PrivateStateThreadIsValid()) PausePrivateStateThread(); @@ -2856,8 +2895,10 @@ void Process::CompleteAttach() { ProcessInstanceInfo process_info; GetProcessInfo(process_info); const ArchSpec &process_arch = process_info.GetArchitecture(); + const ArchSpec &target_arch = GetTarget().GetArchitecture(); if (process_arch.IsValid() && - !GetTarget().GetArchitecture().IsExactMatch(process_arch)) { + target_arch.IsCompatibleMatch(process_arch) && + !target_arch.IsExactMatch(process_arch)) { GetTarget().SetArchitecture(process_arch); LLDB_LOGF(log, "Process::%s switching architecture to %s based on info " @@ -3050,9 +3091,10 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) { return Status(); } - // Wait for 10 second for the process to stop. - StateType state = WaitForProcessToStop( - seconds(10), &event_sp, true, halt_listener_sp, nullptr, use_run_lock); + // Wait for the process halt timeout seconds for the process to stop. + StateType state = + WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true, + halt_listener_sp, nullptr, use_run_lock); RestoreProcessEvents(); if (state == eStateInvalid || !event_sp) { @@ -3083,8 +3125,8 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) { SendAsyncInterrupt(); // Consume the interrupt event. - StateType state = - WaitForProcessToStop(seconds(10), &exit_event_sp, true, listener_sp); + StateType state = WaitForProcessToStop(GetInterruptTimeout(), + &exit_event_sp, true, listener_sp); RestoreProcessEvents(); @@ -3203,7 +3245,7 @@ Status Process::DestroyImpl(bool force_kill) { error = StopForDestroyOrDetach(exit_event_sp); } - if (m_public_state.GetValue() != eStateRunning) { + if (m_public_state.GetValue() == eStateStopped) { // Ditch all thread plans, and remove all our breakpoints: in case we // have to restart the target to kill it, we don't want it hitting a // breakpoint... Only do this if we've stopped, however, since if we @@ -3374,14 +3416,14 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { should_resume = !m_thread_list.ShouldStop(event_ptr); if (was_restarted || should_resume || m_resume_requested) { - Vote stop_vote = m_thread_list.ShouldReportStop(event_ptr); + Vote report_stop_vote = m_thread_list.ShouldReportStop(event_ptr); LLDB_LOGF(log, "Process::ShouldBroadcastEvent: should_resume: %i state: " - "%s was_restarted: %i stop_vote: %d.", + "%s was_restarted: %i report_stop_vote: %d.", should_resume, StateAsCString(state), was_restarted, - stop_vote); + report_stop_vote); - switch (stop_vote) { + switch (report_stop_vote) { case eVoteYes: return_value = true; break; @@ -3819,9 +3861,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { // Process Event Data -Process::ProcessEventData::ProcessEventData() - : EventData(), m_process_wp(), m_state(eStateInvalid), m_restarted(false), - m_update_state(0), m_interrupted(false) {} +Process::ProcessEventData::ProcessEventData() : EventData(), m_process_wp() {} Process::ProcessEventData::ProcessEventData(const ProcessSP &process_sp, StateType state) @@ -5536,6 +5576,26 @@ void Process::Flush() { m_queue_list_stop_id = 0; } +lldb::addr_t Process::GetCodeAddressMask() { + if (m_code_address_mask == 0) { + if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) { + lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1); + SetCodeAddressMask(address_mask); + } + } + return m_code_address_mask; +} + +lldb::addr_t Process::GetDataAddressMask() { + if (m_data_address_mask == 0) { + if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) { + lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1); + SetDataAddressMask(address_mask); + } + } + return m_data_address_mask; +} + void Process::DidExec() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOGF(log, "Process::%s()", __FUNCTION__); @@ -5591,6 +5651,8 @@ addr_t Process::ResolveIndirectFunction(const Address *address, Status &error) { symbol ? symbol->GetName().AsCString() : "<UNKNOWN>"); function_addr = LLDB_INVALID_ADDRESS; } else { + if (ABISP abi_sp = GetABI()) + function_addr = abi_sp->FixCodeAddress(function_addr); m_resolved_indirect_addresses.insert( std::pair<addr_t, addr_t>(addr, function_addr)); } @@ -5684,12 +5746,12 @@ void Process::PrintWarningUnsupportedLanguage(const SymbolContext &sc) { LanguageType language = sc.GetLanguage(); if (language == eLanguageTypeUnknown) return; - auto type_system_or_err = sc.module_sp->GetTypeSystemForLanguage(language); - if (auto err = type_system_or_err.takeError()) { - llvm::consumeError(std::move(err)); + LanguageSet plugins = + PluginManager::GetAllTypeSystemSupportedLanguagesForTypes(); + if (!plugins[language]) { PrintWarning(Process::Warnings::eWarningsUnsupportedLanguage, sc.module_sp.get(), - "This version of LLDB has no plugin for the %s language. " + "This version of LLDB has no plugin for the language \"%s\". " "Inspection of frame variables will be limited.\n", Language::GetNameForLanguageType(language)); } @@ -5769,10 +5831,8 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr, const char *plugin_name = nullptr; const char *flavor = nullptr; - const bool prefer_file_cache = true; disassembler_sp = Disassembler::DisassembleRange( - target.GetArchitecture(), plugin_name, flavor, GetTarget(), range_bounds, - prefer_file_cache); + target.GetArchitecture(), plugin_name, flavor, GetTarget(), range_bounds); if (disassembler_sp) insn_list = &disassembler_sp->GetInstructionList(); @@ -5962,7 +6022,7 @@ UtilityFunction *Process::GetLoadImageUtilityFunction( return m_dlopen_utility_func_up.get(); } -llvm::Expected<TraceTypeInfo> Process::GetSupportedTraceType() { +llvm::Expected<TraceSupportedResponse> Process::TraceSupported() { if (!IsLiveDebugSession()) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Can't trace a non-live process."); @@ -6023,3 +6083,57 @@ bool Process::CallVoidArgVoidPtrReturn(const Address *address, return false; } + +llvm::Expected<const MemoryTagManager *> Process::GetMemoryTagManager() { + Architecture *arch = GetTarget().GetArchitecturePlugin(); + const MemoryTagManager *tag_manager = + arch ? arch->GetMemoryTagManager() : nullptr; + if (!arch || !tag_manager) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "This architecture does not support memory tagging", + GetPluginName().GetCString()); + } + + if (!SupportsMemoryTagging()) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Process does not support memory tagging"); + } + + return tag_manager; +} + +llvm::Expected<std::vector<lldb::addr_t>> +Process::ReadMemoryTags(lldb::addr_t addr, size_t len) { + llvm::Expected<const MemoryTagManager *> tag_manager_or_err = + GetMemoryTagManager(); + if (!tag_manager_or_err) + return tag_manager_or_err.takeError(); + + const MemoryTagManager *tag_manager = *tag_manager_or_err; + llvm::Expected<std::vector<uint8_t>> tag_data = + DoReadMemoryTags(addr, len, tag_manager->GetAllocationTagType()); + if (!tag_data) + return tag_data.takeError(); + + return tag_manager->UnpackTagsData(*tag_data, + len / tag_manager->GetGranuleSize()); +} + +Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len, + const std::vector<lldb::addr_t> &tags) { + llvm::Expected<const MemoryTagManager *> tag_manager_or_err = + GetMemoryTagManager(); + if (!tag_manager_or_err) + return Status(tag_manager_or_err.takeError()); + + const MemoryTagManager *tag_manager = *tag_manager_or_err; + llvm::Expected<std::vector<uint8_t>> packed_tags = + tag_manager->PackTags(tags); + if (!packed_tags) { + return Status(packed_tags.takeError()); + } + + return DoWriteMemoryTags(addr, len, tag_manager->GetAllocationTagType(), + *packed_tags); +} |
