xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- CPPLanguageRuntime.cpp---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
9fe6060f1SDimitry Andric #include <cstring>
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include <memory>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "CPPLanguageRuntime.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
190b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
220b57cec5SDimitry Andric #include "lldb/Core/UniqueCStringMap.h"
23480093f4SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
240b57cec5SDimitry Andric #include "lldb/Target/ABI.h"
250b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
260b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
270b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
280b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
290b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
300b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
31480093f4SDimitry Andric #include "lldb/Utility/Timer.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace lldb;
340b57cec5SDimitry Andric using namespace lldb_private;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric static ConstString g_this = ConstString("this");
375f757f3fSDimitry Andric // Artificial coroutine-related variables emitted by clang.
385f757f3fSDimitry Andric static ConstString g_promise = ConstString("__promise");
395f757f3fSDimitry Andric static ConstString g_coro_frame = ConstString("__coro_frame");
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric char CPPLanguageRuntime::ID = 0;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
440b57cec5SDimitry Andric     : LanguageRuntime(process) {}
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
475f757f3fSDimitry Andric   return name == g_this || name == g_promise || name == g_coro_frame;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
50*0fca6ea1SDimitry Andric llvm::Error CPPLanguageRuntime::GetObjectDescription(Stream &str,
510b57cec5SDimitry Andric                                                      ValueObject &object) {
520b57cec5SDimitry Andric   // C++ has no generic way to do this.
53*0fca6ea1SDimitry Andric   return llvm::createStringError("C++ does not support object descriptions");
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
56*0fca6ea1SDimitry Andric llvm::Error
57*0fca6ea1SDimitry Andric CPPLanguageRuntime::GetObjectDescription(Stream &str, Value &value,
58*0fca6ea1SDimitry Andric                                          ExecutionContextScope *exe_scope) {
590b57cec5SDimitry Andric   // C++ has no generic way to do this.
60*0fca6ea1SDimitry Andric   return llvm::createStringError("C++ does not support object descriptions");
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
63480093f4SDimitry Andric bool contains_lambda_identifier(llvm::StringRef &str_ref) {
64480093f4SDimitry Andric   return str_ref.contains("$_") || str_ref.contains("'lambda'");
65480093f4SDimitry Andric }
66480093f4SDimitry Andric 
67480093f4SDimitry Andric CPPLanguageRuntime::LibCppStdFunctionCallableInfo
68480093f4SDimitry Andric line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol,
69480093f4SDimitry Andric                   llvm::StringRef first_template_param_sref,
7081ad6265SDimitry Andric                   bool has_invoke) {
71480093f4SDimitry Andric 
72480093f4SDimitry Andric   CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info;
73480093f4SDimitry Andric 
74480093f4SDimitry Andric   AddressRange range;
75480093f4SDimitry Andric   sc.GetAddressRange(eSymbolContextEverything, 0, false, range);
76480093f4SDimitry Andric 
77480093f4SDimitry Andric   Address address = range.GetBaseAddress();
78480093f4SDimitry Andric 
79480093f4SDimitry Andric   Address addr;
80480093f4SDimitry Andric   if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
81480093f4SDimitry Andric                                 addr)) {
82480093f4SDimitry Andric     LineEntry line_entry;
83480093f4SDimitry Andric     addr.CalculateSymbolContextLineEntry(line_entry);
84480093f4SDimitry Andric 
8581ad6265SDimitry Andric     if (contains_lambda_identifier(first_template_param_sref) || has_invoke) {
86480093f4SDimitry Andric       // Case 1 and 2
87480093f4SDimitry Andric       optional_info.callable_case = lldb_private::CPPLanguageRuntime::
88480093f4SDimitry Andric           LibCppStdFunctionCallableCase::Lambda;
89480093f4SDimitry Andric     } else {
90480093f4SDimitry Andric       // Case 3
91480093f4SDimitry Andric       optional_info.callable_case = lldb_private::CPPLanguageRuntime::
92480093f4SDimitry Andric           LibCppStdFunctionCallableCase::CallableObject;
93480093f4SDimitry Andric     }
94480093f4SDimitry Andric 
95480093f4SDimitry Andric     optional_info.callable_symbol = *symbol;
96480093f4SDimitry Andric     optional_info.callable_line_entry = line_entry;
97480093f4SDimitry Andric     optional_info.callable_address = addr;
98480093f4SDimitry Andric   }
99480093f4SDimitry Andric 
100480093f4SDimitry Andric   return optional_info;
101480093f4SDimitry Andric }
102480093f4SDimitry Andric 
1030b57cec5SDimitry Andric CPPLanguageRuntime::LibCppStdFunctionCallableInfo
1040b57cec5SDimitry Andric CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
1050b57cec5SDimitry Andric     lldb::ValueObjectSP &valobj_sp) {
106e8d8bef9SDimitry Andric   LLDB_SCOPED_TIMER();
107480093f4SDimitry Andric 
1080b57cec5SDimitry Andric   LibCppStdFunctionCallableInfo optional_info;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   if (!valobj_sp)
1110b57cec5SDimitry Andric     return optional_info;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   // Member __f_ has type __base*, the contents of which will hold:
1140b57cec5SDimitry Andric   // 1) a vtable entry which may hold type information needed to discover the
1150b57cec5SDimitry Andric   //    lambda being called
1160b57cec5SDimitry Andric   // 2) possibly hold a pointer to the callable object
1170b57cec5SDimitry Andric   // e.g.
1180b57cec5SDimitry Andric   //
1190b57cec5SDimitry Andric   // (lldb) frame var -R  f_display
1200b57cec5SDimitry Andric   // (std::__1::function<void (int)>) f_display = {
1210b57cec5SDimitry Andric   //  __buf_ = {
1220b57cec5SDimitry Andric   //  …
1230b57cec5SDimitry Andric   // }
1240b57cec5SDimitry Andric   //  __f_ = 0x00007ffeefbffa00
1250b57cec5SDimitry Andric   // }
1260b57cec5SDimitry Andric   // (lldb) memory read -fA 0x00007ffeefbffa00
1270b57cec5SDimitry Andric   // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
1280b57cec5SDimitry Andric   // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
1290b57cec5SDimitry Andric   //
1300b57cec5SDimitry Andric   // We will be handling five cases below, std::function is wrapping:
1310b57cec5SDimitry Andric   //
1320b57cec5SDimitry Andric   // 1) a lambda we know at compile time. We will obtain the name of the lambda
1330b57cec5SDimitry Andric   //    from the first template pameter from __func's vtable. We will look up
1340b57cec5SDimitry Andric   //    the lambda's operator()() and obtain the line table entry.
1350b57cec5SDimitry Andric   // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
1360b57cec5SDimitry Andric   //    will be stored after the vtable. We will obtain the lambdas name from
1370b57cec5SDimitry Andric   //    this entry and lookup operator()() and obtain the line table entry.
1380b57cec5SDimitry Andric   // 3) a callable object via operator()(). We will obtain the name of the
1390b57cec5SDimitry Andric   //    object from the first template parameter from __func's vtable. We will
140480093f4SDimitry Andric   //    look up the objects operator()() and obtain the line table entry.
1410b57cec5SDimitry Andric   // 4) a member function. A pointer to the function will stored after the
1420b57cec5SDimitry Andric   //    we will obtain the name from this pointer.
1430b57cec5SDimitry Andric   // 5) a free function. A pointer to the function will stored after the vtable
1440b57cec5SDimitry Andric   //    we will obtain the name from this pointer.
14506c3fb27SDimitry Andric   ValueObjectSP member_f_(valobj_sp->GetChildMemberWithName("__f_"));
1460b57cec5SDimitry Andric 
14781ad6265SDimitry Andric   if (member_f_) {
14806c3fb27SDimitry Andric     ValueObjectSP sub_member_f_(member_f_->GetChildMemberWithName("__f_"));
1490b57cec5SDimitry Andric 
15081ad6265SDimitry Andric     if (sub_member_f_)
15181ad6265SDimitry Andric         member_f_ = sub_member_f_;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric 
15481ad6265SDimitry Andric   if (!member_f_)
155e8d8bef9SDimitry Andric     return optional_info;
156e8d8bef9SDimitry Andric 
15781ad6265SDimitry Andric   lldb::addr_t member_f_pointer_value = member_f_->GetValueAsUnsigned(0);
1580b57cec5SDimitry Andric 
15981ad6265SDimitry Andric   optional_info.member_f_pointer_value = member_f_pointer_value;
1600b57cec5SDimitry Andric 
16181ad6265SDimitry Andric   if (!member_f_pointer_value)
162480093f4SDimitry Andric     return optional_info;
163480093f4SDimitry Andric 
1640b57cec5SDimitry Andric   ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
1650b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   if (process == nullptr)
1680b57cec5SDimitry Andric     return optional_info;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   uint32_t address_size = process->GetAddressByteSize();
1710b57cec5SDimitry Andric   Status status;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   // First item pointed to by __f_ should be the pointer to the vtable for
1740b57cec5SDimitry Andric   // a __base object.
1750b57cec5SDimitry Andric   lldb::addr_t vtable_address =
17681ad6265SDimitry Andric       process->ReadPointerFromMemory(member_f_pointer_value, status);
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   if (status.Fail())
1790b57cec5SDimitry Andric     return optional_info;
1800b57cec5SDimitry Andric 
181480093f4SDimitry Andric   lldb::addr_t vtable_address_first_entry =
182480093f4SDimitry Andric       process->ReadPointerFromMemory(vtable_address + address_size, status);
183480093f4SDimitry Andric 
184480093f4SDimitry Andric   if (status.Fail())
185480093f4SDimitry Andric     return optional_info;
186480093f4SDimitry Andric 
18781ad6265SDimitry Andric   lldb::addr_t address_after_vtable = member_f_pointer_value + address_size;
188480093f4SDimitry Andric   // As commented above we may not have a function pointer but if we do we will
1890b57cec5SDimitry Andric   // need it.
1900b57cec5SDimitry Andric   lldb::addr_t possible_function_address =
1910b57cec5SDimitry Andric       process->ReadPointerFromMemory(address_after_vtable, status);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   if (status.Fail())
1940b57cec5SDimitry Andric     return optional_info;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   Target &target = process->GetTarget();
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   if (target.GetSectionLoadList().IsEmpty())
1990b57cec5SDimitry Andric     return optional_info;
2000b57cec5SDimitry Andric 
201480093f4SDimitry Andric   Address vtable_first_entry_resolved;
202480093f4SDimitry Andric 
203480093f4SDimitry Andric   if (!target.GetSectionLoadList().ResolveLoadAddress(
204480093f4SDimitry Andric           vtable_address_first_entry, vtable_first_entry_resolved))
205480093f4SDimitry Andric     return optional_info;
206480093f4SDimitry Andric 
2070b57cec5SDimitry Andric   Address vtable_addr_resolved;
2080b57cec5SDimitry Andric   SymbolContext sc;
209480093f4SDimitry Andric   Symbol *symbol = nullptr;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
2120b57cec5SDimitry Andric                                                       vtable_addr_resolved))
2130b57cec5SDimitry Andric     return optional_info;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   target.GetImages().ResolveSymbolContextForAddress(
2160b57cec5SDimitry Andric       vtable_addr_resolved, eSymbolContextEverything, sc);
2170b57cec5SDimitry Andric   symbol = sc.symbol;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   if (symbol == nullptr)
2200b57cec5SDimitry Andric     return optional_info;
2210b57cec5SDimitry Andric 
222480093f4SDimitry Andric   llvm::StringRef vtable_name(symbol->GetName().GetStringRef());
2230b57cec5SDimitry Andric   bool found_expected_start_string =
2245f757f3fSDimitry Andric       vtable_name.starts_with("vtable for std::__1::__function::__func<");
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   if (!found_expected_start_string)
2270b57cec5SDimitry Andric     return optional_info;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   // Given case 1 or 3 we have a vtable name, we are want to extract the first
2300b57cec5SDimitry Andric   // template parameter
2310b57cec5SDimitry Andric   //
2320b57cec5SDimitry Andric   //  ... __func<main::$_0, std::__1::allocator<main::$_0> ...
2330b57cec5SDimitry Andric   //             ^^^^^^^^^
2340b57cec5SDimitry Andric   //
235480093f4SDimitry Andric   // We could see names such as:
236480093f4SDimitry Andric   //    main::$_0
237480093f4SDimitry Andric   //    Bar::add_num2(int)::'lambda'(int)
238480093f4SDimitry Andric   //    Bar
239480093f4SDimitry Andric   //
2400b57cec5SDimitry Andric   // We do this by find the first < and , and extracting in between.
2410b57cec5SDimitry Andric   //
2420b57cec5SDimitry Andric   // This covers the case of the lambda known at compile time.
2430b57cec5SDimitry Andric   size_t first_open_angle_bracket = vtable_name.find('<') + 1;
2440b57cec5SDimitry Andric   size_t first_comma = vtable_name.find(',');
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   llvm::StringRef first_template_parameter =
2470b57cec5SDimitry Andric       vtable_name.slice(first_open_angle_bracket, first_comma);
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   Address function_address_resolved;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   // Setup for cases 2, 4 and 5 we have a pointer to a function after the
2520b57cec5SDimitry Andric   // vtable. We will use a process of elimination to drop through each case
2530b57cec5SDimitry Andric   // and obtain the data we need.
2540b57cec5SDimitry Andric   if (target.GetSectionLoadList().ResolveLoadAddress(
2550b57cec5SDimitry Andric           possible_function_address, function_address_resolved)) {
2560b57cec5SDimitry Andric     target.GetImages().ResolveSymbolContextForAddress(
2570b57cec5SDimitry Andric         function_address_resolved, eSymbolContextEverything, sc);
2580b57cec5SDimitry Andric     symbol = sc.symbol;
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
261480093f4SDimitry Andric   // These conditions are used several times to simplify statements later on.
26281ad6265SDimitry Andric   bool has_invoke =
263480093f4SDimitry Andric       (symbol ? symbol->GetName().GetStringRef().contains("__invoke") : false);
264480093f4SDimitry Andric   auto calculate_symbol_context_helper = [](auto &t,
265480093f4SDimitry Andric                                             SymbolContextList &sc_list) {
266480093f4SDimitry Andric     SymbolContext sc;
267480093f4SDimitry Andric     t->CalculateSymbolContext(&sc);
268480093f4SDimitry Andric     sc_list.Append(sc);
2690b57cec5SDimitry Andric   };
2700b57cec5SDimitry Andric 
271480093f4SDimitry Andric   // Case 2
27281ad6265SDimitry Andric   if (has_invoke) {
2730b57cec5SDimitry Andric     SymbolContextList scl;
274480093f4SDimitry Andric     calculate_symbol_context_helper(symbol, scl);
2750b57cec5SDimitry Andric 
276480093f4SDimitry Andric     return line_entry_helper(target, scl[0], symbol, first_template_parameter,
27781ad6265SDimitry Andric                              has_invoke);
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   // Case 4 or 5
2815f757f3fSDimitry Andric   if (symbol && !symbol->GetName().GetStringRef().starts_with("vtable for") &&
28281ad6265SDimitry Andric       !contains_lambda_identifier(first_template_parameter) && !has_invoke) {
2830b57cec5SDimitry Andric     optional_info.callable_case =
2840b57cec5SDimitry Andric         LibCppStdFunctionCallableCase::FreeOrMemberFunction;
2850b57cec5SDimitry Andric     optional_info.callable_address = function_address_resolved;
2860b57cec5SDimitry Andric     optional_info.callable_symbol = *symbol;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric     return optional_info;
2890b57cec5SDimitry Andric   }
2900b57cec5SDimitry Andric 
291480093f4SDimitry Andric   std::string func_to_match = first_template_parameter.str();
292480093f4SDimitry Andric 
293480093f4SDimitry Andric   auto it = CallableLookupCache.find(func_to_match);
294480093f4SDimitry Andric   if (it != CallableLookupCache.end())
295480093f4SDimitry Andric     return it->second;
296480093f4SDimitry Andric 
297480093f4SDimitry Andric   SymbolContextList scl;
298480093f4SDimitry Andric 
299480093f4SDimitry Andric   CompileUnit *vtable_cu =
300480093f4SDimitry Andric       vtable_first_entry_resolved.CalculateSymbolContextCompileUnit();
301480093f4SDimitry Andric   llvm::StringRef name_to_use = func_to_match;
302480093f4SDimitry Andric 
303480093f4SDimitry Andric   // Case 3, we have a callable object instead of a lambda
304480093f4SDimitry Andric   //
305480093f4SDimitry Andric   // TODO
306480093f4SDimitry Andric   // We currently don't support this case a callable object may have multiple
307480093f4SDimitry Andric   // operator()() varying on const/non-const and number of arguments and we
308480093f4SDimitry Andric   // don't have a way to currently distinguish them so we will bail out now.
309480093f4SDimitry Andric   if (!contains_lambda_identifier(name_to_use))
310480093f4SDimitry Andric     return optional_info;
311480093f4SDimitry Andric 
31281ad6265SDimitry Andric   if (vtable_cu && !has_invoke) {
313480093f4SDimitry Andric     lldb::FunctionSP func_sp =
314480093f4SDimitry Andric         vtable_cu->FindFunction([name_to_use](const FunctionSP &f) {
315480093f4SDimitry Andric           auto name = f->GetName().GetStringRef();
3165f757f3fSDimitry Andric           if (name.starts_with(name_to_use) && name.contains("operator"))
317480093f4SDimitry Andric             return true;
318480093f4SDimitry Andric 
319480093f4SDimitry Andric           return false;
320480093f4SDimitry Andric         });
321480093f4SDimitry Andric 
322480093f4SDimitry Andric     if (func_sp) {
323480093f4SDimitry Andric       calculate_symbol_context_helper(func_sp, scl);
324480093f4SDimitry Andric     }
325480093f4SDimitry Andric   }
326480093f4SDimitry Andric 
327fe6060f1SDimitry Andric   if (symbol == nullptr)
328fe6060f1SDimitry Andric     return optional_info;
329fe6060f1SDimitry Andric 
330480093f4SDimitry Andric   // Case 1 or 3
331480093f4SDimitry Andric   if (scl.GetSize() >= 1) {
332480093f4SDimitry Andric     optional_info = line_entry_helper(target, scl[0], symbol,
33381ad6265SDimitry Andric                                       first_template_parameter, has_invoke);
334480093f4SDimitry Andric   }
335480093f4SDimitry Andric 
336480093f4SDimitry Andric   CallableLookupCache[func_to_match] = optional_info;
337480093f4SDimitry Andric 
3380b57cec5SDimitry Andric   return optional_info;
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric lldb::ThreadPlanSP
3420b57cec5SDimitry Andric CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
3430b57cec5SDimitry Andric                                                  bool stop_others) {
3440b57cec5SDimitry Andric   ThreadPlanSP ret_plan_sp;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   TargetSP target_sp(thread.CalculateTarget());
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   if (target_sp->GetSectionLoadList().IsEmpty())
3510b57cec5SDimitry Andric     return ret_plan_sp;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   Address pc_addr_resolved;
3540b57cec5SDimitry Andric   SymbolContext sc;
3550b57cec5SDimitry Andric   Symbol *symbol;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
3580b57cec5SDimitry Andric                                                           pc_addr_resolved))
3590b57cec5SDimitry Andric     return ret_plan_sp;
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   target_sp->GetImages().ResolveSymbolContextForAddress(
3620b57cec5SDimitry Andric       pc_addr_resolved, eSymbolContextEverything, sc);
3630b57cec5SDimitry Andric   symbol = sc.symbol;
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   if (symbol == nullptr)
3660b57cec5SDimitry Andric     return ret_plan_sp;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   llvm::StringRef function_name(symbol->GetName().GetCString());
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   // Handling the case where we are attempting to step into std::function.
3710b57cec5SDimitry Andric   // The behavior will be that we will attempt to obtain the wrapped
3720b57cec5SDimitry Andric   // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
3730b57cec5SDimitry Andric   // will return a ThreadPlanRunToAddress to the callable. Therefore we will
3740b57cec5SDimitry Andric   // step into the wrapped callable.
3750b57cec5SDimitry Andric   //
3760b57cec5SDimitry Andric   bool found_expected_start_string =
3775f757f3fSDimitry Andric       function_name.starts_with("std::__1::function<");
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   if (!found_expected_start_string)
3800b57cec5SDimitry Andric     return ret_plan_sp;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   AddressRange range_of_curr_func;
3830b57cec5SDimitry Andric   sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   StackFrameSP frame = thread.GetStackFrameAtIndex(0);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   if (frame) {
3880b57cec5SDimitry Andric     ValueObjectSP value_sp = frame->FindVariable(g_this);
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric     CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
3910b57cec5SDimitry Andric         FindLibCppStdFunctionCallableInfo(value_sp);
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric     if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
3940b57cec5SDimitry Andric         value_sp->GetValueIsValid()) {
3950b57cec5SDimitry Andric       // We found the std::function wrapped callable and we have its address.
3960b57cec5SDimitry Andric       // We now create a ThreadPlan to run to the callable.
3970b57cec5SDimitry Andric       ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
3980b57cec5SDimitry Andric           thread, callable_info.callable_address, stop_others);
3990b57cec5SDimitry Andric       return ret_plan_sp;
4000b57cec5SDimitry Andric     } else {
4010b57cec5SDimitry Andric       // We are in std::function but we could not obtain the callable.
4020b57cec5SDimitry Andric       // We create a ThreadPlan to keep stepping through using the address range
4030b57cec5SDimitry Andric       // of the current function.
4040b57cec5SDimitry Andric       ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
405fe6060f1SDimitry Andric           thread, range_of_curr_func, sc, nullptr, eOnlyThisThread,
406fe6060f1SDimitry Andric           eLazyBoolYes, eLazyBoolYes);
4070b57cec5SDimitry Andric       return ret_plan_sp;
4080b57cec5SDimitry Andric     }
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   return ret_plan_sp;
4120b57cec5SDimitry Andric }
413