ThreadPlanCallFunction.cpp revision 360784
1//===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
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/ThreadPlanCallFunction.h"
10#include "lldb/Breakpoint/Breakpoint.h"
11#include "lldb/Breakpoint/BreakpointLocation.h"
12#include "lldb/Core/Address.h"
13#include "lldb/Core/DumpRegisterValue.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Symbol/ObjectFile.h"
16#include "lldb/Target/ABI.h"
17#include "lldb/Target/LanguageRuntime.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/StopInfo.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Target/ThreadPlanRunToAddress.h"
24#include "lldb/Utility/Log.h"
25#include "lldb/Utility/Stream.h"
26
27#include <memory>
28
29using namespace lldb;
30using namespace lldb_private;
31
32// ThreadPlanCallFunction: Plan to call a single function
33bool ThreadPlanCallFunction::ConstructorSetup(
34    Thread &thread, ABI *&abi, lldb::addr_t &start_load_addr,
35    lldb::addr_t &function_load_addr) {
36  SetIsMasterPlan(true);
37  SetOkayToDiscard(false);
38  SetPrivate(true);
39
40  ProcessSP process_sp(thread.GetProcess());
41  if (!process_sp)
42    return false;
43
44  abi = process_sp->GetABI().get();
45
46  if (!abi)
47    return false;
48
49  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP));
50
51  SetBreakpoints();
52
53  m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
54  // If we can't read memory at the point of the process where we are planning
55  // to put our function, we're not going to get any further...
56  Status error;
57  process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
58  if (!error.Success()) {
59    m_constructor_errors.Printf(
60        "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".",
61        m_function_sp);
62    LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
63              m_constructor_errors.GetData());
64    return false;
65  }
66
67  llvm::Expected<Address> start_address = GetTarget().GetEntryPointAddress();
68  if (!start_address) {
69    m_constructor_errors.Printf(
70        "%s", llvm::toString(start_address.takeError()).c_str());
71    LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
72              m_constructor_errors.GetData());
73    return false;
74  }
75
76  m_start_addr = *start_address;
77  start_load_addr = m_start_addr.GetLoadAddress(&GetTarget());
78
79  // Checkpoint the thread state so we can restore it later.
80  if (log && log->GetVerbose())
81    ReportRegisterState("About to checkpoint thread before function call.  "
82                        "Original register state was:");
83
84  if (!thread.CheckpointThreadState(m_stored_thread_state)) {
85    m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to "
86                                "checkpoint thread state.");
87    LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
88              m_constructor_errors.GetData());
89    return false;
90  }
91  function_load_addr = m_function_addr.GetLoadAddress(&GetTarget());
92
93  return true;
94}
95
96ThreadPlanCallFunction::ThreadPlanCallFunction(
97    Thread &thread, const Address &function, const CompilerType &return_type,
98    llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options)
99    : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,
100                 eVoteNoOpinion, eVoteNoOpinion),
101      m_valid(false), m_stop_other_threads(options.GetStopOthers()),
102      m_unwind_on_error(options.DoesUnwindOnError()),
103      m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),
104      m_debug_execution(options.GetDebug()),
105      m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),
106      m_function_sp(0), m_takedown_done(false),
107      m_should_clear_objc_exception_bp(false),
108      m_should_clear_cxx_exception_bp(false),
109      m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) {
110  lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
111  lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
112  ABI *abi = nullptr;
113
114  if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
115    return;
116
117  if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr,
118                               start_load_addr, args))
119    return;
120
121  ReportRegisterState("Function call was set up.  Register state was:");
122
123  m_valid = true;
124}
125
126ThreadPlanCallFunction::ThreadPlanCallFunction(
127    Thread &thread, const Address &function,
128    const EvaluateExpressionOptions &options)
129    : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,
130                 eVoteNoOpinion, eVoteNoOpinion),
131      m_valid(false), m_stop_other_threads(options.GetStopOthers()),
132      m_unwind_on_error(options.DoesUnwindOnError()),
133      m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),
134      m_debug_execution(options.GetDebug()),
135      m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),
136      m_function_sp(0), m_takedown_done(false),
137      m_should_clear_objc_exception_bp(false),
138      m_should_clear_cxx_exception_bp(false),
139      m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {}
140
141ThreadPlanCallFunction::~ThreadPlanCallFunction() {
142  DoTakedown(PlanSucceeded());
143}
144
145void ThreadPlanCallFunction::ReportRegisterState(const char *message) {
146  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
147  if (log && log->GetVerbose()) {
148    StreamString strm;
149    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
150
151    log->PutCString(message);
152
153    RegisterValue reg_value;
154
155    for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
156         reg_idx < num_registers; ++reg_idx) {
157      const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
158      if (reg_ctx->ReadRegister(reg_info, reg_value)) {
159        DumpRegisterValue(reg_value, &strm, reg_info, true, false,
160                          eFormatDefault);
161        strm.EOL();
162      }
163    }
164    log->PutString(strm.GetString());
165  }
166}
167
168void ThreadPlanCallFunction::DoTakedown(bool success) {
169  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP));
170
171  if (!m_valid) {
172    // Don't call DoTakedown if we were never valid to begin with.
173    LLDB_LOGF(log,
174              "ThreadPlanCallFunction(%p): Log called on "
175              "ThreadPlanCallFunction that was never valid.",
176              static_cast<void *>(this));
177    return;
178  }
179
180  if (!m_takedown_done) {
181    if (success) {
182      SetReturnValue();
183    }
184    LLDB_LOGF(log,
185              "ThreadPlanCallFunction(%p): DoTakedown called for thread "
186              "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
187              static_cast<void *>(this), m_thread.GetID(), m_valid,
188              IsPlanComplete());
189    m_takedown_done = true;
190    m_stop_address =
191        m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
192    m_real_stop_info_sp = GetPrivateStopInfo();
193    if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) {
194      LLDB_LOGF(log,
195                "ThreadPlanCallFunction(%p): DoTakedown failed to restore "
196                "register state",
197                static_cast<void *>(this));
198    }
199    SetPlanComplete(success);
200    ClearBreakpoints();
201    if (log && log->GetVerbose())
202      ReportRegisterState("Restoring thread state after function call.  "
203                          "Restored register state:");
204  } else {
205    LLDB_LOGF(log,
206              "ThreadPlanCallFunction(%p): DoTakedown called as no-op for "
207              "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
208              static_cast<void *>(this), m_thread.GetID(), m_valid,
209              IsPlanComplete());
210  }
211}
212
213void ThreadPlanCallFunction::WillPop() { DoTakedown(PlanSucceeded()); }
214
215void ThreadPlanCallFunction::GetDescription(Stream *s, DescriptionLevel level) {
216  if (level == eDescriptionLevelBrief) {
217    s->Printf("Function call thread plan");
218  } else {
219    TargetSP target_sp(m_thread.CalculateTarget());
220    s->Printf("Thread plan to call 0x%" PRIx64,
221              m_function_addr.GetLoadAddress(target_sp.get()));
222  }
223}
224
225bool ThreadPlanCallFunction::ValidatePlan(Stream *error) {
226  if (!m_valid) {
227    if (error) {
228      if (m_constructor_errors.GetSize() > 0)
229        error->PutCString(m_constructor_errors.GetString());
230      else
231        error->PutCString("Unknown error");
232    }
233    return false;
234  }
235
236  return true;
237}
238
239Vote ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) {
240  if (m_takedown_done || IsPlanComplete())
241    return eVoteYes;
242  else
243    return ThreadPlan::ShouldReportStop(event_ptr);
244}
245
246bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
247  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP |
248                                                  LIBLLDB_LOG_PROCESS));
249  m_real_stop_info_sp = GetPrivateStopInfo();
250
251  // If our subplan knows why we stopped, even if it's done (which would
252  // forward the question to us) we answer yes.
253  if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) {
254    SetPlanComplete();
255    return true;
256  }
257
258  // Check if the breakpoint is one of ours.
259
260  StopReason stop_reason;
261  if (!m_real_stop_info_sp)
262    stop_reason = eStopReasonNone;
263  else
264    stop_reason = m_real_stop_info_sp->GetStopReason();
265  LLDB_LOGF(log,
266            "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.",
267            Thread::StopReasonAsCString(stop_reason));
268
269  if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
270    return true;
271
272  // One more quirk here.  If this event was from Halt interrupting the target,
273  // then we should not consider ourselves complete.  Return true to
274  // acknowledge the stop.
275  if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
276    LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: The event is an "
277                   "Interrupt, returning true.");
278    return true;
279  }
280  // We control breakpoints separately from other "stop reasons."  So first,
281  // check the case where we stopped for an internal breakpoint, in that case,
282  // continue on. If it is not an internal breakpoint, consult
283  // m_ignore_breakpoints.
284
285  if (stop_reason == eStopReasonBreakpoint) {
286    ProcessSP process_sp(m_thread.CalculateProcess());
287    uint64_t break_site_id = m_real_stop_info_sp->GetValue();
288    BreakpointSiteSP bp_site_sp;
289    if (process_sp)
290      bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id);
291    if (bp_site_sp) {
292      uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
293      bool is_internal = true;
294      for (uint32_t i = 0; i < num_owners; i++) {
295        Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
296        LLDB_LOGF(log,
297                  "ThreadPlanCallFunction::PlanExplainsStop: hit "
298                  "breakpoint %d while calling function",
299                  bp.GetID());
300
301        if (!bp.IsInternal()) {
302          is_internal = false;
303          break;
304        }
305      }
306      if (is_internal) {
307        LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop hit an "
308                       "internal breakpoint, not stopping.");
309        return false;
310      }
311    }
312
313    if (m_ignore_breakpoints) {
314      LLDB_LOGF(log,
315                "ThreadPlanCallFunction::PlanExplainsStop: we are ignoring "
316                "breakpoints, overriding breakpoint stop info ShouldStop, "
317                "returning true");
318      m_real_stop_info_sp->OverrideShouldStop(false);
319      return true;
320    } else {
321      LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: we are not "
322                     "ignoring breakpoints, overriding breakpoint stop info "
323                     "ShouldStop, returning true");
324      m_real_stop_info_sp->OverrideShouldStop(true);
325      return false;
326    }
327  } else if (!m_unwind_on_error) {
328    // If we don't want to discard this plan, than any stop we don't understand
329    // should be propagated up the stack.
330    return false;
331  } else {
332    // If the subplan is running, any crashes are attributable to us. If we
333    // want to discard the plan, then we say we explain the stop but if we are
334    // going to be discarded, let whoever is above us explain the stop. But
335    // don't discard the plan if the stop would restart itself (for instance if
336    // it is a signal that is set not to stop.  Check that here first.  We just
337    // say we explain the stop but aren't done and everything will continue on
338    // from there.
339
340    if (m_real_stop_info_sp &&
341        m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) {
342      SetPlanComplete(false);
343      return m_subplan_sp ? m_unwind_on_error : false;
344    } else
345      return true;
346  }
347}
348
349bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) {
350  // We do some computation in DoPlanExplainsStop that may or may not set the
351  // plan as complete. We need to do that here to make sure our state is
352  // correct.
353  DoPlanExplainsStop(event_ptr);
354
355  if (IsPlanComplete()) {
356    ReportRegisterState("Function completed.  Register state was:");
357    return true;
358  } else {
359    return false;
360  }
361}
362
363bool ThreadPlanCallFunction::StopOthers() { return m_stop_other_threads; }
364
365StateType ThreadPlanCallFunction::GetPlanRunState() { return eStateRunning; }
366
367void ThreadPlanCallFunction::DidPush() {
368  //#define SINGLE_STEP_EXPRESSIONS
369
370  // Now set the thread state to "no reason" so we don't run with whatever
371  // signal was outstanding... Wait till the plan is pushed so we aren't
372  // changing the stop info till we're about to run.
373
374  GetThread().SetStopInfoToNothing();
375
376#ifndef SINGLE_STEP_EXPRESSIONS
377  m_subplan_sp = std::make_shared<ThreadPlanRunToAddress>(
378      m_thread, m_start_addr, m_stop_other_threads);
379
380  m_thread.QueueThreadPlan(m_subplan_sp, false);
381  m_subplan_sp->SetPrivate(true);
382#endif
383}
384
385bool ThreadPlanCallFunction::WillStop() { return true; }
386
387bool ThreadPlanCallFunction::MischiefManaged() {
388  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
389
390  if (IsPlanComplete()) {
391    LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.",
392              static_cast<void *>(this));
393
394    ThreadPlan::MischiefManaged();
395    return true;
396  } else {
397    return false;
398  }
399}
400
401void ThreadPlanCallFunction::SetBreakpoints() {
402  ProcessSP process_sp(m_thread.CalculateProcess());
403  if (m_trap_exceptions && process_sp) {
404    m_cxx_language_runtime =
405        process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
406    m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
407
408    if (m_cxx_language_runtime) {
409      m_should_clear_cxx_exception_bp =
410          !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
411      m_cxx_language_runtime->SetExceptionBreakpoints();
412    }
413    if (m_objc_language_runtime) {
414      m_should_clear_objc_exception_bp =
415          !m_objc_language_runtime->ExceptionBreakpointsAreSet();
416      m_objc_language_runtime->SetExceptionBreakpoints();
417    }
418  }
419}
420
421void ThreadPlanCallFunction::ClearBreakpoints() {
422  if (m_trap_exceptions) {
423    if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
424      m_cxx_language_runtime->ClearExceptionBreakpoints();
425    if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
426      m_objc_language_runtime->ClearExceptionBreakpoints();
427  }
428}
429
430bool ThreadPlanCallFunction::BreakpointsExplainStop() {
431  StopInfoSP stop_info_sp = GetPrivateStopInfo();
432
433  if (m_trap_exceptions) {
434    if ((m_cxx_language_runtime &&
435         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(
436             stop_info_sp)) ||
437        (m_objc_language_runtime &&
438         m_objc_language_runtime->ExceptionBreakpointsExplainStop(
439             stop_info_sp))) {
440      Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP));
441      LLDB_LOGF(log, "ThreadPlanCallFunction::BreakpointsExplainStop - Hit an "
442                     "exception breakpoint, setting plan complete.");
443
444      SetPlanComplete(false);
445
446      // If the user has set the ObjC language breakpoint, it would normally
447      // get priority over our internal catcher breakpoint, but in this case we
448      // can't let that happen, so force the ShouldStop here.
449      stop_info_sp->OverrideShouldStop(true);
450      return true;
451    }
452  }
453
454  return false;
455}
456
457void ThreadPlanCallFunction::SetStopOthers(bool new_value) {
458  m_subplan_sp->SetStopOthers(new_value);
459}
460
461bool ThreadPlanCallFunction::RestoreThreadState() {
462  return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
463}
464
465void ThreadPlanCallFunction::SetReturnValue() {
466  ProcessSP process_sp(m_thread.GetProcess());
467  const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
468  if (abi && m_return_type.IsValid()) {
469    const bool persistent = false;
470    m_return_valobj_sp =
471        abi->GetReturnValueObject(m_thread, m_return_type, persistent);
472  }
473}
474