| 1 | //===-- Thread.cpp --------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "lldb/Target/Thread.h" |
| 10 | #include "lldb/Breakpoint/BreakpointLocation.h" |
| 11 | #include "lldb/Core/Debugger.h" |
| 12 | #include "lldb/Core/FormatEntity.h" |
| 13 | #include "lldb/Core/Module.h" |
| 14 | #include "lldb/Core/StructuredDataImpl.h" |
| 15 | #include "lldb/Host/Host.h" |
| 16 | #include "lldb/Interpreter/OptionValueFileSpecList.h" |
| 17 | #include "lldb/Interpreter/OptionValueProperties.h" |
| 18 | #include "lldb/Interpreter/Property.h" |
| 19 | #include "lldb/Symbol/Function.h" |
| 20 | #include "lldb/Target/ABI.h" |
| 21 | #include "lldb/Target/DynamicLoader.h" |
| 22 | #include "lldb/Target/ExecutionContext.h" |
| 23 | #include "lldb/Target/LanguageRuntime.h" |
| 24 | #include "lldb/Target/Process.h" |
| 25 | #include "lldb/Target/RegisterContext.h" |
| 26 | #include "lldb/Target/ScriptedThreadPlan.h" |
| 27 | #include "lldb/Target/StackFrameRecognizer.h" |
| 28 | #include "lldb/Target/StopInfo.h" |
| 29 | #include "lldb/Target/SystemRuntime.h" |
| 30 | #include "lldb/Target/Target.h" |
| 31 | #include "lldb/Target/ThreadPlan.h" |
| 32 | #include "lldb/Target/ThreadPlanBase.h" |
| 33 | #include "lldb/Target/ThreadPlanCallFunction.h" |
| 34 | #include "lldb/Target/ThreadPlanRunToAddress.h" |
| 35 | #include "lldb/Target/ThreadPlanStack.h" |
| 36 | #include "lldb/Target/ThreadPlanStepInRange.h" |
| 37 | #include "lldb/Target/ThreadPlanStepInstruction.h" |
| 38 | #include "lldb/Target/ThreadPlanStepOut.h" |
| 39 | #include "lldb/Target/ThreadPlanStepOverBreakpoint.h" |
| 40 | #include "lldb/Target/ThreadPlanStepOverRange.h" |
| 41 | #include "lldb/Target/ThreadPlanStepThrough.h" |
| 42 | #include "lldb/Target/ThreadPlanStepUntil.h" |
| 43 | #include "lldb/Target/ThreadSpec.h" |
| 44 | #include "lldb/Target/UnwindLLDB.h" |
| 45 | #include "lldb/Utility/LLDBLog.h" |
| 46 | #include "lldb/Utility/Log.h" |
| 47 | #include "lldb/Utility/RegularExpression.h" |
| 48 | #include "lldb/Utility/State.h" |
| 49 | #include "lldb/Utility/Stream.h" |
| 50 | #include "lldb/Utility/StreamString.h" |
| 51 | #include "lldb/ValueObject/ValueObject.h" |
| 52 | #include "lldb/ValueObject/ValueObjectConstResult.h" |
| 53 | #include "lldb/lldb-enumerations.h" |
| 54 | |
| 55 | #include <memory> |
| 56 | #include <optional> |
| 57 | |
| 58 | using namespace lldb; |
| 59 | using namespace lldb_private; |
| 60 | |
| 61 | ThreadProperties &Thread::GetGlobalProperties() { |
| 62 | // NOTE: intentional leak so we don't crash if global destructor chain gets |
| 63 | // called as other threads still use the result of this function |
| 64 | static ThreadProperties *g_settings_ptr = new ThreadProperties(true); |
| 65 | return *g_settings_ptr; |
| 66 | } |
| 67 | |
| 68 | #define LLDB_PROPERTIES_thread |
| 69 | #include "TargetProperties.inc" |
| 70 | |
| 71 | enum { |
| 72 | #define LLDB_PROPERTIES_thread |
| 73 | #include "TargetPropertiesEnum.inc" |
| 74 | }; |
| 75 | |
| 76 | class ThreadOptionValueProperties |
| 77 | : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> { |
| 78 | public: |
| 79 | ThreadOptionValueProperties(llvm::StringRef name) : Cloneable(name) {} |
| 80 | |
| 81 | const Property * |
| 82 | GetPropertyAtIndex(size_t idx, |
| 83 | const ExecutionContext *exe_ctx) const override { |
| 84 | // When getting the value for a key from the thread options, we will always |
| 85 | // try and grab the setting from the current thread if there is one. Else |
| 86 | // we just use the one from this instance. |
| 87 | if (exe_ctx) { |
| 88 | Thread *thread = exe_ctx->GetThreadPtr(); |
| 89 | if (thread) { |
| 90 | ThreadOptionValueProperties *instance_properties = |
| 91 | static_cast<ThreadOptionValueProperties *>( |
| 92 | thread->GetValueProperties().get()); |
| 93 | if (this != instance_properties) |
| 94 | return instance_properties->ProtectedGetPropertyAtIndex(idx); |
| 95 | } |
| 96 | } |
| 97 | return ProtectedGetPropertyAtIndex(idx); |
| 98 | } |
| 99 | }; |
| 100 | |
| 101 | ThreadProperties::ThreadProperties(bool is_global) : Properties() { |
| 102 | if (is_global) { |
| 103 | m_collection_sp = std::make_shared<ThreadOptionValueProperties>(args: "thread" ); |
| 104 | m_collection_sp->Initialize(setting_definitions: g_thread_properties); |
| 105 | } else |
| 106 | m_collection_sp = |
| 107 | OptionValueProperties::CreateLocalCopy(global_properties: Thread::GetGlobalProperties()); |
| 108 | } |
| 109 | |
| 110 | ThreadProperties::~ThreadProperties() = default; |
| 111 | |
| 112 | const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() { |
| 113 | const uint32_t idx = ePropertyStepAvoidRegex; |
| 114 | return GetPropertyAtIndexAs<const RegularExpression *>(idx); |
| 115 | } |
| 116 | |
| 117 | FileSpecList ThreadProperties::GetLibrariesToAvoid() const { |
| 118 | const uint32_t idx = ePropertyStepAvoidLibraries; |
| 119 | return GetPropertyAtIndexAs<FileSpecList>(idx, default_value: {}); |
| 120 | } |
| 121 | |
| 122 | bool ThreadProperties::GetTraceEnabledState() const { |
| 123 | const uint32_t idx = ePropertyEnableThreadTrace; |
| 124 | return GetPropertyAtIndexAs<bool>( |
| 125 | idx, g_thread_properties[idx].default_uint_value != 0); |
| 126 | } |
| 127 | |
| 128 | bool ThreadProperties::GetStepInAvoidsNoDebug() const { |
| 129 | const uint32_t idx = ePropertyStepInAvoidsNoDebug; |
| 130 | return GetPropertyAtIndexAs<bool>( |
| 131 | idx, g_thread_properties[idx].default_uint_value != 0); |
| 132 | } |
| 133 | |
| 134 | bool ThreadProperties::GetStepOutAvoidsNoDebug() const { |
| 135 | const uint32_t idx = ePropertyStepOutAvoidsNoDebug; |
| 136 | return GetPropertyAtIndexAs<bool>( |
| 137 | idx, g_thread_properties[idx].default_uint_value != 0); |
| 138 | } |
| 139 | |
| 140 | uint64_t ThreadProperties::GetMaxBacktraceDepth() const { |
| 141 | const uint32_t idx = ePropertyMaxBacktraceDepth; |
| 142 | return GetPropertyAtIndexAs<uint64_t>( |
| 143 | idx, g_thread_properties[idx].default_uint_value); |
| 144 | } |
| 145 | |
| 146 | uint64_t ThreadProperties::GetSingleThreadPlanTimeout() const { |
| 147 | const uint32_t idx = ePropertySingleThreadPlanTimeout; |
| 148 | return GetPropertyAtIndexAs<uint64_t>( |
| 149 | idx, g_thread_properties[idx].default_uint_value); |
| 150 | } |
| 151 | |
| 152 | // Thread Event Data |
| 153 | |
| 154 | llvm::StringRef Thread::ThreadEventData::GetFlavorString() { |
| 155 | return "Thread::ThreadEventData" ; |
| 156 | } |
| 157 | |
| 158 | Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp) |
| 159 | : m_thread_sp(thread_sp), m_stack_id() {} |
| 160 | |
| 161 | Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp, |
| 162 | const StackID &stack_id) |
| 163 | : m_thread_sp(thread_sp), m_stack_id(stack_id) {} |
| 164 | |
| 165 | Thread::ThreadEventData::ThreadEventData() : m_thread_sp(), m_stack_id() {} |
| 166 | |
| 167 | Thread::ThreadEventData::~ThreadEventData() = default; |
| 168 | |
| 169 | void Thread::ThreadEventData::Dump(Stream *s) const {} |
| 170 | |
| 171 | const Thread::ThreadEventData * |
| 172 | Thread::ThreadEventData::GetEventDataFromEvent(const Event *event_ptr) { |
| 173 | if (event_ptr) { |
| 174 | const EventData *event_data = event_ptr->GetData(); |
| 175 | if (event_data && |
| 176 | event_data->GetFlavor() == ThreadEventData::GetFlavorString()) |
| 177 | return static_cast<const ThreadEventData *>(event_ptr->GetData()); |
| 178 | } |
| 179 | return nullptr; |
| 180 | } |
| 181 | |
| 182 | ThreadSP Thread::ThreadEventData::GetThreadFromEvent(const Event *event_ptr) { |
| 183 | ThreadSP thread_sp; |
| 184 | const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); |
| 185 | if (event_data) |
| 186 | thread_sp = event_data->GetThread(); |
| 187 | return thread_sp; |
| 188 | } |
| 189 | |
| 190 | StackID Thread::ThreadEventData::GetStackIDFromEvent(const Event *event_ptr) { |
| 191 | StackID stack_id; |
| 192 | const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); |
| 193 | if (event_data) |
| 194 | stack_id = event_data->GetStackID(); |
| 195 | return stack_id; |
| 196 | } |
| 197 | |
| 198 | StackFrameSP |
| 199 | Thread::ThreadEventData::GetStackFrameFromEvent(const Event *event_ptr) { |
| 200 | const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr); |
| 201 | StackFrameSP frame_sp; |
| 202 | if (event_data) { |
| 203 | ThreadSP thread_sp = event_data->GetThread(); |
| 204 | if (thread_sp) { |
| 205 | frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID( |
| 206 | stack_id: event_data->GetStackID()); |
| 207 | } |
| 208 | } |
| 209 | return frame_sp; |
| 210 | } |
| 211 | |
| 212 | // Thread class |
| 213 | |
| 214 | llvm::StringRef Thread::GetStaticBroadcasterClass() { |
| 215 | static constexpr llvm::StringLiteral class_name("lldb.thread" ); |
| 216 | return class_name; |
| 217 | } |
| 218 | |
| 219 | Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) |
| 220 | : ThreadProperties(false), UserID(tid), |
| 221 | Broadcaster(process.GetTarget().GetDebugger().GetBroadcasterManager(), |
| 222 | Thread::GetStaticBroadcasterClass().str()), |
| 223 | m_process_wp(process.shared_from_this()), m_stop_info_sp(), |
| 224 | m_stop_info_stop_id(0), m_stop_info_override_stop_id(0), |
| 225 | m_should_run_before_public_stop(false), |
| 226 | m_stopped_at_unexecuted_bp(LLDB_INVALID_ADDRESS), |
| 227 | m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32 |
| 228 | : process.GetNextThreadIndexID(thread_id: tid)), |
| 229 | m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(), |
| 230 | m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(), |
| 231 | m_prev_framezero_pc(), m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER), |
| 232 | m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning), |
| 233 | m_unwinder_up(), m_destroy_called(false), |
| 234 | m_override_should_notify(eLazyBoolCalculate), |
| 235 | m_extended_info_fetched(false), m_extended_info() { |
| 236 | Log *log = GetLog(mask: LLDBLog::Object); |
| 237 | LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")" , |
| 238 | static_cast<void *>(this), GetID()); |
| 239 | |
| 240 | CheckInWithManager(); |
| 241 | } |
| 242 | |
| 243 | Thread::~Thread() { |
| 244 | Log *log = GetLog(mask: LLDBLog::Object); |
| 245 | LLDB_LOGF(log, "%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")" , |
| 246 | static_cast<void *>(this), GetID()); |
| 247 | /// If you hit this assert, it means your derived class forgot to call |
| 248 | /// DestroyThread in its destructor. |
| 249 | assert(m_destroy_called); |
| 250 | } |
| 251 | |
| 252 | void Thread::DestroyThread() { |
| 253 | m_destroy_called = true; |
| 254 | m_stop_info_sp.reset(); |
| 255 | m_reg_context_sp.reset(); |
| 256 | m_unwinder_up.reset(); |
| 257 | std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); |
| 258 | m_curr_frames_sp.reset(); |
| 259 | m_prev_frames_sp.reset(); |
| 260 | m_prev_framezero_pc.reset(); |
| 261 | } |
| 262 | |
| 263 | void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) { |
| 264 | if (EventTypeHasListeners(event_type: eBroadcastBitSelectedFrameChanged)) { |
| 265 | auto data_sp = |
| 266 | std::make_shared<ThreadEventData>(args: shared_from_this(), args&: new_frame_id); |
| 267 | BroadcastEvent(event_type: eBroadcastBitSelectedFrameChanged, event_data_sp: data_sp); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | lldb::StackFrameSP |
| 272 | Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) { |
| 273 | StackFrameListSP stack_frame_list_sp(GetStackFrameList()); |
| 274 | StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex( |
| 275 | idx: stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant_frame: select_most_relevant)); |
| 276 | FrameSelectedCallback(frame: frame_sp.get()); |
| 277 | return frame_sp; |
| 278 | } |
| 279 | |
| 280 | uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame, |
| 281 | bool broadcast) { |
| 282 | uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame); |
| 283 | if (broadcast) |
| 284 | BroadcastSelectedFrameChange(new_frame_id&: frame->GetStackID()); |
| 285 | FrameSelectedCallback(frame); |
| 286 | return ret_value; |
| 287 | } |
| 288 | |
| 289 | bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) { |
| 290 | StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex(idx: frame_idx)); |
| 291 | if (frame_sp) { |
| 292 | GetStackFrameList()->SetSelectedFrame(frame_sp.get()); |
| 293 | if (broadcast) |
| 294 | BroadcastSelectedFrameChange(new_frame_id&: frame_sp->GetStackID()); |
| 295 | FrameSelectedCallback(frame: frame_sp.get()); |
| 296 | return true; |
| 297 | } else |
| 298 | return false; |
| 299 | } |
| 300 | |
| 301 | bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx, |
| 302 | Stream &output_stream) { |
| 303 | const bool broadcast = true; |
| 304 | bool success = SetSelectedFrameByIndex(frame_idx, broadcast); |
| 305 | if (success) { |
| 306 | StackFrameSP frame_sp = GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame); |
| 307 | if (frame_sp) { |
| 308 | bool already_shown = false; |
| 309 | SymbolContext frame_sc( |
| 310 | frame_sp->GetSymbolContext(resolve_scope: eSymbolContextLineEntry)); |
| 311 | const Debugger &debugger = GetProcess()->GetTarget().GetDebugger(); |
| 312 | if (debugger.GetUseExternalEditor() && frame_sc.line_entry.GetFile() && |
| 313 | frame_sc.line_entry.line != 0) { |
| 314 | if (llvm::Error e = Host::OpenFileInExternalEditor( |
| 315 | editor: debugger.GetExternalEditor(), file_spec: frame_sc.line_entry.GetFile(), |
| 316 | line_no: frame_sc.line_entry.line)) { |
| 317 | LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), |
| 318 | "OpenFileInExternalEditor failed: {0}" ); |
| 319 | } else { |
| 320 | already_shown = true; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | bool show_frame_info = true; |
| 325 | bool show_source = !already_shown; |
| 326 | FrameSelectedCallback(frame: frame_sp.get()); |
| 327 | return frame_sp->GetStatus(strm&: output_stream, show_frame_info, show_source); |
| 328 | } |
| 329 | return false; |
| 330 | } else |
| 331 | return false; |
| 332 | } |
| 333 | |
| 334 | void Thread::FrameSelectedCallback(StackFrame *frame) { |
| 335 | if (!frame) |
| 336 | return; |
| 337 | |
| 338 | if (frame->HasDebugInformation() && |
| 339 | (GetProcess()->GetWarningsOptimization() || |
| 340 | GetProcess()->GetWarningsUnsupportedLanguage())) { |
| 341 | SymbolContext sc = |
| 342 | frame->GetSymbolContext(resolve_scope: eSymbolContextFunction | eSymbolContextModule); |
| 343 | GetProcess()->PrintWarningOptimization(sc); |
| 344 | GetProcess()->PrintWarningUnsupportedLanguage(sc); |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | lldb::StopInfoSP Thread::GetStopInfo() { |
| 349 | if (m_destroy_called) |
| 350 | return m_stop_info_sp; |
| 351 | |
| 352 | ThreadPlanSP completed_plan_sp(GetCompletedPlan()); |
| 353 | ProcessSP process_sp(GetProcess()); |
| 354 | const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX; |
| 355 | |
| 356 | // Here we select the stop info according to priorirty: - m_stop_info_sp (if |
| 357 | // not trace) - preset value - completed plan stop info - new value with plan |
| 358 | // from completed plan stack - m_stop_info_sp (trace stop reason is OK now) - |
| 359 | // ask GetPrivateStopInfo to set stop info |
| 360 | |
| 361 | bool have_valid_stop_info = m_stop_info_sp && |
| 362 | m_stop_info_sp ->IsValid() && |
| 363 | m_stop_info_stop_id == stop_id; |
| 364 | bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded(); |
| 365 | bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded(); |
| 366 | bool plan_overrides_trace = |
| 367 | have_valid_stop_info && have_valid_completed_plan |
| 368 | && (m_stop_info_sp->GetStopReason() == eStopReasonTrace); |
| 369 | |
| 370 | if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) { |
| 371 | return m_stop_info_sp; |
| 372 | } else if (completed_plan_sp) { |
| 373 | return StopInfo::CreateStopReasonWithPlan( |
| 374 | plan&: completed_plan_sp, return_valobj_sp: GetReturnValueObject(), expression_variable_sp: GetExpressionVariable()); |
| 375 | } else { |
| 376 | GetPrivateStopInfo(); |
| 377 | return m_stop_info_sp; |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | void Thread::CalculatePublicStopInfo() { |
| 382 | ResetStopInfo(); |
| 383 | SetStopInfo(GetStopInfo()); |
| 384 | } |
| 385 | |
| 386 | lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) { |
| 387 | if (!calculate) |
| 388 | return m_stop_info_sp; |
| 389 | |
| 390 | if (m_destroy_called) |
| 391 | return m_stop_info_sp; |
| 392 | |
| 393 | ProcessSP process_sp(GetProcess()); |
| 394 | if (process_sp) { |
| 395 | const uint32_t process_stop_id = process_sp->GetStopID(); |
| 396 | if (m_stop_info_stop_id != process_stop_id) { |
| 397 | // We preserve the old stop info for a variety of reasons: |
| 398 | // 1) Someone has already updated it by the time we get here |
| 399 | // 2) We didn't get to execute the breakpoint instruction we stopped at |
| 400 | // 3) This is a virtual step so we didn't actually run |
| 401 | // 4) If this thread wasn't allowed to run the last time round. |
| 402 | if (m_stop_info_sp) { |
| 403 | if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() || |
| 404 | GetCurrentPlan()->IsVirtualStep() |
| 405 | || GetTemporaryResumeState() == eStateSuspended) |
| 406 | SetStopInfo(m_stop_info_sp); |
| 407 | else |
| 408 | m_stop_info_sp.reset(); |
| 409 | } |
| 410 | |
| 411 | if (!m_stop_info_sp) { |
| 412 | if (!CalculateStopInfo()) |
| 413 | SetStopInfo(StopInfoSP()); |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | // The stop info can be manually set by calling Thread::SetStopInfo() prior |
| 418 | // to this function ever getting called, so we can't rely on |
| 419 | // "m_stop_info_stop_id != process_stop_id" as the condition for the if |
| 420 | // statement below, we must also check the stop info to see if we need to |
| 421 | // override it. See the header documentation in |
| 422 | // Architecture::OverrideStopInfo() for more information on the stop |
| 423 | // info override callback. |
| 424 | if (m_stop_info_override_stop_id != process_stop_id) { |
| 425 | m_stop_info_override_stop_id = process_stop_id; |
| 426 | if (m_stop_info_sp) { |
| 427 | if (const Architecture *arch = |
| 428 | process_sp->GetTarget().GetArchitecturePlugin()) |
| 429 | arch->OverrideStopInfo(thread&: *this); |
| 430 | } |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | // If we were resuming the process and it was interrupted, |
| 435 | // return no stop reason. This thread would like to resume. |
| 436 | if (m_stop_info_sp && m_stop_info_sp->WasContinueInterrupted(thread&: *this)) |
| 437 | return {}; |
| 438 | |
| 439 | return m_stop_info_sp; |
| 440 | } |
| 441 | |
| 442 | lldb::StopReason Thread::GetStopReason() { |
| 443 | lldb::StopInfoSP stop_info_sp(GetStopInfo()); |
| 444 | if (stop_info_sp) |
| 445 | return stop_info_sp->GetStopReason(); |
| 446 | return eStopReasonNone; |
| 447 | } |
| 448 | |
| 449 | bool Thread::StopInfoIsUpToDate() const { |
| 450 | ProcessSP process_sp(GetProcess()); |
| 451 | if (process_sp) |
| 452 | return m_stop_info_stop_id == process_sp->GetStopID(); |
| 453 | else |
| 454 | return true; // Process is no longer around so stop info is always up to |
| 455 | // date... |
| 456 | } |
| 457 | |
| 458 | void Thread::ResetStopInfo() { |
| 459 | if (m_stop_info_sp) { |
| 460 | m_stop_info_sp.reset(); |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) { |
| 465 | m_stop_info_sp = stop_info_sp; |
| 466 | if (m_stop_info_sp) { |
| 467 | m_stop_info_sp->MakeStopInfoValid(); |
| 468 | // If we are overriding the ShouldReportStop, do that here: |
| 469 | if (m_override_should_notify != eLazyBoolCalculate) |
| 470 | m_stop_info_sp->OverrideShouldNotify(override_value: m_override_should_notify == |
| 471 | eLazyBoolYes); |
| 472 | } |
| 473 | |
| 474 | ProcessSP process_sp(GetProcess()); |
| 475 | if (process_sp) |
| 476 | m_stop_info_stop_id = process_sp->GetStopID(); |
| 477 | else |
| 478 | m_stop_info_stop_id = UINT32_MAX; |
| 479 | Log *log = GetLog(mask: LLDBLog::Thread); |
| 480 | LLDB_LOGF(log, "%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)" , |
| 481 | static_cast<void *>(this), GetID(), |
| 482 | stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>" , |
| 483 | m_stop_info_stop_id); |
| 484 | } |
| 485 | |
| 486 | void Thread::SetShouldReportStop(Vote vote) { |
| 487 | if (vote == eVoteNoOpinion) |
| 488 | return; |
| 489 | else { |
| 490 | m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo); |
| 491 | if (m_stop_info_sp) |
| 492 | m_stop_info_sp->OverrideShouldNotify(override_value: m_override_should_notify == |
| 493 | eLazyBoolYes); |
| 494 | } |
| 495 | } |
| 496 | |
| 497 | void Thread::SetStopInfoToNothing() { |
| 498 | // Note, we can't just NULL out the private reason, or the native thread |
| 499 | // implementation will try to go calculate it again. For now, just set it to |
| 500 | // a Unix Signal with an invalid signal number. |
| 501 | SetStopInfo( |
| 502 | StopInfo::CreateStopReasonWithSignal(thread&: *this, LLDB_INVALID_SIGNAL_NUMBER)); |
| 503 | } |
| 504 | |
| 505 | bool Thread::ThreadStoppedForAReason() { return (bool)GetPrivateStopInfo(); } |
| 506 | |
| 507 | bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) { |
| 508 | saved_state.register_backup_sp.reset(); |
| 509 | lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(idx: 0)); |
| 510 | if (frame_sp) { |
| 511 | lldb::RegisterCheckpointSP reg_checkpoint_sp( |
| 512 | new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression)); |
| 513 | if (reg_checkpoint_sp) { |
| 514 | lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext()); |
| 515 | if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues(reg_checkpoint&: *reg_checkpoint_sp)) |
| 516 | saved_state.register_backup_sp = reg_checkpoint_sp; |
| 517 | } |
| 518 | } |
| 519 | if (!saved_state.register_backup_sp) |
| 520 | return false; |
| 521 | |
| 522 | saved_state.stop_info_sp = GetStopInfo(); |
| 523 | ProcessSP process_sp(GetProcess()); |
| 524 | if (process_sp) |
| 525 | saved_state.orig_stop_id = process_sp->GetStopID(); |
| 526 | saved_state.current_inlined_depth = GetCurrentInlinedDepth(); |
| 527 | saved_state.m_completed_plan_checkpoint = |
| 528 | GetPlans().CheckpointCompletedPlans(); |
| 529 | saved_state.stopped_at_unexecuted_bp = m_stopped_at_unexecuted_bp; |
| 530 | |
| 531 | return true; |
| 532 | } |
| 533 | |
| 534 | bool Thread::RestoreRegisterStateFromCheckpoint( |
| 535 | ThreadStateCheckpoint &saved_state) { |
| 536 | if (saved_state.register_backup_sp) { |
| 537 | lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(idx: 0)); |
| 538 | if (frame_sp) { |
| 539 | lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext()); |
| 540 | if (reg_ctx_sp) { |
| 541 | bool ret = |
| 542 | reg_ctx_sp->WriteAllRegisterValues(reg_checkpoint: *saved_state.register_backup_sp); |
| 543 | |
| 544 | // Clear out all stack frames as our world just changed. |
| 545 | ClearStackFrames(); |
| 546 | reg_ctx_sp->InvalidateIfNeeded(force: true); |
| 547 | if (m_unwinder_up) |
| 548 | m_unwinder_up->Clear(); |
| 549 | return ret; |
| 550 | } |
| 551 | } |
| 552 | } |
| 553 | return false; |
| 554 | } |
| 555 | |
| 556 | void Thread::RestoreThreadStateFromCheckpoint( |
| 557 | ThreadStateCheckpoint &saved_state) { |
| 558 | if (saved_state.stop_info_sp) |
| 559 | saved_state.stop_info_sp->MakeStopInfoValid(); |
| 560 | SetStopInfo(saved_state.stop_info_sp); |
| 561 | GetStackFrameList()->SetCurrentInlinedDepth( |
| 562 | saved_state.current_inlined_depth); |
| 563 | GetPlans().RestoreCompletedPlanCheckpoint( |
| 564 | checkpoint: saved_state.m_completed_plan_checkpoint); |
| 565 | m_stopped_at_unexecuted_bp = saved_state.stopped_at_unexecuted_bp; |
| 566 | } |
| 567 | |
| 568 | StateType Thread::GetState() const { |
| 569 | // If any other threads access this we will need a mutex for it |
| 570 | std::lock_guard<std::recursive_mutex> guard(m_state_mutex); |
| 571 | return m_state; |
| 572 | } |
| 573 | |
| 574 | void Thread::SetState(StateType state) { |
| 575 | std::lock_guard<std::recursive_mutex> guard(m_state_mutex); |
| 576 | m_state = state; |
| 577 | } |
| 578 | |
| 579 | std::string Thread::GetStopDescription() { |
| 580 | StackFrameSP frame_sp = GetStackFrameAtIndex(idx: 0); |
| 581 | |
| 582 | if (!frame_sp) |
| 583 | return GetStopDescriptionRaw(); |
| 584 | |
| 585 | auto recognized_frame_sp = frame_sp->GetRecognizedFrame(); |
| 586 | |
| 587 | if (!recognized_frame_sp) |
| 588 | return GetStopDescriptionRaw(); |
| 589 | |
| 590 | std::string recognized_stop_description = |
| 591 | recognized_frame_sp->GetStopDescription(); |
| 592 | |
| 593 | if (!recognized_stop_description.empty()) |
| 594 | return recognized_stop_description; |
| 595 | |
| 596 | return GetStopDescriptionRaw(); |
| 597 | } |
| 598 | |
| 599 | std::string Thread::GetStopDescriptionRaw() { |
| 600 | StopInfoSP stop_info_sp = GetStopInfo(); |
| 601 | std::string raw_stop_description; |
| 602 | if (stop_info_sp && stop_info_sp->IsValid()) { |
| 603 | raw_stop_description = stop_info_sp->GetDescription(); |
| 604 | assert((!raw_stop_description.empty() || |
| 605 | stop_info_sp->GetStopReason() == eStopReasonNone) && |
| 606 | "StopInfo returned an empty description." ); |
| 607 | } |
| 608 | return raw_stop_description; |
| 609 | } |
| 610 | |
| 611 | void Thread::WillStop() { |
| 612 | ThreadPlan *current_plan = GetCurrentPlan(); |
| 613 | |
| 614 | // FIXME: I may decide to disallow threads with no plans. In which |
| 615 | // case this should go to an assert. |
| 616 | |
| 617 | if (!current_plan) |
| 618 | return; |
| 619 | |
| 620 | current_plan->WillStop(); |
| 621 | } |
| 622 | |
| 623 | bool Thread::SetupToStepOverBreakpointIfNeeded(RunDirection direction) { |
| 624 | if (GetResumeState() != eStateSuspended) { |
| 625 | // First check whether this thread is going to "actually" resume at all. |
| 626 | // For instance, if we're stepping from one level to the next of an |
| 627 | // virtual inlined call stack, we just change the inlined call stack index |
| 628 | // without actually running this thread. In that case, for this thread we |
| 629 | // shouldn't push a step over breakpoint plan or do that work. |
| 630 | if (GetCurrentPlan()->IsVirtualStep()) |
| 631 | return false; |
| 632 | |
| 633 | // If we're at a breakpoint push the step-over breakpoint plan. Do this |
| 634 | // before telling the current plan it will resume, since we might change |
| 635 | // what the current plan is. |
| 636 | |
| 637 | lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); |
| 638 | ProcessSP process_sp(GetProcess()); |
| 639 | if (reg_ctx_sp && process_sp && direction == eRunForward) { |
| 640 | const addr_t thread_pc = reg_ctx_sp->GetPC(); |
| 641 | BreakpointSiteSP bp_site_sp = |
| 642 | process_sp->GetBreakpointSiteList().FindByAddress(addr: thread_pc); |
| 643 | // If we're at a BreakpointSite which we have either |
| 644 | // 1. already triggered/hit, or |
| 645 | // 2. the Breakpoint was added while stopped, or the pc was moved |
| 646 | // to this BreakpointSite |
| 647 | // Step past the breakpoint before resuming. |
| 648 | // If we stopped at a breakpoint instruction/BreakpointSite location |
| 649 | // without hitting it, and we're still at that same address on |
| 650 | // resuming, then we want to hit the BreakpointSite when we resume. |
| 651 | if (bp_site_sp && m_stopped_at_unexecuted_bp != thread_pc) { |
| 652 | // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the |
| 653 | // target may not require anything special to step over a breakpoint. |
| 654 | |
| 655 | ThreadPlan *cur_plan = GetCurrentPlan(); |
| 656 | |
| 657 | bool push_step_over_bp_plan = false; |
| 658 | if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) { |
| 659 | ThreadPlanStepOverBreakpoint *bp_plan = |
| 660 | (ThreadPlanStepOverBreakpoint *)cur_plan; |
| 661 | if (bp_plan->GetBreakpointLoadAddress() != thread_pc) |
| 662 | push_step_over_bp_plan = true; |
| 663 | } else |
| 664 | push_step_over_bp_plan = true; |
| 665 | |
| 666 | if (push_step_over_bp_plan) { |
| 667 | ThreadPlanSP step_bp_plan_sp(new ThreadPlanStepOverBreakpoint(*this)); |
| 668 | if (step_bp_plan_sp) { |
| 669 | step_bp_plan_sp->SetPrivate(true); |
| 670 | |
| 671 | if (GetCurrentPlan()->RunState() != eStateStepping) { |
| 672 | ThreadPlanStepOverBreakpoint *step_bp_plan = |
| 673 | static_cast<ThreadPlanStepOverBreakpoint *>( |
| 674 | step_bp_plan_sp.get()); |
| 675 | step_bp_plan->SetAutoContinue(true); |
| 676 | } |
| 677 | QueueThreadPlan(plan_sp&: step_bp_plan_sp, abort_other_plans: false); |
| 678 | return true; |
| 679 | } |
| 680 | } |
| 681 | } |
| 682 | } |
| 683 | } |
| 684 | return false; |
| 685 | } |
| 686 | |
| 687 | bool Thread::ShouldResume(StateType resume_state) { |
| 688 | // At this point clear the completed plan stack. |
| 689 | GetPlans().WillResume(); |
| 690 | m_override_should_notify = eLazyBoolCalculate; |
| 691 | |
| 692 | StateType prev_resume_state = GetTemporaryResumeState(); |
| 693 | |
| 694 | SetTemporaryResumeState(resume_state); |
| 695 | |
| 696 | lldb::ThreadSP backing_thread_sp(GetBackingThread()); |
| 697 | if (backing_thread_sp) |
| 698 | backing_thread_sp->SetTemporaryResumeState(resume_state); |
| 699 | |
| 700 | // Make sure m_stop_info_sp is valid. Don't do this for threads we suspended |
| 701 | // in the previous run. |
| 702 | if (prev_resume_state != eStateSuspended) |
| 703 | GetPrivateStopInfo(); |
| 704 | |
| 705 | // This is a little dubious, but we are trying to limit how often we actually |
| 706 | // fetch stop info from the target, 'cause that slows down single stepping. |
| 707 | // So assume that if we got to the point where we're about to resume, and we |
| 708 | // haven't yet had to fetch the stop reason, then it doesn't need to know |
| 709 | // about the fact that we are resuming... |
| 710 | const uint32_t process_stop_id = GetProcess()->GetStopID(); |
| 711 | if (m_stop_info_stop_id == process_stop_id && |
| 712 | (m_stop_info_sp && m_stop_info_sp->IsValid())) { |
| 713 | StopInfo *stop_info = GetPrivateStopInfo().get(); |
| 714 | if (stop_info) |
| 715 | stop_info->WillResume(resume_state); |
| 716 | } |
| 717 | |
| 718 | // Tell all the plans that we are about to resume in case they need to clear |
| 719 | // any state. We distinguish between the plan on the top of the stack and the |
| 720 | // lower plans in case a plan needs to do any special business before it |
| 721 | // runs. |
| 722 | |
| 723 | bool need_to_resume = false; |
| 724 | ThreadPlan *plan_ptr = GetCurrentPlan(); |
| 725 | if (plan_ptr) { |
| 726 | need_to_resume = plan_ptr->WillResume(resume_state, current_plan: true); |
| 727 | |
| 728 | while ((plan_ptr = GetPreviousPlan(plan: plan_ptr)) != nullptr) { |
| 729 | plan_ptr->WillResume(resume_state, current_plan: false); |
| 730 | } |
| 731 | |
| 732 | // If the WillResume for the plan says we are faking a resume, then it will |
| 733 | // have set an appropriate stop info. In that case, don't reset it here. |
| 734 | |
| 735 | if (need_to_resume && resume_state != eStateSuspended) { |
| 736 | m_stop_info_sp.reset(); |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | if (need_to_resume) { |
| 741 | ClearStackFrames(); |
| 742 | m_stopped_at_unexecuted_bp = LLDB_INVALID_ADDRESS; |
| 743 | // Let Thread subclasses do any special work they need to prior to resuming |
| 744 | WillResume(resume_state); |
| 745 | } |
| 746 | |
| 747 | return need_to_resume; |
| 748 | } |
| 749 | |
| 750 | void Thread::DidResume() { |
| 751 | SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); |
| 752 | // This will get recomputed each time when we stop. |
| 753 | SetShouldRunBeforePublicStop(false); |
| 754 | } |
| 755 | |
| 756 | void Thread::DidStop() { SetState(eStateStopped); } |
| 757 | |
| 758 | bool Thread::ShouldStop(Event *event_ptr) { |
| 759 | ThreadPlan *current_plan = GetCurrentPlan(); |
| 760 | |
| 761 | bool should_stop = true; |
| 762 | |
| 763 | Log *log = GetLog(mask: LLDBLog::Step); |
| 764 | |
| 765 | if (GetResumeState() == eStateSuspended) { |
| 766 | LLDB_LOGF(log, |
| 767 | "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 |
| 768 | ", should_stop = 0 (ignore since thread was suspended)" , |
| 769 | __FUNCTION__, GetID(), GetProtocolID()); |
| 770 | return false; |
| 771 | } |
| 772 | |
| 773 | if (GetTemporaryResumeState() == eStateSuspended) { |
| 774 | LLDB_LOGF(log, |
| 775 | "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 |
| 776 | ", should_stop = 0 (ignore since thread was suspended)" , |
| 777 | __FUNCTION__, GetID(), GetProtocolID()); |
| 778 | return false; |
| 779 | } |
| 780 | |
| 781 | // Based on the current thread plan and process stop info, check if this |
| 782 | // thread caused the process to stop. NOTE: this must take place before the |
| 783 | // plan is moved from the current plan stack to the completed plan stack. |
| 784 | if (!ThreadStoppedForAReason()) { |
| 785 | LLDB_LOGF(log, |
| 786 | "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 |
| 787 | ", pc = 0x%16.16" PRIx64 |
| 788 | ", should_stop = 0 (ignore since no stop reason)" , |
| 789 | __FUNCTION__, GetID(), GetProtocolID(), |
| 790 | GetRegisterContext() ? GetRegisterContext()->GetPC() |
| 791 | : LLDB_INVALID_ADDRESS); |
| 792 | return false; |
| 793 | } |
| 794 | |
| 795 | // Clear the "must run me before stop" if it was set: |
| 796 | SetShouldRunBeforePublicStop(false); |
| 797 | |
| 798 | if (log) { |
| 799 | LLDB_LOGF(log, |
| 800 | "Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 |
| 801 | ", pc = 0x%16.16" PRIx64, |
| 802 | __FUNCTION__, static_cast<void *>(this), GetID(), GetProtocolID(), |
| 803 | GetRegisterContext() ? GetRegisterContext()->GetPC() |
| 804 | : LLDB_INVALID_ADDRESS); |
| 805 | LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^" ); |
| 806 | StreamString s; |
| 807 | s.IndentMore(); |
| 808 | GetProcess()->DumpThreadPlansForTID( |
| 809 | strm&: s, tid: GetID(), desc_level: eDescriptionLevelVerbose, internal: true /* internal */, |
| 810 | condense_trivial: false /* condense_trivial */, skip_unreported_plans: true /* skip_unreported */); |
| 811 | LLDB_LOGF(log, "Plan stack initial state:\n%s" , s.GetData()); |
| 812 | } |
| 813 | |
| 814 | // The top most plan always gets to do the trace log... |
| 815 | current_plan->DoTraceLog(); |
| 816 | |
| 817 | // First query the stop info's ShouldStopSynchronous. This handles |
| 818 | // "synchronous" stop reasons, for example the breakpoint command on internal |
| 819 | // breakpoints. If a synchronous stop reason says we should not stop, then |
| 820 | // we don't have to do any more work on this stop. |
| 821 | StopInfoSP private_stop_info(GetPrivateStopInfo()); |
| 822 | if (private_stop_info && |
| 823 | !private_stop_info->ShouldStopSynchronous(event_ptr)) { |
| 824 | LLDB_LOGF(log, "StopInfo::ShouldStop async callback says we should not " |
| 825 | "stop, returning ShouldStop of false." ); |
| 826 | return false; |
| 827 | } |
| 828 | |
| 829 | // If we've already been restarted, don't query the plans since the state |
| 830 | // they would examine is not current. |
| 831 | if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr)) |
| 832 | return false; |
| 833 | |
| 834 | // Before the plans see the state of the world, calculate the current inlined |
| 835 | // depth. |
| 836 | GetStackFrameList()->CalculateCurrentInlinedDepth(); |
| 837 | |
| 838 | // If the base plan doesn't understand why we stopped, then we have to find a |
| 839 | // plan that does. If that plan is still working, then we don't need to do |
| 840 | // any more work. If the plan that explains the stop is done, then we should |
| 841 | // pop all the plans below it, and pop it, and then let the plans above it |
| 842 | // decide whether they still need to do more work. |
| 843 | |
| 844 | bool done_processing_current_plan = false; |
| 845 | if (!current_plan->PlanExplainsStop(event_ptr)) { |
| 846 | if (current_plan->TracerExplainsStop()) { |
| 847 | done_processing_current_plan = true; |
| 848 | should_stop = false; |
| 849 | } else { |
| 850 | // Leaf plan that does not explain the stop should be popped. |
| 851 | // The plan should be push itself later again before resuming to stay |
| 852 | // as leaf. |
| 853 | if (current_plan->IsLeafPlan()) |
| 854 | PopPlan(); |
| 855 | |
| 856 | // If the current plan doesn't explain the stop, then find one that does |
| 857 | // and let it handle the situation. |
| 858 | ThreadPlan *plan_ptr = current_plan; |
| 859 | while ((plan_ptr = GetPreviousPlan(plan: plan_ptr)) != nullptr) { |
| 860 | if (plan_ptr->PlanExplainsStop(event_ptr)) { |
| 861 | LLDB_LOGF(log, "Plan %s explains stop." , plan_ptr->GetName()); |
| 862 | |
| 863 | should_stop = plan_ptr->ShouldStop(event_ptr); |
| 864 | |
| 865 | // plan_ptr explains the stop, next check whether plan_ptr is done, |
| 866 | // if so, then we should take it and all the plans below it off the |
| 867 | // stack. |
| 868 | |
| 869 | if (plan_ptr->MischiefManaged()) { |
| 870 | // We're going to pop the plans up to and including the plan that |
| 871 | // explains the stop. |
| 872 | ThreadPlan *prev_plan_ptr = GetPreviousPlan(plan: plan_ptr); |
| 873 | |
| 874 | do { |
| 875 | if (should_stop) |
| 876 | current_plan->WillStop(); |
| 877 | PopPlan(); |
| 878 | } while ((current_plan = GetCurrentPlan()) != prev_plan_ptr); |
| 879 | // Now, if the responsible plan was not "Okay to discard" then |
| 880 | // we're done, otherwise we forward this to the next plan in the |
| 881 | // stack below. |
| 882 | done_processing_current_plan = |
| 883 | (plan_ptr->IsControllingPlan() && !plan_ptr->OkayToDiscard()); |
| 884 | } else { |
| 885 | bool should_force_run = plan_ptr->ShouldRunBeforePublicStop(); |
| 886 | if (should_force_run) { |
| 887 | SetShouldRunBeforePublicStop(true); |
| 888 | should_stop = false; |
| 889 | } |
| 890 | done_processing_current_plan = true; |
| 891 | } |
| 892 | break; |
| 893 | } |
| 894 | } |
| 895 | } |
| 896 | } |
| 897 | |
| 898 | if (!done_processing_current_plan) { |
| 899 | bool override_stop = false; |
| 900 | |
| 901 | // We're starting from the base plan, so just let it decide; |
| 902 | if (current_plan->IsBasePlan()) { |
| 903 | should_stop = current_plan->ShouldStop(event_ptr); |
| 904 | LLDB_LOGF(log, "Base plan says should stop: %i." , should_stop); |
| 905 | } else { |
| 906 | // Otherwise, don't let the base plan override what the other plans say |
| 907 | // to do, since presumably if there were other plans they would know what |
| 908 | // to do... |
| 909 | while (true) { |
| 910 | if (current_plan->IsBasePlan()) |
| 911 | break; |
| 912 | |
| 913 | should_stop = current_plan->ShouldStop(event_ptr); |
| 914 | LLDB_LOGF(log, "Plan %s should stop: %d." , current_plan->GetName(), |
| 915 | should_stop); |
| 916 | if (current_plan->MischiefManaged()) { |
| 917 | if (should_stop) |
| 918 | current_plan->WillStop(); |
| 919 | |
| 920 | if (current_plan->ShouldAutoContinue(event_ptr)) { |
| 921 | override_stop = true; |
| 922 | LLDB_LOGF(log, "Plan %s auto-continue: true." , |
| 923 | current_plan->GetName()); |
| 924 | } |
| 925 | |
| 926 | // If a Controlling Plan wants to stop, we let it. Otherwise, see if |
| 927 | // the plan's parent wants to stop. |
| 928 | |
| 929 | PopPlan(); |
| 930 | if (should_stop && current_plan->IsControllingPlan() && |
| 931 | !current_plan->OkayToDiscard()) { |
| 932 | break; |
| 933 | } |
| 934 | |
| 935 | current_plan = GetCurrentPlan(); |
| 936 | if (current_plan == nullptr) { |
| 937 | break; |
| 938 | } |
| 939 | } else { |
| 940 | break; |
| 941 | } |
| 942 | } |
| 943 | } |
| 944 | |
| 945 | if (override_stop) |
| 946 | should_stop = false; |
| 947 | } |
| 948 | |
| 949 | // One other potential problem is that we set up a controlling plan, then stop |
| 950 | // in before it is complete - for instance by hitting a breakpoint during a |
| 951 | // step-over - then do some step/finish/etc operations that wind up past the |
| 952 | // end point condition of the initial plan. We don't want to strand the |
| 953 | // original plan on the stack, This code clears stale plans off the stack. |
| 954 | |
| 955 | if (should_stop) { |
| 956 | ThreadPlan *plan_ptr = GetCurrentPlan(); |
| 957 | |
| 958 | // Discard the stale plans and all plans below them in the stack, plus move |
| 959 | // the completed plans to the completed plan stack |
| 960 | while (!plan_ptr->IsBasePlan()) { |
| 961 | bool stale = plan_ptr->IsPlanStale(); |
| 962 | ThreadPlan *examined_plan = plan_ptr; |
| 963 | plan_ptr = GetPreviousPlan(plan: examined_plan); |
| 964 | |
| 965 | if (stale) { |
| 966 | LLDB_LOGF( |
| 967 | log, |
| 968 | "Plan %s being discarded in cleanup, it says it is already done." , |
| 969 | examined_plan->GetName()); |
| 970 | while (GetCurrentPlan() != examined_plan) { |
| 971 | DiscardPlan(); |
| 972 | } |
| 973 | if (examined_plan->IsPlanComplete()) { |
| 974 | // plan is complete but does not explain the stop (example: step to a |
| 975 | // line with breakpoint), let us move the plan to |
| 976 | // completed_plan_stack anyway |
| 977 | PopPlan(); |
| 978 | } else |
| 979 | DiscardPlan(); |
| 980 | } |
| 981 | } |
| 982 | } |
| 983 | |
| 984 | if (log) { |
| 985 | StreamString s; |
| 986 | s.IndentMore(); |
| 987 | GetProcess()->DumpThreadPlansForTID( |
| 988 | strm&: s, tid: GetID(), desc_level: eDescriptionLevelVerbose, internal: true /* internal */, |
| 989 | condense_trivial: false /* condense_trivial */, skip_unreported_plans: true /* skip_unreported */); |
| 990 | LLDB_LOGF(log, "Plan stack final state:\n%s" , s.GetData()); |
| 991 | LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv" , |
| 992 | should_stop); |
| 993 | } |
| 994 | return should_stop; |
| 995 | } |
| 996 | |
| 997 | Vote Thread::ShouldReportStop(Event *event_ptr) { |
| 998 | StateType thread_state = GetResumeState(); |
| 999 | StateType temp_thread_state = GetTemporaryResumeState(); |
| 1000 | |
| 1001 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1002 | |
| 1003 | if (thread_state == eStateSuspended || thread_state == eStateInvalid) { |
| 1004 | LLDB_LOGF(log, |
| 1005 | "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 |
| 1006 | ": returning vote %i (state was suspended or invalid)" , |
| 1007 | GetID(), eVoteNoOpinion); |
| 1008 | return eVoteNoOpinion; |
| 1009 | } |
| 1010 | |
| 1011 | if (temp_thread_state == eStateSuspended || |
| 1012 | temp_thread_state == eStateInvalid) { |
| 1013 | LLDB_LOGF(log, |
| 1014 | "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 |
| 1015 | ": returning vote %i (temporary state was suspended or invalid)" , |
| 1016 | GetID(), eVoteNoOpinion); |
| 1017 | return eVoteNoOpinion; |
| 1018 | } |
| 1019 | |
| 1020 | if (!ThreadStoppedForAReason()) { |
| 1021 | LLDB_LOGF(log, |
| 1022 | "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 |
| 1023 | ": returning vote %i (thread didn't stop for a reason.)" , |
| 1024 | GetID(), eVoteNoOpinion); |
| 1025 | return eVoteNoOpinion; |
| 1026 | } |
| 1027 | |
| 1028 | if (GetPlans().AnyCompletedPlans()) { |
| 1029 | // Pass skip_private = false to GetCompletedPlan, since we want to ask |
| 1030 | // the last plan, regardless of whether it is private or not. |
| 1031 | LLDB_LOGF(log, |
| 1032 | "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 |
| 1033 | ": returning vote for complete stack's back plan" , |
| 1034 | GetID()); |
| 1035 | return GetPlans().GetCompletedPlan(skip_private: false)->ShouldReportStop(event_ptr); |
| 1036 | } else { |
| 1037 | Vote thread_vote = eVoteNoOpinion; |
| 1038 | ThreadPlan *plan_ptr = GetCurrentPlan(); |
| 1039 | while (true) { |
| 1040 | if (plan_ptr->PlanExplainsStop(event_ptr)) { |
| 1041 | thread_vote = plan_ptr->ShouldReportStop(event_ptr); |
| 1042 | break; |
| 1043 | } |
| 1044 | if (plan_ptr->IsBasePlan()) |
| 1045 | break; |
| 1046 | else |
| 1047 | plan_ptr = GetPreviousPlan(plan: plan_ptr); |
| 1048 | } |
| 1049 | LLDB_LOGF(log, |
| 1050 | "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 |
| 1051 | ": returning vote %i for current plan" , |
| 1052 | GetID(), thread_vote); |
| 1053 | |
| 1054 | return thread_vote; |
| 1055 | } |
| 1056 | } |
| 1057 | |
| 1058 | Vote Thread::ShouldReportRun(Event *event_ptr) { |
| 1059 | StateType thread_state = GetResumeState(); |
| 1060 | |
| 1061 | if (thread_state == eStateSuspended || thread_state == eStateInvalid) { |
| 1062 | return eVoteNoOpinion; |
| 1063 | } |
| 1064 | |
| 1065 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1066 | if (GetPlans().AnyCompletedPlans()) { |
| 1067 | // Pass skip_private = false to GetCompletedPlan, since we want to ask |
| 1068 | // the last plan, regardless of whether it is private or not. |
| 1069 | LLDB_LOGF(log, |
| 1070 | "Current Plan for thread %d(%p) (0x%4.4" PRIx64 |
| 1071 | ", %s): %s being asked whether we should report run." , |
| 1072 | GetIndexID(), static_cast<void *>(this), GetID(), |
| 1073 | StateAsCString(GetTemporaryResumeState()), |
| 1074 | GetCompletedPlan()->GetName()); |
| 1075 | |
| 1076 | return GetPlans().GetCompletedPlan(skip_private: false)->ShouldReportRun(event_ptr); |
| 1077 | } else { |
| 1078 | LLDB_LOGF(log, |
| 1079 | "Current Plan for thread %d(%p) (0x%4.4" PRIx64 |
| 1080 | ", %s): %s being asked whether we should report run." , |
| 1081 | GetIndexID(), static_cast<void *>(this), GetID(), |
| 1082 | StateAsCString(GetTemporaryResumeState()), |
| 1083 | GetCurrentPlan()->GetName()); |
| 1084 | |
| 1085 | return GetCurrentPlan()->ShouldReportRun(event_ptr); |
| 1086 | } |
| 1087 | } |
| 1088 | |
| 1089 | bool Thread::MatchesSpec(const ThreadSpec *spec) { |
| 1090 | return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(thread&: *this); |
| 1091 | } |
| 1092 | |
| 1093 | ThreadPlanStack &Thread::GetPlans() const { |
| 1094 | ThreadPlanStack *plans = GetProcess()->FindThreadPlans(tid: GetID()); |
| 1095 | if (plans) |
| 1096 | return *plans; |
| 1097 | |
| 1098 | // History threads don't have a thread plan, but they do ask get asked to |
| 1099 | // describe themselves, which usually involves pulling out the stop reason. |
| 1100 | // That in turn will check for a completed plan on the ThreadPlanStack. |
| 1101 | // Instead of special-casing at that point, we return a Stack with a |
| 1102 | // ThreadPlanNull as its base plan. That will give the right answers to the |
| 1103 | // queries GetDescription makes, and only assert if you try to run the thread. |
| 1104 | if (!m_null_plan_stack_up) |
| 1105 | m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(args: *this, args: true); |
| 1106 | return *m_null_plan_stack_up; |
| 1107 | } |
| 1108 | |
| 1109 | void Thread::PushPlan(ThreadPlanSP thread_plan_sp) { |
| 1110 | assert(thread_plan_sp && "Don't push an empty thread plan." ); |
| 1111 | |
| 1112 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1113 | if (log) { |
| 1114 | StreamString s; |
| 1115 | thread_plan_sp->GetDescription(s: &s, level: lldb::eDescriptionLevelFull); |
| 1116 | LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 "." , |
| 1117 | static_cast<void *>(this), s.GetData(), |
| 1118 | thread_plan_sp->GetThread().GetID()); |
| 1119 | } |
| 1120 | |
| 1121 | GetPlans().PushPlan(new_plan_sp: std::move(thread_plan_sp)); |
| 1122 | } |
| 1123 | |
| 1124 | void Thread::PopPlan() { |
| 1125 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1126 | ThreadPlanSP popped_plan_sp = GetPlans().PopPlan(); |
| 1127 | if (log) { |
| 1128 | LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 "." , |
| 1129 | popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID()); |
| 1130 | } |
| 1131 | } |
| 1132 | |
| 1133 | void Thread::DiscardPlan() { |
| 1134 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1135 | ThreadPlanSP discarded_plan_sp = GetPlans().DiscardPlan(); |
| 1136 | |
| 1137 | LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 "." , |
| 1138 | discarded_plan_sp->GetName(), |
| 1139 | discarded_plan_sp->GetThread().GetID()); |
| 1140 | } |
| 1141 | |
| 1142 | void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const { |
| 1143 | const ThreadPlanStack &plans = GetPlans(); |
| 1144 | if (!plans.AnyPlans()) |
| 1145 | return; |
| 1146 | |
| 1147 | // Iterate from the second plan (index: 1) to skip the base plan. |
| 1148 | ThreadPlanSP p; |
| 1149 | uint32_t i = 1; |
| 1150 | while ((p = plans.GetPlanByIndex(plan_idx: i, skip_private: false))) { |
| 1151 | StreamString strm; |
| 1152 | p->GetDescription(s: &strm, level: eDescriptionLevelInitial); |
| 1153 | request.TryCompleteCurrentArg(completion: std::to_string(val: i), description: strm.GetString()); |
| 1154 | i++; |
| 1155 | } |
| 1156 | } |
| 1157 | |
| 1158 | ThreadPlan *Thread::GetCurrentPlan() const { |
| 1159 | return GetPlans().GetCurrentPlan().get(); |
| 1160 | } |
| 1161 | |
| 1162 | ThreadPlanSP Thread::GetCompletedPlan() const { |
| 1163 | return GetPlans().GetCompletedPlan(); |
| 1164 | } |
| 1165 | |
| 1166 | ValueObjectSP Thread::GetReturnValueObject() const { |
| 1167 | return GetPlans().GetReturnValueObject(); |
| 1168 | } |
| 1169 | |
| 1170 | ExpressionVariableSP Thread::GetExpressionVariable() const { |
| 1171 | return GetPlans().GetExpressionVariable(); |
| 1172 | } |
| 1173 | |
| 1174 | bool Thread::IsThreadPlanDone(ThreadPlan *plan) const { |
| 1175 | return GetPlans().IsPlanDone(plan); |
| 1176 | } |
| 1177 | |
| 1178 | bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const { |
| 1179 | return GetPlans().WasPlanDiscarded(plan); |
| 1180 | } |
| 1181 | |
| 1182 | bool Thread::CompletedPlanOverridesBreakpoint() const { |
| 1183 | return GetPlans().AnyCompletedPlans(); |
| 1184 | } |
| 1185 | |
| 1186 | ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{ |
| 1187 | return GetPlans().GetPreviousPlan(current_plan); |
| 1188 | } |
| 1189 | |
| 1190 | Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp, |
| 1191 | bool abort_other_plans) { |
| 1192 | Status status; |
| 1193 | StreamString s; |
| 1194 | if (!thread_plan_sp->ValidatePlan(error: &s)) { |
| 1195 | DiscardThreadPlansUpToPlan(up_to_plan_sp&: thread_plan_sp); |
| 1196 | thread_plan_sp.reset(); |
| 1197 | return Status(s.GetString().str()); |
| 1198 | } |
| 1199 | |
| 1200 | if (abort_other_plans) |
| 1201 | DiscardThreadPlans(force: true); |
| 1202 | |
| 1203 | PushPlan(thread_plan_sp); |
| 1204 | |
| 1205 | // This seems a little funny, but I don't want to have to split up the |
| 1206 | // constructor and the DidPush in the scripted plan, that seems annoying. |
| 1207 | // That means the constructor has to be in DidPush. So I have to validate the |
| 1208 | // plan AFTER pushing it, and then take it off again... |
| 1209 | if (!thread_plan_sp->ValidatePlan(error: &s)) { |
| 1210 | DiscardThreadPlansUpToPlan(up_to_plan_sp&: thread_plan_sp); |
| 1211 | thread_plan_sp.reset(); |
| 1212 | return Status(s.GetString().str()); |
| 1213 | } |
| 1214 | |
| 1215 | return status; |
| 1216 | } |
| 1217 | |
| 1218 | bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) { |
| 1219 | // Count the user thread plans from the back end to get the number of the one |
| 1220 | // we want to discard: |
| 1221 | |
| 1222 | ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_idx: plan_index).get(); |
| 1223 | if (up_to_plan_ptr == nullptr) |
| 1224 | return false; |
| 1225 | |
| 1226 | DiscardThreadPlansUpToPlan(up_to_plan_ptr); |
| 1227 | return true; |
| 1228 | } |
| 1229 | |
| 1230 | void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) { |
| 1231 | DiscardThreadPlansUpToPlan(up_to_plan_ptr: up_to_plan_sp.get()); |
| 1232 | } |
| 1233 | |
| 1234 | void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { |
| 1235 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1236 | LLDB_LOGF(log, |
| 1237 | "Discarding thread plans for thread tid = 0x%4.4" PRIx64 |
| 1238 | ", up to %p" , |
| 1239 | GetID(), static_cast<void *>(up_to_plan_ptr)); |
| 1240 | GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr); |
| 1241 | } |
| 1242 | |
| 1243 | void Thread::DiscardThreadPlans(bool force) { |
| 1244 | Log *log = GetLog(mask: LLDBLog::Step); |
| 1245 | if (log) { |
| 1246 | LLDB_LOGF(log, |
| 1247 | "Discarding thread plans for thread (tid = 0x%4.4" PRIx64 |
| 1248 | ", force %d)" , |
| 1249 | GetID(), force); |
| 1250 | } |
| 1251 | |
| 1252 | if (force) { |
| 1253 | GetPlans().DiscardAllPlans(); |
| 1254 | return; |
| 1255 | } |
| 1256 | GetPlans().DiscardConsultingControllingPlans(); |
| 1257 | } |
| 1258 | |
| 1259 | Status Thread::UnwindInnermostExpression() { |
| 1260 | Status error; |
| 1261 | ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression(); |
| 1262 | if (!innermost_expr_plan) { |
| 1263 | error = Status::FromErrorString( |
| 1264 | str: "No expressions currently active on this thread" ); |
| 1265 | return error; |
| 1266 | } |
| 1267 | DiscardThreadPlansUpToPlan(up_to_plan_ptr: innermost_expr_plan); |
| 1268 | return error; |
| 1269 | } |
| 1270 | |
| 1271 | ThreadPlanSP Thread::QueueBasePlan(bool abort_other_plans) { |
| 1272 | ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this)); |
| 1273 | QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1274 | return thread_plan_sp; |
| 1275 | } |
| 1276 | |
| 1277 | ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction( |
| 1278 | bool step_over, bool abort_other_plans, bool stop_other_threads, |
| 1279 | Status &status) { |
| 1280 | ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction( |
| 1281 | *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion)); |
| 1282 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1283 | return thread_plan_sp; |
| 1284 | } |
| 1285 | |
| 1286 | ThreadPlanSP Thread::QueueThreadPlanForStepOverRange( |
| 1287 | bool abort_other_plans, const AddressRange &range, |
| 1288 | const SymbolContext &addr_context, lldb::RunMode stop_other_threads, |
| 1289 | Status &status, LazyBool step_out_avoids_code_withoug_debug_info) { |
| 1290 | ThreadPlanSP thread_plan_sp; |
| 1291 | thread_plan_sp = std::make_shared<ThreadPlanStepOverRange>( |
| 1292 | args&: *this, args: range, args: addr_context, args&: stop_other_threads, |
| 1293 | args&: step_out_avoids_code_withoug_debug_info); |
| 1294 | |
| 1295 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1296 | return thread_plan_sp; |
| 1297 | } |
| 1298 | |
| 1299 | // Call the QueueThreadPlanForStepOverRange method which takes an address |
| 1300 | // range. |
| 1301 | ThreadPlanSP Thread::QueueThreadPlanForStepOverRange( |
| 1302 | bool abort_other_plans, const LineEntry &line_entry, |
| 1303 | const SymbolContext &addr_context, lldb::RunMode stop_other_threads, |
| 1304 | Status &status, LazyBool step_out_avoids_code_withoug_debug_info) { |
| 1305 | const bool include_inlined_functions = true; |
| 1306 | auto address_range = |
| 1307 | line_entry.GetSameLineContiguousAddressRange(include_inlined_functions); |
| 1308 | return QueueThreadPlanForStepOverRange( |
| 1309 | abort_other_plans, range: address_range, addr_context, stop_other_threads, |
| 1310 | status, step_out_avoids_code_withoug_debug_info); |
| 1311 | } |
| 1312 | |
| 1313 | ThreadPlanSP Thread::QueueThreadPlanForStepInRange( |
| 1314 | bool abort_other_plans, const AddressRange &range, |
| 1315 | const SymbolContext &addr_context, const char *step_in_target, |
| 1316 | lldb::RunMode stop_other_threads, Status &status, |
| 1317 | LazyBool step_in_avoids_code_without_debug_info, |
| 1318 | LazyBool step_out_avoids_code_without_debug_info) { |
| 1319 | ThreadPlanSP thread_plan_sp(new ThreadPlanStepInRange( |
| 1320 | *this, range, addr_context, step_in_target, stop_other_threads, |
| 1321 | step_in_avoids_code_without_debug_info, |
| 1322 | step_out_avoids_code_without_debug_info)); |
| 1323 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1324 | return thread_plan_sp; |
| 1325 | } |
| 1326 | |
| 1327 | // Call the QueueThreadPlanForStepInRange method which takes an address range. |
| 1328 | ThreadPlanSP Thread::QueueThreadPlanForStepInRange( |
| 1329 | bool abort_other_plans, const LineEntry &line_entry, |
| 1330 | const SymbolContext &addr_context, const char *step_in_target, |
| 1331 | lldb::RunMode stop_other_threads, Status &status, |
| 1332 | LazyBool step_in_avoids_code_without_debug_info, |
| 1333 | LazyBool step_out_avoids_code_without_debug_info) { |
| 1334 | const bool include_inlined_functions = false; |
| 1335 | return QueueThreadPlanForStepInRange( |
| 1336 | abort_other_plans, |
| 1337 | range: line_entry.GetSameLineContiguousAddressRange(include_inlined_functions), |
| 1338 | addr_context, step_in_target, stop_other_threads, status, |
| 1339 | step_in_avoids_code_without_debug_info, |
| 1340 | step_out_avoids_code_without_debug_info); |
| 1341 | } |
| 1342 | |
| 1343 | ThreadPlanSP Thread::QueueThreadPlanForStepOut( |
| 1344 | bool abort_other_plans, SymbolContext *addr_context, bool first_insn, |
| 1345 | bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote, |
| 1346 | uint32_t frame_idx, Status &status, |
| 1347 | LazyBool step_out_avoids_code_without_debug_info) { |
| 1348 | ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut( |
| 1349 | *this, addr_context, first_insn, stop_other_threads, report_stop_vote, |
| 1350 | report_run_vote, frame_idx, step_out_avoids_code_without_debug_info)); |
| 1351 | |
| 1352 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1353 | return thread_plan_sp; |
| 1354 | } |
| 1355 | |
| 1356 | ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop( |
| 1357 | bool abort_other_plans, SymbolContext *addr_context, bool first_insn, |
| 1358 | bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote, |
| 1359 | uint32_t frame_idx, Status &status, bool continue_to_next_branch) { |
| 1360 | const bool calculate_return_value = |
| 1361 | false; // No need to calculate the return value here. |
| 1362 | ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut( |
| 1363 | *this, stop_other_threads, report_stop_vote, report_run_vote, frame_idx, |
| 1364 | continue_to_next_branch, calculate_return_value)); |
| 1365 | |
| 1366 | ThreadPlanStepOut *new_plan = |
| 1367 | static_cast<ThreadPlanStepOut *>(thread_plan_sp.get()); |
| 1368 | new_plan->ClearShouldStopHereCallbacks(); |
| 1369 | |
| 1370 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1371 | return thread_plan_sp; |
| 1372 | } |
| 1373 | |
| 1374 | ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id, |
| 1375 | bool abort_other_plans, |
| 1376 | bool stop_other_threads, |
| 1377 | Status &status) { |
| 1378 | ThreadPlanSP thread_plan_sp( |
| 1379 | new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads)); |
| 1380 | if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(error: nullptr)) |
| 1381 | return ThreadPlanSP(); |
| 1382 | |
| 1383 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1384 | return thread_plan_sp; |
| 1385 | } |
| 1386 | |
| 1387 | ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans, |
| 1388 | Address &target_addr, |
| 1389 | bool stop_other_threads, |
| 1390 | Status &status) { |
| 1391 | ThreadPlanSP thread_plan_sp( |
| 1392 | new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads)); |
| 1393 | |
| 1394 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1395 | return thread_plan_sp; |
| 1396 | } |
| 1397 | |
| 1398 | ThreadPlanSP Thread::QueueThreadPlanForStepUntil( |
| 1399 | bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses, |
| 1400 | bool stop_other_threads, uint32_t frame_idx, Status &status) { |
| 1401 | ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil( |
| 1402 | *this, address_list, num_addresses, stop_other_threads, frame_idx)); |
| 1403 | |
| 1404 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1405 | return thread_plan_sp; |
| 1406 | } |
| 1407 | |
| 1408 | lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted( |
| 1409 | bool abort_other_plans, const char *class_name, |
| 1410 | StructuredData::ObjectSP , bool stop_other_threads, |
| 1411 | Status &status) { |
| 1412 | |
| 1413 | ThreadPlanSP thread_plan_sp(new ScriptedThreadPlan( |
| 1414 | *this, class_name, StructuredDataImpl(extra_args_sp))); |
| 1415 | thread_plan_sp->SetStopOthers(stop_other_threads); |
| 1416 | status = QueueThreadPlan(thread_plan_sp, abort_other_plans); |
| 1417 | return thread_plan_sp; |
| 1418 | } |
| 1419 | |
| 1420 | uint32_t Thread::GetIndexID() const { return m_index_id; } |
| 1421 | |
| 1422 | TargetSP Thread::CalculateTarget() { |
| 1423 | TargetSP target_sp; |
| 1424 | ProcessSP process_sp(GetProcess()); |
| 1425 | if (process_sp) |
| 1426 | target_sp = process_sp->CalculateTarget(); |
| 1427 | return target_sp; |
| 1428 | } |
| 1429 | |
| 1430 | ProcessSP Thread::CalculateProcess() { return GetProcess(); } |
| 1431 | |
| 1432 | ThreadSP Thread::CalculateThread() { return shared_from_this(); } |
| 1433 | |
| 1434 | StackFrameSP Thread::CalculateStackFrame() { return StackFrameSP(); } |
| 1435 | |
| 1436 | void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) { |
| 1437 | exe_ctx.SetContext(shared_from_this()); |
| 1438 | } |
| 1439 | |
| 1440 | StackFrameListSP Thread::GetStackFrameList() { |
| 1441 | std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); |
| 1442 | |
| 1443 | if (!m_curr_frames_sp) |
| 1444 | m_curr_frames_sp = |
| 1445 | std::make_shared<StackFrameList>(args&: *this, args&: m_prev_frames_sp, args: true); |
| 1446 | |
| 1447 | return m_curr_frames_sp; |
| 1448 | } |
| 1449 | |
| 1450 | std::optional<addr_t> Thread::GetPreviousFrameZeroPC() { |
| 1451 | return m_prev_framezero_pc; |
| 1452 | } |
| 1453 | |
| 1454 | void Thread::ClearStackFrames() { |
| 1455 | std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); |
| 1456 | |
| 1457 | GetUnwinder().Clear(); |
| 1458 | m_prev_framezero_pc.reset(); |
| 1459 | if (RegisterContextSP reg_ctx_sp = GetRegisterContext()) |
| 1460 | m_prev_framezero_pc = reg_ctx_sp->GetPC(); |
| 1461 | |
| 1462 | // Only store away the old "reference" StackFrameList if we got all its |
| 1463 | // frames: |
| 1464 | // FIXME: At some point we can try to splice in the frames we have fetched |
| 1465 | // into the new frame as we make it, but let's not try that now. |
| 1466 | if (m_curr_frames_sp && m_curr_frames_sp->WereAllFramesFetched()) |
| 1467 | m_prev_frames_sp.swap(other&: m_curr_frames_sp); |
| 1468 | m_curr_frames_sp.reset(); |
| 1469 | |
| 1470 | m_extended_info.reset(); |
| 1471 | m_extended_info_fetched = false; |
| 1472 | } |
| 1473 | |
| 1474 | lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) { |
| 1475 | return GetStackFrameList()->GetFrameWithConcreteFrameIndex(unwind_idx); |
| 1476 | } |
| 1477 | |
| 1478 | Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx, |
| 1479 | lldb::ValueObjectSP return_value_sp, |
| 1480 | bool broadcast) { |
| 1481 | StackFrameSP frame_sp = GetStackFrameAtIndex(idx: frame_idx); |
| 1482 | Status return_error; |
| 1483 | |
| 1484 | if (!frame_sp) { |
| 1485 | return_error = Status::FromErrorStringWithFormat( |
| 1486 | format: "Could not find frame with index %d in thread 0x%" PRIx64 "." , |
| 1487 | frame_idx, GetID()); |
| 1488 | } |
| 1489 | |
| 1490 | return ReturnFromFrame(frame_sp, return_value_sp, broadcast); |
| 1491 | } |
| 1492 | |
| 1493 | Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp, |
| 1494 | lldb::ValueObjectSP return_value_sp, |
| 1495 | bool broadcast) { |
| 1496 | Status return_error; |
| 1497 | |
| 1498 | if (!frame_sp) { |
| 1499 | return_error = Status::FromErrorString(str: "Can't return to a null frame." ); |
| 1500 | return return_error; |
| 1501 | } |
| 1502 | |
| 1503 | Thread *thread = frame_sp->GetThread().get(); |
| 1504 | uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1; |
| 1505 | StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(idx: older_frame_idx); |
| 1506 | if (!older_frame_sp) { |
| 1507 | return_error = Status::FromErrorString(str: "No older frame to return to." ); |
| 1508 | return return_error; |
| 1509 | } |
| 1510 | |
| 1511 | if (return_value_sp) { |
| 1512 | lldb::ABISP abi = thread->GetProcess()->GetABI(); |
| 1513 | if (!abi) { |
| 1514 | return_error = |
| 1515 | Status::FromErrorString(str: "Could not find ABI to set return value." ); |
| 1516 | return return_error; |
| 1517 | } |
| 1518 | SymbolContext sc = frame_sp->GetSymbolContext(resolve_scope: eSymbolContextFunction); |
| 1519 | |
| 1520 | // FIXME: ValueObject::Cast doesn't currently work correctly, at least not |
| 1521 | // for scalars. |
| 1522 | // Turn that back on when that works. |
| 1523 | if (/* DISABLES CODE */ (false) && sc.function != nullptr) { |
| 1524 | Type *function_type = sc.function->GetType(); |
| 1525 | if (function_type) { |
| 1526 | CompilerType return_type = |
| 1527 | sc.function->GetCompilerType().GetFunctionReturnType(); |
| 1528 | if (return_type) { |
| 1529 | StreamString s; |
| 1530 | return_type.DumpTypeDescription(s: &s); |
| 1531 | ValueObjectSP cast_value_sp = return_value_sp->Cast(compiler_type: return_type); |
| 1532 | if (cast_value_sp) { |
| 1533 | cast_value_sp->SetFormat(eFormatHex); |
| 1534 | return_value_sp = cast_value_sp; |
| 1535 | } |
| 1536 | } |
| 1537 | } |
| 1538 | } |
| 1539 | |
| 1540 | return_error = abi->SetReturnValueObject(frame_sp&: older_frame_sp, new_value&: return_value_sp); |
| 1541 | if (!return_error.Success()) |
| 1542 | return return_error; |
| 1543 | } |
| 1544 | |
| 1545 | // Now write the return registers for the chosen frame: Note, we can't use |
| 1546 | // ReadAllRegisterValues->WriteAllRegisterValues, since the read & write cook |
| 1547 | // their data |
| 1548 | |
| 1549 | StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(idx: 0); |
| 1550 | if (youngest_frame_sp) { |
| 1551 | lldb::RegisterContextSP reg_ctx_sp(youngest_frame_sp->GetRegisterContext()); |
| 1552 | if (reg_ctx_sp) { |
| 1553 | bool copy_success = reg_ctx_sp->CopyFromRegisterContext( |
| 1554 | context: older_frame_sp->GetRegisterContext()); |
| 1555 | if (copy_success) { |
| 1556 | thread->DiscardThreadPlans(force: true); |
| 1557 | thread->ClearStackFrames(); |
| 1558 | if (broadcast && EventTypeHasListeners(event_type: eBroadcastBitStackChanged)) { |
| 1559 | auto data_sp = std::make_shared<ThreadEventData>(args: shared_from_this()); |
| 1560 | BroadcastEvent(event_type: eBroadcastBitStackChanged, event_data_sp: data_sp); |
| 1561 | } |
| 1562 | } else { |
| 1563 | return_error = |
| 1564 | Status::FromErrorString(str: "Could not reset register values." ); |
| 1565 | } |
| 1566 | } else { |
| 1567 | return_error = Status::FromErrorString(str: "Frame has no register context." ); |
| 1568 | } |
| 1569 | } else { |
| 1570 | return_error = Status::FromErrorString(str: "Returned past top frame." ); |
| 1571 | } |
| 1572 | return return_error; |
| 1573 | } |
| 1574 | |
| 1575 | static void DumpAddressList(Stream &s, const std::vector<Address> &list, |
| 1576 | ExecutionContextScope *exe_scope) { |
| 1577 | for (size_t n = 0; n < list.size(); n++) { |
| 1578 | s << "\t" ; |
| 1579 | list[n].Dump(s: &s, exe_scope, style: Address::DumpStyleResolvedDescription, |
| 1580 | fallback_style: Address::DumpStyleSectionNameOffset); |
| 1581 | s << "\n" ; |
| 1582 | } |
| 1583 | } |
| 1584 | |
| 1585 | Status Thread::JumpToLine(const FileSpec &file, uint32_t line, |
| 1586 | bool can_leave_function, std::string *warnings) { |
| 1587 | ExecutionContext exe_ctx(GetStackFrameAtIndex(idx: 0)); |
| 1588 | Target *target = exe_ctx.GetTargetPtr(); |
| 1589 | TargetSP target_sp = exe_ctx.GetTargetSP(); |
| 1590 | RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); |
| 1591 | StackFrame *frame = exe_ctx.GetFramePtr(); |
| 1592 | const SymbolContext &sc = frame->GetSymbolContext(resolve_scope: eSymbolContextFunction); |
| 1593 | |
| 1594 | // Find candidate locations. |
| 1595 | std::vector<Address> candidates, within_function, outside_function; |
| 1596 | target->GetImages().FindAddressesForLine(target_sp, file, line, function: sc.function, |
| 1597 | output_local&: within_function, output_extern&: outside_function); |
| 1598 | |
| 1599 | // If possible, we try and stay within the current function. Within a |
| 1600 | // function, we accept multiple locations (optimized code may do this, |
| 1601 | // there's no solution here so we do the best we can). However if we're |
| 1602 | // trying to leave the function, we don't know how to pick the right |
| 1603 | // location, so if there's more than one then we bail. |
| 1604 | if (!within_function.empty()) |
| 1605 | candidates = within_function; |
| 1606 | else if (outside_function.size() == 1 && can_leave_function) |
| 1607 | candidates = outside_function; |
| 1608 | |
| 1609 | // Check if we got anything. |
| 1610 | if (candidates.empty()) { |
| 1611 | if (outside_function.empty()) { |
| 1612 | return Status::FromErrorStringWithFormat( |
| 1613 | format: "Cannot locate an address for %s:%i." , file.GetFilename().AsCString(), |
| 1614 | line); |
| 1615 | } else if (outside_function.size() == 1) { |
| 1616 | return Status::FromErrorStringWithFormat( |
| 1617 | format: "%s:%i is outside the current function." , |
| 1618 | file.GetFilename().AsCString(), line); |
| 1619 | } else { |
| 1620 | StreamString sstr; |
| 1621 | DumpAddressList(s&: sstr, list: outside_function, exe_scope: target); |
| 1622 | return Status::FromErrorStringWithFormat( |
| 1623 | format: "%s:%i has multiple candidate locations:\n%s" , |
| 1624 | file.GetFilename().AsCString(), line, sstr.GetData()); |
| 1625 | } |
| 1626 | } |
| 1627 | |
| 1628 | // Accept the first location, warn about any others. |
| 1629 | Address dest = candidates[0]; |
| 1630 | if (warnings && candidates.size() > 1) { |
| 1631 | StreamString sstr; |
| 1632 | sstr.Printf(format: "%s:%i appears multiple times in this function, selecting the " |
| 1633 | "first location:\n" , |
| 1634 | file.GetFilename().AsCString(), line); |
| 1635 | DumpAddressList(s&: sstr, list: candidates, exe_scope: target); |
| 1636 | *warnings = std::string(sstr.GetString()); |
| 1637 | } |
| 1638 | |
| 1639 | if (!reg_ctx->SetPC(dest)) |
| 1640 | return Status::FromErrorString(str: "Cannot change PC to target address." ); |
| 1641 | |
| 1642 | return Status(); |
| 1643 | } |
| 1644 | |
| 1645 | bool Thread::DumpUsingFormat(Stream &strm, uint32_t frame_idx, |
| 1646 | const FormatEntity::Entry *format) { |
| 1647 | ExecutionContext exe_ctx(shared_from_this()); |
| 1648 | Process *process = exe_ctx.GetProcessPtr(); |
| 1649 | if (!process || !format) |
| 1650 | return false; |
| 1651 | |
| 1652 | StackFrameSP frame_sp; |
| 1653 | SymbolContext frame_sc; |
| 1654 | if (frame_idx != LLDB_INVALID_FRAME_ID) { |
| 1655 | frame_sp = GetStackFrameAtIndex(idx: frame_idx); |
| 1656 | if (frame_sp) { |
| 1657 | exe_ctx.SetFrameSP(frame_sp); |
| 1658 | frame_sc = frame_sp->GetSymbolContext(resolve_scope: eSymbolContextEverything); |
| 1659 | } |
| 1660 | } |
| 1661 | |
| 1662 | return FormatEntity::Format(entry: *format, s&: strm, sc: frame_sp ? &frame_sc : nullptr, |
| 1663 | exe_ctx: &exe_ctx, addr: nullptr, valobj: nullptr, function_changed: false, initial_function: false); |
| 1664 | } |
| 1665 | |
| 1666 | void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, |
| 1667 | bool stop_format) { |
| 1668 | ExecutionContext exe_ctx(shared_from_this()); |
| 1669 | |
| 1670 | const FormatEntity::Entry *thread_format; |
| 1671 | FormatEntity::Entry format_entry; |
| 1672 | if (stop_format) { |
| 1673 | format_entry = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); |
| 1674 | thread_format = &format_entry; |
| 1675 | } else { |
| 1676 | format_entry = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); |
| 1677 | thread_format = &format_entry; |
| 1678 | } |
| 1679 | |
| 1680 | assert(thread_format); |
| 1681 | |
| 1682 | DumpUsingFormat(strm, frame_idx, format: thread_format); |
| 1683 | } |
| 1684 | |
| 1685 | void Thread::SettingsInitialize() {} |
| 1686 | |
| 1687 | void Thread::SettingsTerminate() {} |
| 1688 | |
| 1689 | lldb::addr_t Thread::GetThreadPointer() { |
| 1690 | if (m_reg_context_sp) |
| 1691 | return m_reg_context_sp->GetThreadPointer(); |
| 1692 | return LLDB_INVALID_ADDRESS; |
| 1693 | } |
| 1694 | |
| 1695 | addr_t Thread::GetThreadLocalData(const ModuleSP module, |
| 1696 | lldb::addr_t tls_file_addr) { |
| 1697 | // The default implementation is to ask the dynamic loader for it. This can |
| 1698 | // be overridden for specific platforms. |
| 1699 | DynamicLoader *loader = GetProcess()->GetDynamicLoader(); |
| 1700 | if (loader) |
| 1701 | return loader->GetThreadLocalData(module, thread: shared_from_this(), |
| 1702 | tls_file_addr); |
| 1703 | else |
| 1704 | return LLDB_INVALID_ADDRESS; |
| 1705 | } |
| 1706 | |
| 1707 | bool Thread::SafeToCallFunctions() { |
| 1708 | Process *process = GetProcess().get(); |
| 1709 | if (process) { |
| 1710 | DynamicLoader *loader = GetProcess()->GetDynamicLoader(); |
| 1711 | if (loader && loader->IsFullyInitialized() == false) |
| 1712 | return false; |
| 1713 | |
| 1714 | SystemRuntime *runtime = process->GetSystemRuntime(); |
| 1715 | if (runtime) { |
| 1716 | return runtime->SafeToCallFunctionsOnThisThread(thread_sp: shared_from_this()); |
| 1717 | } |
| 1718 | } |
| 1719 | return true; |
| 1720 | } |
| 1721 | |
| 1722 | lldb::StackFrameSP |
| 1723 | Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) { |
| 1724 | return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr); |
| 1725 | } |
| 1726 | |
| 1727 | std::string Thread::StopReasonAsString(lldb::StopReason reason) { |
| 1728 | switch (reason) { |
| 1729 | case eStopReasonInvalid: |
| 1730 | return "invalid" ; |
| 1731 | case eStopReasonNone: |
| 1732 | return "none" ; |
| 1733 | case eStopReasonTrace: |
| 1734 | return "trace" ; |
| 1735 | case eStopReasonBreakpoint: |
| 1736 | return "breakpoint" ; |
| 1737 | case eStopReasonWatchpoint: |
| 1738 | return "watchpoint" ; |
| 1739 | case eStopReasonSignal: |
| 1740 | return "signal" ; |
| 1741 | case eStopReasonException: |
| 1742 | return "exception" ; |
| 1743 | case eStopReasonExec: |
| 1744 | return "exec" ; |
| 1745 | case eStopReasonFork: |
| 1746 | return "fork" ; |
| 1747 | case eStopReasonVFork: |
| 1748 | return "vfork" ; |
| 1749 | case eStopReasonVForkDone: |
| 1750 | return "vfork done" ; |
| 1751 | case eStopReasonPlanComplete: |
| 1752 | return "plan complete" ; |
| 1753 | case eStopReasonThreadExiting: |
| 1754 | return "thread exiting" ; |
| 1755 | case eStopReasonInstrumentation: |
| 1756 | return "instrumentation break" ; |
| 1757 | case eStopReasonProcessorTrace: |
| 1758 | return "processor trace" ; |
| 1759 | case eStopReasonInterrupt: |
| 1760 | return "async interrupt" ; |
| 1761 | case eStopReasonHistoryBoundary: |
| 1762 | return "history boundary" ; |
| 1763 | } |
| 1764 | |
| 1765 | return "StopReason = " + std::to_string(val: reason); |
| 1766 | } |
| 1767 | |
| 1768 | std::string Thread::RunModeAsString(lldb::RunMode mode) { |
| 1769 | switch (mode) { |
| 1770 | case eOnlyThisThread: |
| 1771 | return "only this thread" ; |
| 1772 | case eAllThreads: |
| 1773 | return "all threads" ; |
| 1774 | case eOnlyDuringStepping: |
| 1775 | return "only during stepping" ; |
| 1776 | } |
| 1777 | |
| 1778 | return "RunMode = " + std::to_string(val: mode); |
| 1779 | } |
| 1780 | |
| 1781 | size_t Thread::GetStatus(Stream &strm, uint32_t start_frame, |
| 1782 | uint32_t num_frames, uint32_t num_frames_with_source, |
| 1783 | bool stop_format, bool show_hidden, bool only_stacks) { |
| 1784 | |
| 1785 | if (!only_stacks) { |
| 1786 | ExecutionContext exe_ctx(shared_from_this()); |
| 1787 | Target *target = exe_ctx.GetTargetPtr(); |
| 1788 | Process *process = exe_ctx.GetProcessPtr(); |
| 1789 | strm.Indent(); |
| 1790 | bool is_selected = false; |
| 1791 | if (process) { |
| 1792 | if (process->GetThreadList().GetSelectedThread().get() == this) |
| 1793 | is_selected = true; |
| 1794 | } |
| 1795 | strm.Printf(format: "%c " , is_selected ? '*' : ' '); |
| 1796 | if (target && target->GetDebugger().GetUseExternalEditor()) { |
| 1797 | StackFrameSP frame_sp = GetStackFrameAtIndex(idx: start_frame); |
| 1798 | if (frame_sp) { |
| 1799 | SymbolContext frame_sc( |
| 1800 | frame_sp->GetSymbolContext(resolve_scope: eSymbolContextLineEntry)); |
| 1801 | if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.GetFile()) { |
| 1802 | if (llvm::Error e = Host::OpenFileInExternalEditor( |
| 1803 | editor: target->GetDebugger().GetExternalEditor(), |
| 1804 | file_spec: frame_sc.line_entry.GetFile(), line_no: frame_sc.line_entry.line)) { |
| 1805 | LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), |
| 1806 | "OpenFileInExternalEditor failed: {0}" ); |
| 1807 | } |
| 1808 | } |
| 1809 | } |
| 1810 | } |
| 1811 | |
| 1812 | DumpUsingSettingsFormat(strm, frame_idx: start_frame, stop_format); |
| 1813 | } |
| 1814 | |
| 1815 | size_t num_frames_shown = 0; |
| 1816 | if (num_frames > 0) { |
| 1817 | strm.IndentMore(); |
| 1818 | |
| 1819 | const bool show_frame_info = true; |
| 1820 | const bool show_frame_unique = only_stacks; |
| 1821 | const char *selected_frame_marker = nullptr; |
| 1822 | if (num_frames == 1 || only_stacks || |
| 1823 | (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID())) |
| 1824 | strm.IndentMore(); |
| 1825 | else |
| 1826 | selected_frame_marker = "* " ; |
| 1827 | |
| 1828 | num_frames_shown = GetStackFrameList()->GetStatus( |
| 1829 | strm, first_frame: start_frame, num_frames, show_frame_info, num_frames_with_source, |
| 1830 | show_unique: show_frame_unique, show_hidden, frame_marker: selected_frame_marker); |
| 1831 | if (num_frames == 1) |
| 1832 | strm.IndentLess(); |
| 1833 | strm.IndentLess(); |
| 1834 | } |
| 1835 | return num_frames_shown; |
| 1836 | } |
| 1837 | |
| 1838 | bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level, |
| 1839 | bool print_json_thread, bool print_json_stopinfo) { |
| 1840 | const bool stop_format = false; |
| 1841 | DumpUsingSettingsFormat(strm, frame_idx: 0, stop_format); |
| 1842 | strm.Printf(format: "\n" ); |
| 1843 | |
| 1844 | StructuredData::ObjectSP thread_info = GetExtendedInfo(); |
| 1845 | |
| 1846 | if (print_json_thread || print_json_stopinfo) { |
| 1847 | if (thread_info && print_json_thread) { |
| 1848 | thread_info->Dump(s&: strm); |
| 1849 | strm.Printf(format: "\n" ); |
| 1850 | } |
| 1851 | |
| 1852 | if (print_json_stopinfo && m_stop_info_sp) { |
| 1853 | StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo(); |
| 1854 | if (stop_info) { |
| 1855 | stop_info->Dump(s&: strm); |
| 1856 | strm.Printf(format: "\n" ); |
| 1857 | } |
| 1858 | } |
| 1859 | |
| 1860 | return true; |
| 1861 | } |
| 1862 | |
| 1863 | if (thread_info) { |
| 1864 | StructuredData::ObjectSP activity = |
| 1865 | thread_info->GetObjectForDotSeparatedPath(path: "activity" ); |
| 1866 | StructuredData::ObjectSP breadcrumb = |
| 1867 | thread_info->GetObjectForDotSeparatedPath(path: "breadcrumb" ); |
| 1868 | StructuredData::ObjectSP messages = |
| 1869 | thread_info->GetObjectForDotSeparatedPath(path: "trace_messages" ); |
| 1870 | |
| 1871 | bool printed_activity = false; |
| 1872 | if (activity && activity->GetType() == eStructuredDataTypeDictionary) { |
| 1873 | StructuredData::Dictionary *activity_dict = activity->GetAsDictionary(); |
| 1874 | StructuredData::ObjectSP id = activity_dict->GetValueForKey(key: "id" ); |
| 1875 | StructuredData::ObjectSP name = activity_dict->GetValueForKey(key: "name" ); |
| 1876 | if (name && name->GetType() == eStructuredDataTypeString && id && |
| 1877 | id->GetType() == eStructuredDataTypeInteger) { |
| 1878 | strm.Format(format: " Activity '{0}', {1:x}\n" , |
| 1879 | args: name->GetAsString()->GetValue(), |
| 1880 | args: id->GetUnsignedIntegerValue()); |
| 1881 | } |
| 1882 | printed_activity = true; |
| 1883 | } |
| 1884 | bool printed_breadcrumb = false; |
| 1885 | if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) { |
| 1886 | if (printed_activity) |
| 1887 | strm.Printf(format: "\n" ); |
| 1888 | StructuredData::Dictionary *breadcrumb_dict = |
| 1889 | breadcrumb->GetAsDictionary(); |
| 1890 | StructuredData::ObjectSP breadcrumb_text = |
| 1891 | breadcrumb_dict->GetValueForKey(key: "name" ); |
| 1892 | if (breadcrumb_text && |
| 1893 | breadcrumb_text->GetType() == eStructuredDataTypeString) { |
| 1894 | strm.Format(format: " Current Breadcrumb: {0}\n" , |
| 1895 | args: breadcrumb_text->GetAsString()->GetValue()); |
| 1896 | } |
| 1897 | printed_breadcrumb = true; |
| 1898 | } |
| 1899 | if (messages && messages->GetType() == eStructuredDataTypeArray) { |
| 1900 | if (printed_breadcrumb) |
| 1901 | strm.Printf(format: "\n" ); |
| 1902 | StructuredData::Array *messages_array = messages->GetAsArray(); |
| 1903 | const size_t msg_count = messages_array->GetSize(); |
| 1904 | if (msg_count > 0) { |
| 1905 | strm.Printf(format: " %zu trace messages:\n" , msg_count); |
| 1906 | for (size_t i = 0; i < msg_count; i++) { |
| 1907 | StructuredData::ObjectSP message = messages_array->GetItemAtIndex(idx: i); |
| 1908 | if (message && message->GetType() == eStructuredDataTypeDictionary) { |
| 1909 | StructuredData::Dictionary *message_dict = |
| 1910 | message->GetAsDictionary(); |
| 1911 | StructuredData::ObjectSP message_text = |
| 1912 | message_dict->GetValueForKey(key: "message" ); |
| 1913 | if (message_text && |
| 1914 | message_text->GetType() == eStructuredDataTypeString) { |
| 1915 | strm.Format(format: " {0}\n" , args: message_text->GetAsString()->GetValue()); |
| 1916 | } |
| 1917 | } |
| 1918 | } |
| 1919 | } |
| 1920 | } |
| 1921 | } |
| 1922 | |
| 1923 | return true; |
| 1924 | } |
| 1925 | |
| 1926 | size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame, |
| 1927 | uint32_t num_frames, bool show_frame_info, |
| 1928 | uint32_t num_frames_with_source, |
| 1929 | bool show_hidden) { |
| 1930 | return GetStackFrameList()->GetStatus(strm, first_frame, num_frames, |
| 1931 | show_frame_info, num_frames_with_source, |
| 1932 | /*show_unique*/ false, show_hidden); |
| 1933 | } |
| 1934 | |
| 1935 | Unwind &Thread::GetUnwinder() { |
| 1936 | if (!m_unwinder_up) |
| 1937 | m_unwinder_up = std::make_unique<UnwindLLDB>(args&: *this); |
| 1938 | return *m_unwinder_up; |
| 1939 | } |
| 1940 | |
| 1941 | void Thread::Flush() { |
| 1942 | ClearStackFrames(); |
| 1943 | m_reg_context_sp.reset(); |
| 1944 | m_stopped_at_unexecuted_bp = LLDB_INVALID_ADDRESS; |
| 1945 | } |
| 1946 | |
| 1947 | bool Thread::IsStillAtLastBreakpointHit() { |
| 1948 | // If we are currently stopped at a breakpoint, always return that stopinfo |
| 1949 | // and don't reset it. This allows threads to maintain their breakpoint |
| 1950 | // stopinfo, such as when thread-stepping in multithreaded programs. |
| 1951 | if (m_stop_info_sp) { |
| 1952 | StopReason stop_reason = m_stop_info_sp->GetStopReason(); |
| 1953 | if (stop_reason == lldb::eStopReasonBreakpoint) { |
| 1954 | uint64_t value = m_stop_info_sp->GetValue(); |
| 1955 | lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); |
| 1956 | if (reg_ctx_sp) { |
| 1957 | lldb::addr_t pc = reg_ctx_sp->GetPC(); |
| 1958 | BreakpointSiteSP bp_site_sp = |
| 1959 | GetProcess()->GetBreakpointSiteList().FindByAddress(addr: pc); |
| 1960 | if (bp_site_sp && static_cast<break_id_t>(value) == bp_site_sp->GetID()) |
| 1961 | return true; |
| 1962 | } |
| 1963 | } |
| 1964 | } |
| 1965 | return false; |
| 1966 | } |
| 1967 | |
| 1968 | Status Thread::StepIn(bool source_step, |
| 1969 | LazyBool step_in_avoids_code_without_debug_info, |
| 1970 | LazyBool step_out_avoids_code_without_debug_info) |
| 1971 | |
| 1972 | { |
| 1973 | Status error; |
| 1974 | Process *process = GetProcess().get(); |
| 1975 | if (StateIsStoppedState(state: process->GetState(), must_exist: true)) { |
| 1976 | StackFrameSP frame_sp = GetStackFrameAtIndex(idx: 0); |
| 1977 | ThreadPlanSP new_plan_sp; |
| 1978 | const lldb::RunMode run_mode = eOnlyThisThread; |
| 1979 | const bool abort_other_plans = false; |
| 1980 | |
| 1981 | if (source_step && frame_sp && frame_sp->HasDebugInformation()) { |
| 1982 | SymbolContext sc(frame_sp->GetSymbolContext(resolve_scope: eSymbolContextEverything)); |
| 1983 | new_plan_sp = QueueThreadPlanForStepInRange( |
| 1984 | abort_other_plans, line_entry: sc.line_entry, addr_context: sc, step_in_target: nullptr, stop_other_threads: run_mode, status&: error, |
| 1985 | step_in_avoids_code_without_debug_info, |
| 1986 | step_out_avoids_code_without_debug_info); |
| 1987 | } else { |
| 1988 | new_plan_sp = QueueThreadPlanForStepSingleInstruction( |
| 1989 | step_over: false, abort_other_plans, stop_other_threads: run_mode, status&: error); |
| 1990 | } |
| 1991 | |
| 1992 | new_plan_sp->SetIsControllingPlan(true); |
| 1993 | new_plan_sp->SetOkayToDiscard(false); |
| 1994 | |
| 1995 | // Why do we need to set the current thread by ID here??? |
| 1996 | process->GetThreadList().SetSelectedThreadByID(tid: GetID()); |
| 1997 | error = process->Resume(); |
| 1998 | } else { |
| 1999 | error = Status::FromErrorString(str: "process not stopped" ); |
| 2000 | } |
| 2001 | return error; |
| 2002 | } |
| 2003 | |
| 2004 | Status Thread::StepOver(bool source_step, |
| 2005 | LazyBool step_out_avoids_code_without_debug_info) { |
| 2006 | Status error; |
| 2007 | Process *process = GetProcess().get(); |
| 2008 | if (StateIsStoppedState(state: process->GetState(), must_exist: true)) { |
| 2009 | StackFrameSP frame_sp = GetStackFrameAtIndex(idx: 0); |
| 2010 | ThreadPlanSP new_plan_sp; |
| 2011 | |
| 2012 | const lldb::RunMode run_mode = eOnlyThisThread; |
| 2013 | const bool abort_other_plans = false; |
| 2014 | |
| 2015 | if (source_step && frame_sp && frame_sp->HasDebugInformation()) { |
| 2016 | SymbolContext sc(frame_sp->GetSymbolContext(resolve_scope: eSymbolContextEverything)); |
| 2017 | new_plan_sp = QueueThreadPlanForStepOverRange( |
| 2018 | abort_other_plans, line_entry: sc.line_entry, addr_context: sc, stop_other_threads: run_mode, status&: error, |
| 2019 | step_out_avoids_code_withoug_debug_info: step_out_avoids_code_without_debug_info); |
| 2020 | } else { |
| 2021 | new_plan_sp = QueueThreadPlanForStepSingleInstruction( |
| 2022 | step_over: true, abort_other_plans, stop_other_threads: run_mode, status&: error); |
| 2023 | } |
| 2024 | |
| 2025 | new_plan_sp->SetIsControllingPlan(true); |
| 2026 | new_plan_sp->SetOkayToDiscard(false); |
| 2027 | |
| 2028 | // Why do we need to set the current thread by ID here??? |
| 2029 | process->GetThreadList().SetSelectedThreadByID(tid: GetID()); |
| 2030 | error = process->Resume(); |
| 2031 | } else { |
| 2032 | error = Status::FromErrorString(str: "process not stopped" ); |
| 2033 | } |
| 2034 | return error; |
| 2035 | } |
| 2036 | |
| 2037 | Status Thread::StepOut(uint32_t frame_idx) { |
| 2038 | Status error; |
| 2039 | Process *process = GetProcess().get(); |
| 2040 | if (StateIsStoppedState(state: process->GetState(), must_exist: true)) { |
| 2041 | const bool first_instruction = false; |
| 2042 | const bool stop_other_threads = false; |
| 2043 | const bool abort_other_plans = false; |
| 2044 | |
| 2045 | ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut( |
| 2046 | abort_other_plans, addr_context: nullptr, first_insn: first_instruction, stop_other_threads, |
| 2047 | report_stop_vote: eVoteYes, report_run_vote: eVoteNoOpinion, frame_idx, status&: error)); |
| 2048 | |
| 2049 | new_plan_sp->SetIsControllingPlan(true); |
| 2050 | new_plan_sp->SetOkayToDiscard(false); |
| 2051 | |
| 2052 | // Why do we need to set the current thread by ID here??? |
| 2053 | process->GetThreadList().SetSelectedThreadByID(tid: GetID()); |
| 2054 | error = process->Resume(); |
| 2055 | } else { |
| 2056 | error = Status::FromErrorString(str: "process not stopped" ); |
| 2057 | } |
| 2058 | return error; |
| 2059 | } |
| 2060 | |
| 2061 | ValueObjectSP Thread::GetCurrentException() { |
| 2062 | if (auto frame_sp = GetStackFrameAtIndex(idx: 0)) |
| 2063 | if (auto recognized_frame = frame_sp->GetRecognizedFrame()) |
| 2064 | if (auto e = recognized_frame->GetExceptionObject()) |
| 2065 | return e; |
| 2066 | |
| 2067 | // NOTE: Even though this behavior is generalized, only ObjC is actually |
| 2068 | // supported at the moment. |
| 2069 | for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) { |
| 2070 | if (auto e = runtime->GetExceptionObjectForThread(thread_sp: shared_from_this())) |
| 2071 | return e; |
| 2072 | } |
| 2073 | |
| 2074 | return ValueObjectSP(); |
| 2075 | } |
| 2076 | |
| 2077 | ThreadSP Thread::GetCurrentExceptionBacktrace() { |
| 2078 | ValueObjectSP exception = GetCurrentException(); |
| 2079 | if (!exception) |
| 2080 | return ThreadSP(); |
| 2081 | |
| 2082 | // NOTE: Even though this behavior is generalized, only ObjC is actually |
| 2083 | // supported at the moment. |
| 2084 | for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) { |
| 2085 | if (auto bt = runtime->GetBacktraceThreadFromException(thread_sp: exception)) |
| 2086 | return bt; |
| 2087 | } |
| 2088 | |
| 2089 | return ThreadSP(); |
| 2090 | } |
| 2091 | |
| 2092 | lldb::ValueObjectSP Thread::GetSiginfoValue() { |
| 2093 | ProcessSP process_sp = GetProcess(); |
| 2094 | assert(process_sp); |
| 2095 | Target &target = process_sp->GetTarget(); |
| 2096 | PlatformSP platform_sp = target.GetPlatform(); |
| 2097 | assert(platform_sp); |
| 2098 | ArchSpec arch = target.GetArchitecture(); |
| 2099 | |
| 2100 | CompilerType type = platform_sp->GetSiginfoType(triple: arch.GetTriple()); |
| 2101 | if (!type.IsValid()) |
| 2102 | return ValueObjectConstResult::Create( |
| 2103 | exe_scope: &target, error: Status::FromErrorString(str: "no siginfo_t for the platform" )); |
| 2104 | |
| 2105 | auto type_size_or_err = type.GetByteSize(exe_scope: nullptr); |
| 2106 | if (!type_size_or_err) |
| 2107 | return ValueObjectConstResult::Create( |
| 2108 | exe_scope: &target, error: Status::FromError(error: type_size_or_err.takeError())); |
| 2109 | |
| 2110 | llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = |
| 2111 | GetSiginfo(max_size: *type_size_or_err); |
| 2112 | if (!data) |
| 2113 | return ValueObjectConstResult::Create(exe_scope: &target, |
| 2114 | error: Status::FromError(error: data.takeError())); |
| 2115 | |
| 2116 | DataExtractor {data.get()->getBufferStart(), data.get()->getBufferSize(), |
| 2117 | process_sp->GetByteOrder(), arch.GetAddressByteSize()}; |
| 2118 | return ValueObjectConstResult::Create(exe_scope: &target, compiler_type: type, name: ConstString("__lldb_siginfo" ), data: data_extractor); |
| 2119 | } |
| 2120 | |