diff options
author | Shafik Yaghmour <syaghmour@apple.com> | 2018-09-11 20:58:28 +0000 |
---|---|---|
committer | Shafik Yaghmour <syaghmour@apple.com> | 2018-09-11 20:58:28 +0000 |
commit | 443e20ba325b6f1c5ecf2cd2470fc3e72b887e9b (patch) | |
tree | 63a9ecc29785560afad7dfea69bc514ff32516d5 /lldb/source/Plugins/Language/CPlusPlus | |
parent | 48e5b8b1a45aafb0b275758c80d5381bd3ce3659 (diff) | |
download | bcm5719-llvm-443e20ba325b6f1c5ecf2cd2470fc3e72b887e9b.tar.gz bcm5719-llvm-443e20ba325b6f1c5ecf2cd2470fc3e72b887e9b.zip |
Refactoring std::function formatter to move core functionality into CPPLanguageRuntime
Patch by Shafik Yaghmour.
Differential Revision: https://reviews.llvm.org/D51896
llvm-svn: 341991
Diffstat (limited to 'lldb/source/Plugins/Language/CPlusPlus')
-rw-r--r-- | lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp | 223 |
1 files changed, 26 insertions, 197 deletions
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 16e1138f542..aa91e8f47c2 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -23,6 +23,7 @@ #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/DataFormatters/VectorIterator.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" @@ -65,216 +66,44 @@ bool lldb_private::formatters::LibcxxFunctionSummaryProvider( if (!valobj_sp) return false; - // Member __f_ has type __base*, the contents of which will hold: - // 1) a vtable entry which may hold type information needed to discover the - // lambda being called - // 2) possibly hold a pointer to the callable object - // e.g. - // - // (lldb) frame var -R f_display - // (std::__1::function<void (int)>) f_display = { - // __buf_ = { - // … - // } - // __f_ = 0x00007ffeefbffa00 - // } - // (lldb) memory read -fA 0x00007ffeefbffa00 - // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ... - // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ... - // - // We will be handling five cases below, std::function is wrapping: - // - // 1) a lambda we know at compile time. We will obtain the name of the lambda - // from the first template pameter from __func's vtable. We will look up - // the lambda's operator()() and obtain the line table entry. - // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method - // will be stored after the vtable. We will obtain the lambdas name from - // this entry and lookup operator()() and obtain the line table entry. - // 3) a callable object via operator()(). We will obtain the name of the - // object from the first template parameter from __func's vtable. We will - // look up the objectc operator()() and obtain the line table entry. - // 4) a member function. A pointer to the function will stored after the - // we will obtain the name from this pointer. - // 5) a free function. A pointer to the function will stored after the vtable - // we will obtain the name from this pointer. - ValueObjectSP member__f_( - valobj_sp->GetChildMemberWithName(ConstString("__f_"), true)); - lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0); - ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (process == nullptr) return false; - uint32_t address_size = process->GetAddressByteSize(); - Status status; - - // First item pointed to by __f_ should be the pointer to the vtable for - // a __base object. - lldb::addr_t vtable_address = - process->ReadPointerFromMemory(member__f_pointer_value, status); + CPPLanguageRuntime *cpp_runtime = process->GetCPPLanguageRuntime(); - if (status.Fail()) + if (!cpp_runtime) return false; - bool found_wrapped_function = false; - - // Using scoped exit so we can use early return and still execute the default - // action in case we don't find the wrapper function. Otherwise we can't use - // early exit without duplicating code. - auto default_print_on_exit = llvm::make_scope_exit( - [&found_wrapped_function, &stream, &member__f_pointer_value]() { - if (!found_wrapped_function) - stream.Printf(" __f_ = %" PRIu64, member__f_pointer_value); - }); + CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info = + cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp); - lldb::addr_t address_after_vtable = member__f_pointer_value + address_size; - // As commened above we may not have a function pointer but if we do we will - // need it. - lldb::addr_t possible_function_address = - process->ReadPointerFromMemory(address_after_vtable, status); - - if (status.Fail()) + switch (callable_info.callable_case) { + case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid: + stream.Printf(" __f_ = %" PRIu64, callable_info.member__f_pointer_value); return false; - - Target &target = process->GetTarget(); - - if (target.GetSectionLoadList().IsEmpty()) - return false; - - Address vtable_addr_resolved; - SymbolContext sc; - Symbol *symbol; - - if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address, - vtable_addr_resolved)) - return false; - - target.GetImages().ResolveSymbolContextForAddress( - vtable_addr_resolved, eSymbolContextEverything, sc); - symbol = sc.symbol; - - if (symbol == NULL) - return false; - - llvm::StringRef vtable_name(symbol->GetName().GetCString()); - bool found_expected_start_string = - vtable_name.startswith("vtable for std::__1::__function::__func<"); - - if (!found_expected_start_string) - return false; - - // Given case 1 or 3 we have a vtable name, we are want to extract the first - // template parameter - // - // ... __func<main::$_0, std::__1::allocator<main::$_0> ... - // ^^^^^^^^^ - // - // We do this by find the first < and , and extracting in between. - // - // This covers the case of the lambda known at compile time. - // - size_t first_open_angle_bracket = vtable_name.find('<') + 1; - size_t first_comma = vtable_name.find_first_of(','); - - llvm::StringRef first_template_parameter = - vtable_name.slice(first_open_angle_bracket, first_comma); - - Address function_address_resolved; - - // Setup for cases 2, 4 and 5 we have a pointer to a function after the - // vtable. We will use a process of elimination to drop through each case - // and obtain the data we need. - if (target.GetSectionLoadList().ResolveLoadAddress( - possible_function_address, function_address_resolved)) { - target.GetImages().ResolveSymbolContextForAddress( - function_address_resolved, eSymbolContextEverything, sc); - symbol = sc.symbol; - } - - auto get_name = [&first_template_parameter, &symbol]() { - // Given case 1: - // - // main::$_0 - // - // we want to append ::operator()() - if (first_template_parameter.contains("$_")) - return llvm::Regex::escape(first_template_parameter.str()) + - R"(::operator\(\)\(.*\))"; - - if (symbol != NULL && - symbol->GetName().GetStringRef().contains("__invoke")) { - - llvm::StringRef symbol_name = symbol->GetName().GetStringRef(); - size_t pos2 = symbol_name.find_last_of(':'); - - // Given case 2: - // - // main::$_1::__invoke(...) - // - // We want to slice off __invoke(...) and append operator()() - std::string lambda_operator = - llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) + - R"(operator\(\)\(.*\))"; - - return lambda_operator; - } - - // Case 3 - return first_template_parameter.str() + R"(::operator\(\)\(.*\))"; - ; - }; - - std::string func_to_match = get_name(); - - SymbolContextList scl; - - target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true, - true, scl); - - // Case 1,2 or 3 - if (scl.GetSize() >= 1) { - SymbolContext sc2 = scl[0]; - - AddressRange range; - sc2.GetAddressRange(eSymbolContextEverything, 0, false, range); - - Address address = range.GetBaseAddress(); - - Address addr; - if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target), - addr)) { - LineEntry line_entry; - addr.CalculateSymbolContextLineEntry(line_entry); - - found_wrapped_function = true; - if (first_template_parameter.contains("$_") || - (symbol != NULL && - symbol->GetName().GetStringRef().contains("__invoke"))) { - // Case 1 and 2 - stream.Printf(" Lambda in File %s at Line %u", - line_entry.file.GetFilename().GetCString(), - line_entry.line); - } else { - // Case 3 - stream.Printf(" Function in File %s at Line %u", - line_entry.file.GetFilename().GetCString(), - line_entry.line); - } - - return true; - } - } - - // Case 4 or 5 - if (!symbol->GetName().GetStringRef().startswith("vtable for")) { - found_wrapped_function = true; - stream.Printf(" Function = %s ", symbol->GetName().GetCString()); - return true; + break; + case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda: + stream.Printf( + " Lambda in File %s at Line %u", + callable_info.callable_line_entry.file.GetFilename().GetCString(), + callable_info.callable_line_entry.line); + break; + case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject: + stream.Printf( + " Function in File %s at Line %u", + callable_info.callable_line_entry.file.GetFilename().GetCString(), + callable_info.callable_line_entry.line); + break; + case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction: + stream.Printf(" Function = %s ", + callable_info.callable_symbol.GetName().GetCString()); + break; } - return false; + return true; } bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider( |