diff options
Diffstat (limited to 'source/Plugins/LanguageRuntime')
30 files changed, 1768 insertions, 416 deletions
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp new file mode 100644 index 0000000000000..b392282c3eb1a --- /dev/null +++ b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -0,0 +1,353 @@ +//===-- CPPLanguageRuntime.cpp +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <string.h> + +#include <memory> + +#include "CPPLanguageRuntime.h" + +#include "llvm/ADT/StringRef.h" + +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" +#include "lldb/Target/ThreadPlanStepInRange.h" + +using namespace lldb; +using namespace lldb_private; + +static ConstString g_this = ConstString("this"); + +char CPPLanguageRuntime::ID = 0; + +// Destructor +CPPLanguageRuntime::~CPPLanguageRuntime() {} + +CPPLanguageRuntime::CPPLanguageRuntime(Process *process) + : LanguageRuntime(process) {} + +bool CPPLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) { + return name == g_this; +} + +bool CPPLanguageRuntime::GetObjectDescription(Stream &str, + ValueObject &object) { + // C++ has no generic way to do this. + return false; +} + +bool CPPLanguageRuntime::GetObjectDescription( + Stream &str, Value &value, ExecutionContextScope *exe_scope) { + // C++ has no generic way to do this. + return false; +} + +CPPLanguageRuntime::LibCppStdFunctionCallableInfo +CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( + lldb::ValueObjectSP &valobj_sp) { + LibCppStdFunctionCallableInfo optional_info; + + if (!valobj_sp) + return optional_info; + + // 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)); + + if (member__f_) { + ValueObjectSP sub_member__f_( + member__f_->GetChildMemberWithName(ConstString("__f_"), true)); + + if (sub_member__f_) + member__f_ = sub_member__f_; + } + + lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0); + + optional_info.member__f_pointer_value = member__f_pointer_value; + + ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + + if (process == nullptr) + return optional_info; + + 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); + + if (status.Fail()) + return optional_info; + + 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()) + return optional_info; + + Target &target = process->GetTarget(); + + if (target.GetSectionLoadList().IsEmpty()) + return optional_info; + + Address vtable_addr_resolved; + SymbolContext sc; + Symbol *symbol; + + if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address, + vtable_addr_resolved)) + return optional_info; + + target.GetImages().ResolveSymbolContextForAddress( + vtable_addr_resolved, eSymbolContextEverything, sc); + symbol = sc.symbol; + + if (symbol == nullptr) + return optional_info; + + 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 optional_info; + + // 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(','); + + 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 != nullptr && + 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().FindSymbolsMatchingRegExAndType( + RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true); + + // 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); + + if (first_template_parameter.contains("$_") || + (symbol != nullptr && + symbol->GetName().GetStringRef().contains("__invoke"))) { + // Case 1 and 2 + optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda; + } else { + // Case 3 + optional_info.callable_case = + LibCppStdFunctionCallableCase::CallableObject; + } + + optional_info.callable_symbol = *symbol; + optional_info.callable_line_entry = line_entry; + optional_info.callable_address = addr; + return optional_info; + } + } + + // Case 4 or 5 + if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for")) { + optional_info.callable_case = + LibCppStdFunctionCallableCase::FreeOrMemberFunction; + optional_info.callable_address = function_address_resolved; + optional_info.callable_symbol = *symbol; + + return optional_info; + } + + return optional_info; +} + +lldb::ThreadPlanSP +CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, + bool stop_others) { + ThreadPlanSP ret_plan_sp; + + lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); + + TargetSP target_sp(thread.CalculateTarget()); + + if (target_sp->GetSectionLoadList().IsEmpty()) + return ret_plan_sp; + + Address pc_addr_resolved; + SymbolContext sc; + Symbol *symbol; + + if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc, + pc_addr_resolved)) + return ret_plan_sp; + + target_sp->GetImages().ResolveSymbolContextForAddress( + pc_addr_resolved, eSymbolContextEverything, sc); + symbol = sc.symbol; + + if (symbol == nullptr) + return ret_plan_sp; + + llvm::StringRef function_name(symbol->GetName().GetCString()); + + // Handling the case where we are attempting to step into std::function. + // The behavior will be that we will attempt to obtain the wrapped + // callable via FindLibCppStdFunctionCallableInfo() and if we find it we + // will return a ThreadPlanRunToAddress to the callable. Therefore we will + // step into the wrapped callable. + // + bool found_expected_start_string = + function_name.startswith("std::__1::function<"); + + if (!found_expected_start_string) + return ret_plan_sp; + + AddressRange range_of_curr_func; + sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func); + + StackFrameSP frame = thread.GetStackFrameAtIndex(0); + + if (frame) { + ValueObjectSP value_sp = frame->FindVariable(g_this); + + CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info = + FindLibCppStdFunctionCallableInfo(value_sp); + + if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid && + value_sp->GetValueIsValid()) { + // We found the std::function wrapped callable and we have its address. + // We now create a ThreadPlan to run to the callable. + ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>( + thread, callable_info.callable_address, stop_others); + return ret_plan_sp; + } else { + // We are in std::function but we could not obtain the callable. + // We create a ThreadPlan to keep stepping through using the address range + // of the current function. + ret_plan_sp = std::make_shared<ThreadPlanStepInRange>( + thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes, + eLazyBoolYes); + return ret_plan_sp; + } + } + + return ret_plan_sp; +} diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h new file mode 100644 index 0000000000000..28526361efc4a --- /dev/null +++ b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -0,0 +1,90 @@ +//===-- CPPLanguageRuntime.h +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CPPLanguageRuntime_h_ +#define liblldb_CPPLanguageRuntime_h_ + +#include <vector> +#include "lldb/Core/PluginInterface.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class CPPLanguageRuntime : public LanguageRuntime { +public: + enum class LibCppStdFunctionCallableCase { + Lambda = 0, + CallableObject, + FreeOrMemberFunction, + Invalid + }; + + struct LibCppStdFunctionCallableInfo { + Symbol callable_symbol; + Address callable_address; + LineEntry callable_line_entry; + lldb::addr_t member__f_pointer_value = 0u; + LibCppStdFunctionCallableCase callable_case = + LibCppStdFunctionCallableCase::Invalid; + }; + + LibCppStdFunctionCallableInfo + FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp); + + ~CPPLanguageRuntime() override; + + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || LanguageRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); + } + + lldb::LanguageType GetLanguageType() const override { + return lldb::eLanguageTypeC_plus_plus; + } + + static CPPLanguageRuntime *Get(Process &process) { + return llvm::cast_or_null<CPPLanguageRuntime>( + process.GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus)); + } + + bool GetObjectDescription(Stream &str, ValueObject &object) override; + + bool GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) override; + + /// Obtain a ThreadPlan to get us into C++ constructs such as std::function. + /// + /// \param[in] thread + /// Curent thrad of execution. + /// + /// \param[in] stop_others + /// True if other threads should pause during execution. + /// + /// \return + /// A ThreadPlan Shared pointer + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, + bool stop_others) override; + + bool IsWhitelistedRuntimeValue(ConstString name) override; +protected: + // Classes that inherit from CPPLanguageRuntime can see and modify these + CPPLanguageRuntime(Process *process); + +private: + DISALLOW_COPY_AND_ASSIGN(CPPLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_CPPLanguageRuntime_h_ diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 49a3d40d7b371..41f38a4e3dcd0 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -1,10 +1,9 @@ //===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- //C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -44,10 +43,12 @@ using namespace lldb_private; static const char *vtable_demangled_prefix = "vtable for "; +char ItaniumABILanguageRuntime::ID = 0; + bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) { const bool check_cxx = true; const bool check_objc = false; - return in_value.GetCompilerType().IsPossibleDynamicType(NULL, check_cxx, + return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx, check_objc); } @@ -70,7 +71,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( target.GetImages().ResolveSymbolContextForAddress( vtable_addr, eSymbolContextSymbol, sc); Symbol *symbol = sc.symbol; - if (symbol != NULL) { + if (symbol != nullptr) { const char *name = symbol->GetMangled() .GetDemangledName(lldb::eLanguageTypeC_plus_plus) @@ -236,16 +237,15 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( if (!class_type_or_name) return false; - TypeSP type_sp = class_type_or_name.GetTypeSP(); + CompilerType type = class_type_or_name.GetCompilerType(); // There can only be one type with a given name, so we've just found // duplicate definitions, and this one will do as well as any other. We // don't consider something to have a dynamic type if it is the same as // the static type. So compare against the value we were handed. - if (!type_sp) + if (!type) return true; - if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), - type_sp->GetForwardCompilerType())) { + if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type)) { // The dynamic type we found was the same type, so we don't have a // dynamic type here... return false; @@ -307,17 +307,7 @@ TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType( return ret; } -bool ItaniumABILanguageRuntime::IsVTableName(const char *name) { - if (name == NULL) - return false; - - // Can we maybe ask Clang about this? - return strstr(name, "_vptr$") == name; -} - -//------------------------------------------------------------------ // Static Functions -//------------------------------------------------------------------ LanguageRuntime * ItaniumABILanguageRuntime::CreateInstance(Process *process, lldb::LanguageType language) { @@ -330,7 +320,7 @@ ItaniumABILanguageRuntime::CreateInstance(Process *process, language == eLanguageTypeC_plus_plus_14) return new ItaniumABILanguageRuntime(process); else - return NULL; + return nullptr; } class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed { @@ -429,9 +419,7 @@ lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginNameStatic() { return g_name; } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginName() { return GetPluginNameStatic(); } @@ -479,16 +467,14 @@ BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver( lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() { Target &target = m_process->GetTarget(); + FileSpecList filter_modules; if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) { // Limit the number of modules that are searched for these breakpoints for // Apple binaries. - FileSpecList filter_modules; filter_modules.Append(FileSpec("libc++abi.dylib")); filter_modules.Append(FileSpec("libSystem.B.dylib")); - return target.GetSearchFilterForModuleList(&filter_modules); - } else { - return LanguageRuntime::CreateExceptionSearchFilter(); } + return target.GetSearchFilterForModuleList(&filter_modules); } lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint( @@ -496,7 +482,7 @@ lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint( Target &target = m_process->GetTarget(); FileSpecList filter_modules; BreakpointResolverSP exception_resolver_sp = - CreateExceptionResolver(NULL, catch_bp, throw_bp, for_expressions); + CreateExceptionResolver(nullptr, catch_bp, throw_bp, for_expressions); SearchFilterSP filter_sp(CreateExceptionSearchFilter()); const bool hardware = false; const bool resolve_indirect_functions = false; @@ -569,7 +555,7 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); + options.SetTimeout(m_process->GetUtilityExpressionTimeout()); options.SetTryAllThreads(false); thread_sp->CalculateExecutionContext(exe_ctx); @@ -600,6 +586,10 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( addr_t exception_addr = m_process->ReadPointerFromMemory(result_ptr - ptr_size, error); + if (!error.Success()) { + return ValueObjectSP(); + } + lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr, *m_process); ValueObjectSP exception = ValueObject::CreateValueObjectFromData( diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index abed3706c6b8b..97cc81b8681fc 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -1,9 +1,8 @@ //===-- ItaniumABILanguageRuntime.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -17,19 +16,18 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Core/Value.h" #include "lldb/Symbol/Type.h" -#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" + namespace lldb_private { class ItaniumABILanguageRuntime : public lldb_private::CPPLanguageRuntime { public: ~ItaniumABILanguageRuntime() override = default; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -39,7 +37,15 @@ public: static lldb_private::ConstString GetPluginNameStatic(); - bool IsVTableName(const char *name) override; + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || CPPLanguageRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); + } bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, @@ -69,9 +75,7 @@ public: lldb::ValueObjectSP GetExceptionObjectForThread( lldb::ThreadSP thread_sp) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -91,9 +95,8 @@ private: ItaniumABILanguageRuntime(Process *process) : // Call CreateInstance instead. - lldb_private::CPPLanguageRuntime(process), - m_cxx_exception_bp_sp(), m_dynamic_type_map(), - m_dynamic_type_map_mutex() {} + lldb_private::CPPLanguageRuntime(process), m_cxx_exception_bp_sp(), + m_dynamic_type_map(), m_dynamic_type_map_mutex() {} lldb::BreakpointSP m_cxx_exception_bp_sp; DynamicTypeCache m_dynamic_type_map; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 679c3c850e5b5..93aa07f89165e 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -1,10 +1,9 @@ //===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -335,9 +334,9 @@ bool ClassDescriptorV2::Describe( std::unique_ptr<class_rw_t> class_rw; if (!Read_objc_class(process, objc_class)) - return 0; + return false; if (!Read_class_row(process, *objc_class, class_ro, class_rw)) - return 0; + return false; static ConstString NSObject_name("NSObject"); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 308ff1426fb26..b8ba9dbb65f45 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -1,9 +1,8 @@ //===-- AppleObjCClassDescriptorV2.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -13,9 +12,10 @@ #include <mutex> #include "AppleObjCRuntimeV2.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + namespace lldb_private { class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor { diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 4fc340b23c2c7..18f2a1829a419 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -1,19 +1,18 @@ //===-- AppleObjCDeclVendor.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "AppleObjCDeclVendor.h" #include "Plugins/ExpressionParser/Clang/ASTDumper.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangUtil.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" @@ -21,6 +20,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" + using namespace lldb_private; class lldb_private::AppleObjCExternalASTSource @@ -63,7 +63,7 @@ public: non_const_interface_decl->lookup(name); return (result.size() != 0); - } while (0); + } while (false); SetNoExternalVisibleDeclsForName(decl_ctx, name); return false; @@ -174,9 +174,9 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) { m_runtime.GetClassDescriptorFromISA(isa); if (!descriptor) - return NULL; + return nullptr; - const ConstString &name(descriptor->GetClassName()); + ConstString name(descriptor->GetClassName()); clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef()); @@ -204,12 +204,12 @@ public: ObjCRuntimeMethodType(const char *types) : m_is_valid(false) { const char *cursor = types; enum ParserState { Start = 0, InType, InPos } state = Start; - const char *type = NULL; + const char *type = nullptr; int brace_depth = 0; uint32_t stepsLeft = 256; - while (1) { + while (true) { if (--stepsLeft == 0) { m_is_valid = false; return; @@ -262,7 +262,7 @@ public: m_is_valid = false; return; } - type = NULL; + type = nullptr; } else { ++cursor; } @@ -320,7 +320,7 @@ public: bool instance, ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) { if (!m_is_valid || m_type_vector.size() < 3) - return NULL; + return nullptr; clang::ASTContext &ast_ctx(interface_decl->getASTContext()); @@ -355,7 +355,7 @@ public: clang::IdentifierInfo **identifier_infos = selector_components.data(); if (!identifier_infos) { - return NULL; + return nullptr; } clang::Selector sel = ast_ctx.Selectors.getSelector( @@ -368,12 +368,13 @@ public: for_expression)); if (ret_type.isNull()) - return NULL; + return nullptr; clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create( ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel, - ret_type, NULL, interface_decl, isInstance, isVariadic, isSynthesized, - isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); + ret_type, nullptr, interface_decl, isInstance, isVariadic, + isSynthesized, isImplicitlyDeclared, isDefined, impControl, + HasRelatedResultType); std::vector<clang::ParmVarDecl *> parm_vars; @@ -384,12 +385,12 @@ public: ast_ctx, m_type_vector[ai].c_str(), for_expression)); if (arg_type.isNull()) - return NULL; // well, we just wasted a bunch of time. Wish we could - // delete the stuff we'd just made! + return nullptr; // well, we just wasted a bunch of time. Wish we could + // delete the stuff we'd just made! parm_vars.push_back(clang::ParmVarDecl::Create( - ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), NULL, - arg_type, NULL, clang::SC_None, NULL)); + ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), + nullptr, arg_type, nullptr, clang::SC_None, nullptr)); } ret->setMethodParams(ast_ctx, @@ -513,7 +514,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name), ClangUtil::GetQualType(ivar_type), type_source_info, // TypeSourceInfo * - clang::ObjCIvarDecl::Public, 0, is_synthesized); + clang::ObjCIvarDecl::Public, nullptr, is_synthesized); if (ivar_decl) { interface_decl->addDecl(ivar_decl); @@ -548,7 +549,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { } uint32_t -AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append, +AppleObjCDeclVendor::FindDecls(ConstString name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) { static unsigned int invocation_id = 0; @@ -647,7 +648,7 @@ AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append, decls.push_back(iface_decl); ret++; break; - } while (0); + } while (false); return ret; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 7f5c0bf3eb632..77b30b7fde791 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -1,9 +1,8 @@ //===-- AppleObjCDeclVendor.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -12,9 +11,10 @@ #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/DeclVendor.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + namespace lldb_private { class AppleObjCExternalASTSource; @@ -23,7 +23,7 @@ class AppleObjCDeclVendor : public DeclVendor { public: AppleObjCDeclVendor(ObjCLanguageRuntime &runtime); - uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches, + uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) override; clang::ExternalASTMerger::ImporterSource GetImporterSource() override; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index ed47b481a810a..52ed3628520f9 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -1,10 +1,9 @@ //===-- AppleObjCRuntime.cpp -------------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -25,7 +24,6 @@ #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -40,19 +38,20 @@ #include "Plugins/Process/Utility/HistoryThread.h" #include "Plugins/Language/ObjC/NSString.h" +#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" #include <vector> using namespace lldb; using namespace lldb_private; -static constexpr std::chrono::seconds g_po_function_timeout(15); +char AppleObjCRuntime::ID = 0; AppleObjCRuntime::~AppleObjCRuntime() {} AppleObjCRuntime::AppleObjCRuntime(Process *process) : ObjCLanguageRuntime(process), m_read_objc_library(false), - m_objc_trampoline_handler_ap(), m_Foundation_major() { + m_objc_trampoline_handler_up(), m_Foundation_major() { ReadObjCLibraryIfNeeded(process->GetTarget().GetImages()); } @@ -131,9 +130,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, // ret.SetContext(Value::eContextTypeClangType, return_compiler_type); ret.SetCompilerType(return_compiler_type); - if (exe_ctx.GetFramePtr() == NULL) { + if (exe_ctx.GetFramePtr() == nullptr) { Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) { + if (thread == nullptr) { exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread()); thread = exe_ctx.GetThreadPtr(); } @@ -172,7 +171,7 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); - options.SetTimeout(g_po_function_timeout); + options.SetTimeout(process->GetUtilityExpressionTimeout()); options.SetIsForUtilityExpr(true); ExpressionResults results = m_print_object_caller_up->ExecuteFunction( @@ -218,7 +217,7 @@ lldb::ModuleSP AppleObjCRuntime::GetObjCModule() { } Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { - if (!m_PrintForDebugger_addr.get()) { + if (!m_PrintForDebugger_addr) { const ModuleList &modules = m_process->GetTarget().GetImages(); SymbolContextList contexts; @@ -228,7 +227,7 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { eSymbolTypeCode, contexts)) && (!modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), eSymbolTypeCode, contexts))) - return NULL; + return nullptr; contexts.GetContextAtIndex(0, context); @@ -240,7 +239,7 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { bool AppleObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) { return in_value.GetCompilerType().IsPossibleDynamicType( - NULL, + nullptr, false, // do not check C++ true); // check ObjC } @@ -328,9 +327,9 @@ bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) { // Maybe check here and if we have a handler already, and the UUID of this // module is the same as the one in the current module, then we don't have to // reread it? - m_objc_trampoline_handler_ap.reset( + m_objc_trampoline_handler_up.reset( new AppleObjCTrampolineHandler(m_process->shared_from_this(), module_sp)); - if (m_objc_trampoline_handler_ap.get() != NULL) { + if (m_objc_trampoline_handler_up != nullptr) { m_read_objc_library = true; return true; } else @@ -340,15 +339,13 @@ bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) { ThreadPlanSP AppleObjCRuntime::GetStepThroughTrampolinePlan(Thread &thread, bool stop_others) { ThreadPlanSP thread_plan_sp; - if (m_objc_trampoline_handler_ap.get()) - thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan( + if (m_objc_trampoline_handler_up) + thread_plan_sp = m_objc_trampoline_handler_up->GetStepThroughDispatchPlan( thread, stop_others); return thread_plan_sp; } -//------------------------------------------------------------------ // Static Functions -//------------------------------------------------------------------ ObjCLanguageRuntime::ObjCRuntimeVersions AppleObjCRuntime::GetObjCVersion(Process *process, ModuleSP &objc_module_sp) { if (!process) @@ -456,28 +453,27 @@ bool AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() { lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() { Target &target = m_process->GetTarget(); + FileSpecList filter_modules; if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) { - FileSpecList filter_modules; filter_modules.Append(std::get<0>(GetExceptionThrowLocation())); - return target.GetSearchFilterForModuleList(&filter_modules); - } else { - return LanguageRuntime::CreateExceptionSearchFilter(); } + return target.GetSearchFilterForModuleList(&filter_modules); } ValueObjectSP AppleObjCRuntime::GetExceptionObjectForThread( ThreadSP thread_sp) { - auto cpp_runtime = m_process->GetCPPLanguageRuntime(); + auto *cpp_runtime = m_process->GetLanguageRuntime(eLanguageTypeC_plus_plus); if (!cpp_runtime) return ValueObjectSP(); auto cpp_exception = cpp_runtime->GetExceptionObjectForThread(thread_sp); if (!cpp_exception) return ValueObjectSP(); - - auto descriptor = GetClassDescriptor(*cpp_exception.get()); + + auto descriptor = GetClassDescriptor(*cpp_exception); if (!descriptor || !descriptor->IsValid()) return ValueObjectSP(); while (descriptor) { ConstString class_name(descriptor->GetClassName()); - if (class_name == ConstString("NSException")) return cpp_exception; + if (class_name == "NSException") + return cpp_exception; descriptor = descriptor->GetSuperclass(); } @@ -556,7 +552,7 @@ ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException( if (pcs.empty()) return ThreadSP(); - ThreadSP new_thread_sp(new HistoryThread(*m_process, 0, pcs, 0, false)); + ThreadSP new_thread_sp(new HistoryThread(*m_process, 0, pcs)); m_process->GetExtendedThreadList().AddThread(new_thread_sp); return new_thread_sp; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index 8660646001497..79ac53e1e440a 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -1,9 +1,8 @@ //===-- AppleObjCRuntime.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,30 +14,29 @@ #include "AppleObjCTrampolineHandler.h" #include "AppleThreadPlanStepThroughObjCTrampoline.h" #include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + namespace lldb_private { class AppleObjCRuntime : public lldb_private::ObjCLanguageRuntime { public: ~AppleObjCRuntime() override; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ // Note there is no CreateInstance, Initialize & Terminate functions here, // because // you can't make an instance of this generic runtime. - static bool classof(const ObjCLanguageRuntime *runtime) { - switch (runtime->GetRuntimeVersion()) { - case ObjCRuntimeVersions::eAppleObjC_V1: - case ObjCRuntimeVersions::eAppleObjC_V2: - return true; - default: - return false; - } + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjCLanguageRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); } // These are generic runtime functions: @@ -120,7 +118,7 @@ protected: std::unique_ptr<Address> m_PrintForDebugger_addr; bool m_read_objc_library; std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> - m_objc_trampoline_handler_ap; + m_objc_trampoline_handler_up; lldb::BreakpointSP m_objc_exception_bp_sp; lldb::ModuleWP m_objc_module_wp; std::unique_ptr<FunctionCaller> m_print_object_caller_up; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 1cfc7a1a022b5..c8884fd5c9b9c 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -1,10 +1,9 @@ //===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -32,11 +31,14 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include <memory> #include <vector> using namespace lldb; using namespace lldb_private; +char AppleObjCRuntimeV1::ID = 0; + AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process) : AppleObjCRuntime(process), m_hash_signature(), m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {} @@ -61,9 +63,7 @@ bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress( return !class_type_or_name.IsEmpty(); } -//------------------------------------------------------------------ // Static Functions -//------------------------------------------------------------------ lldb_private::LanguageRuntime * AppleObjCRuntimeV1::CreateInstance(Process *process, lldb::LanguageType language) { @@ -77,15 +77,16 @@ AppleObjCRuntimeV1::CreateInstance(Process *process, ObjCRuntimeVersions::eAppleObjC_V1) return new AppleObjCRuntimeV1(process); else - return NULL; + return nullptr; } else - return NULL; + return nullptr; } void AppleObjCRuntimeV1::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1", - CreateInstance); + CreateInstance, + /*command_callback = */ nullptr, GetBreakpointExceptionPrecondition); } void AppleObjCRuntimeV1::Terminate() { @@ -97,9 +98,7 @@ lldb_private::ConstString AppleObjCRuntimeV1::GetPluginNameStatic() { return g_name; } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ ConstString AppleObjCRuntimeV1::GetPluginName() { return GetPluginNameStatic(); } @@ -112,10 +111,10 @@ AppleObjCRuntimeV1::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, BreakpointResolverSP resolver_sp; if (throw_bp) - resolver_sp.reset(new BreakpointResolverName( + resolver_sp = std::make_shared<BreakpointResolverName>( bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(), eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0, - eLazyBoolNo)); + eLazyBoolNo); // FIXME: don't do catch yet. return resolver_sp; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h index 442a3a1fb5e1e..6fdae63d4126e 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h @@ -1,9 +1,8 @@ //===-- AppleObjCRuntimeV1.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -11,18 +10,17 @@ #define liblldb_AppleObjCRuntimeV1_h_ #include "AppleObjCRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + namespace lldb_private { class AppleObjCRuntimeV1 : public AppleObjCRuntime { public: ~AppleObjCRuntimeV1() override = default; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -32,13 +30,14 @@ public: static lldb_private::ConstString GetPluginNameStatic(); - static bool classof(const ObjCLanguageRuntime *runtime) { - switch (runtime->GetRuntimeVersion()) { - case ObjCRuntimeVersions::eAppleObjC_V1: - return true; - default: - return false; - } + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || AppleObjCRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); } lldb::addr_t GetTaggedPointerObfuscator(); @@ -100,9 +99,7 @@ public: UtilityFunction *CreateObjectChecker(const char *) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -148,7 +145,7 @@ protected: HashTableSignature m_hash_signature; lldb::addr_t m_isa_hash_table_ptr; - std::unique_ptr<DeclVendor> m_decl_vendor_ap; + std::unique_ptr<DeclVendor> m_decl_vendor_up; private: AppleObjCRuntimeV1(Process *process); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index b6ed2fe376d35..635eaff637bcb 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -1,14 +1,14 @@ //===-- AppleObjCRuntimeV2.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include <stdint.h> +#include <memory> #include <string> #include <vector> @@ -65,13 +65,14 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + #include <vector> using namespace lldb; using namespace lldb_private; -// 2 second timeout when running utility functions -static constexpr std::chrono::seconds g_utility_function_timeout(2); +char AppleObjCRuntimeV2::ID = 0; static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info"; @@ -157,6 +158,16 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr )"; +// We'll substitute in class_getName or class_getNameRaw depending +// on which is present. +static const char *g_shared_cache_class_name_funcptr = R"( +extern "C" +{ + const char *%s(void *objc_class); + const char *(*class_name_lookup_func)(void *) = %s; +} +)"; + static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info"; // Testing using the new C++11 raw string literals. If this breaks GCC then we @@ -165,7 +176,6 @@ static const char *g_get_shared_cache_class_info_body = R"( extern "C" { - const char *class_getName(void *objc_class); size_t strlen(const char *); char *strncpy (char * s1, const char * s2, size_t n); int printf(const char * format, ...); @@ -286,13 +296,24 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, if (class_infos && idx < max_class_infos) { class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); - const char *name = class_getName (class_infos[idx].isa); + const char *name = class_name_lookup_func (class_infos[idx].isa); DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); // Hash the class name so we don't have to read it const char *s = name; uint32_t h = 5381; for (unsigned char c = *s; c; c = *++s) + { + // class_getName demangles swift names and the hash must + // be calculated on the mangled name. hash==0 means lldb + // will fetch the mangled name and compute the hash in + // ParseClassInfoArray. + if (c == '.') + { + h = 0; + break; + } h = ((h << 5) + h) + c; + } class_infos[idx].hash = h; } else @@ -318,13 +339,24 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, if (class_infos && idx < max_class_infos) { class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); - const char *name = class_getName (class_infos[idx].isa); + const char *name = class_name_lookup_func (class_infos[idx].isa); DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); // Hash the class name so we don't have to read it const char *s = name; uint32_t h = 5381; for (unsigned char c = *s; c; c = *++s) + { + // class_getName demangles swift names and the hash must + // be calculated on the mangled name. hash==0 means lldb + // will fetch the mangled name and compute the hash in + // ParseClassInfoArray. + if (c == '.') + { + h = 0; + break; + } h = ((h << 5) + h) + c; + } class_infos[idx].hash = h; } ++idx; @@ -384,20 +416,20 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, m_get_class_info_args(LLDB_INVALID_ADDRESS), m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(), m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS), - m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_ap(), + m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_up(), m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS), - m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), - m_hash_signature(), + m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(), m_has_object_getClass(false), m_loaded_objc_opt(false), - m_non_pointer_isa_cache_ap( + m_non_pointer_isa_cache_up( NonPointerISACache::CreateInstance(*this, objc_module_sp)), - m_tagged_pointer_vendor_ap( + m_tagged_pointer_vendor_up( TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)), m_encoding_to_type_sp(), m_noclasses_warning_emitted(false), m_CFBoolean_values() { static const ConstString g_gdb_object_getClass("gdb_object_getClass"); - m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType( - g_gdb_object_getClass, eSymbolTypeCode) != NULL); + m_has_object_getClass = + (objc_module_sp->FindFirstSymbolWithNameAndType( + g_gdb_object_getClass, eSymbolTypeCode) != nullptr); RegisterObjCExceptionRecognizer(); } @@ -406,7 +438,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) { // We should never get here with a null process... - assert(m_process != NULL); + assert(m_process != nullptr); // The Runtime is attached to a particular process, you shouldn't pass in a // value from another process. Note, however, the process might be NULL (e.g. @@ -443,12 +475,10 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( class_type_or_name.SetTypeSP(type_sp); } else { // try to go for a CompilerType at least - DeclVendor *vendor = GetDeclVendor(); - if (vendor) { - std::vector<clang::NamedDecl *> decls; - if (vendor->FindDecls(class_name, false, 1, decls) && decls.size()) - class_type_or_name.SetCompilerType( - ClangASTContext::GetTypeForDecl(decls[0])); + if (auto *vendor = GetDeclVendor()) { + auto types = vendor->FindTypes(class_name, /*max_matches*/ 1); + if (!types.empty()) + class_type_or_name.SetCompilerType(types.front()); } } } @@ -457,9 +487,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( return !class_type_or_name.IsEmpty(); } -//------------------------------------------------------------------ // Static Functions -//------------------------------------------------------------------ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process, LanguageType language) { // FIXME: This should be a MacOS or iOS process, and we need to look for the @@ -472,9 +500,9 @@ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process, ObjCRuntimeVersions::eAppleObjC_V2) return new AppleObjCRuntimeV2(process, objc_module_sp); else - return NULL; + return nullptr; } else - return NULL; + return nullptr; } static constexpr OptionDefinition g_objc_classtable_dump_options[] = { @@ -572,7 +600,7 @@ protected: } Process *process = m_exe_ctx.GetProcessPtr(); - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); + ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); if (objc_runtime) { auto iterators_pair = objc_runtime->GetDescriptorIteratorPair(); auto iterator = iterators_pair.first; @@ -674,7 +702,7 @@ protected: Process *process = m_exe_ctx.GetProcessPtr(); ExecutionContext exe_ctx(process); - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); + ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); if (objc_runtime) { ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = objc_runtime->GetTaggedPointerVendor(); @@ -777,7 +805,8 @@ void AppleObjCRuntimeV2::Initialize() { CreateInstance, [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP { return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter)); - }); + }, + GetBreakpointExceptionPrecondition); } void AppleObjCRuntimeV2::Terminate() { @@ -789,9 +818,7 @@ lldb_private::ConstString AppleObjCRuntimeV2::GetPluginNameStatic() { return g_name; } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ lldb_private::ConstString AppleObjCRuntimeV2::GetPluginName() { return GetPluginNameStatic(); } @@ -804,10 +831,10 @@ AppleObjCRuntimeV2::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, BreakpointResolverSP resolver_sp; if (throw_bp) - resolver_sp.reset(new BreakpointResolverName( + resolver_sp = std::make_shared<BreakpointResolverName>( bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(), eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0, - eLazyBoolNo)); + eLazyBoolNo); // FIXME: We don't do catch breakpoints for ObjC yet. // Should there be some way for the runtime to specify what it can do in this // regard? @@ -872,20 +899,16 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type, const char *class_name = parent_ast_type.GetConstTypeName().AsCString(); if (class_name && class_name[0] && ivar_name && ivar_name[0]) { - //---------------------------------------------------------------------- // Make the objective C V2 mangled name for the ivar offset from the class // name and ivar name - //---------------------------------------------------------------------- std::string buffer("OBJC_IVAR_$_"); buffer.append(class_name); buffer.push_back('.'); buffer.append(ivar_name); ConstString ivar_const_str(buffer.c_str()); - //---------------------------------------------------------------------- // Try to get the ivar offset address from the symbol table first using the // name we created above - //---------------------------------------------------------------------- SymbolContextList sc_list; Target &target = m_process->GetTarget(); target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, @@ -902,10 +925,8 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type, ivar_offset_symbol.symbol->GetLoadAddress(&target); } - //---------------------------------------------------------------------- // If we didn't get the ivar offset address from the symbol table, fall // back to getting it from the runtime - //---------------------------------------------------------------------- if (ivar_offset_address == LLDB_INVALID_ADDRESS) ivar_offset_address = LookupRuntimeSymbol(ivar_const_str); @@ -921,16 +942,16 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type, // computational effort as possible whether something could possibly be a // tagged pointer - false positives are possible but false negatives shouldn't bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) { - if (!m_tagged_pointer_vendor_ap) + if (!m_tagged_pointer_vendor_up) return false; - return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr); + return m_tagged_pointer_vendor_up->IsPossibleTaggedPointer(ptr); } class RemoteNXMapTable { public: RemoteNXMapTable() : m_count(0), m_num_buckets_minus_one(0), - m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(NULL), + m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr), m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS), m_map_pair_size(0), m_invalid_key(0) {} @@ -1148,8 +1169,8 @@ bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate( ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) { ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp; - if (m_non_pointer_isa_cache_ap.get()) - class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa); + if (m_non_pointer_isa_cache_up) + class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa); if (!class_descriptor_sp) class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa); return class_descriptor_sp; @@ -1176,7 +1197,7 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) { // tagged pointer if (IsTaggedPointer(isa_pointer)) { - return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer); + return m_tagged_pointer_vendor_up->GetClassDescriptor(isa_pointer); } else { ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); @@ -1265,7 +1286,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( RemoteNXMapTable &hash_table) { Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return DescriptorMapUpdateResult::Fail(); uint32_t num_class_infos = 0; @@ -1310,7 +1331,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( ValueList arguments; FunctionCaller *get_class_info_function = nullptr; - if (!m_get_class_info_code.get()) { + if (!m_get_class_info_code) { Status error; m_get_class_info_code.reset(GetTargetRef().GetUtilityFunctionForLanguage( g_get_dynamic_class_info_body, eLanguageTypeObjC, @@ -1332,7 +1353,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( m_get_class_info_code.reset(); } } - if (!m_get_class_info_code.get()) + if (!m_get_class_info_code) return DescriptorMapUpdateResult::Fail(); // Next make the runner function for our implementation utility function. @@ -1411,7 +1432,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( options.SetTryAllThreads(false); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); - options.SetTimeout(g_utility_function_timeout); + options.SetTimeout(process->GetUtilityExpressionTimeout()); options.SetIsForUtilityExpr(true); Value return_value; @@ -1501,8 +1522,18 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, } else { // Read the 32 bit hash for the class name const uint32_t name_hash = data.GetU32(&offset); - ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, NULL)); - AddClass(isa, descriptor_sp, name_hash); + ClassDescriptorSP descriptor_sp( + new ClassDescriptorV2(*this, isa, nullptr)); + + // The code in g_get_shared_cache_class_info_body sets the value of the hash + // to 0 to signal a demangled symbol. We use class_getName() in that code to + // find the class name, but this returns a demangled name for Swift symbols. + // For those symbols, recompute the hash here by reading their name from the + // runtime. + if (name_hash) + AddClass(isa, descriptor_sp, name_hash); + else + AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr)); num_parsed++; if (should_log) log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 @@ -1521,7 +1552,7 @@ AppleObjCRuntimeV2::DescriptorMapUpdateResult AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return DescriptorMapUpdateResult::Fail(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); @@ -1565,11 +1596,54 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { ValueList arguments; FunctionCaller *get_shared_cache_class_info_function = nullptr; - if (!m_get_shared_cache_class_info_code.get()) { + if (!m_get_shared_cache_class_info_code) { Status error; + + // If the inferior objc.dylib has the class_getNameRaw function, + // use that in our jitted expression. Else fall back to the old + // class_getName. + static ConstString g_class_getName_symbol_name("class_getName"); + static ConstString g_class_getNameRaw_symbol_name("class_getNameRaw"); + ConstString class_name_getter_function_name = g_class_getName_symbol_name; + + ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); + if (objc_runtime) { + const ModuleList &images = process->GetTarget().GetImages(); + std::lock_guard<std::recursive_mutex> guard(images.GetMutex()); + for (size_t i = 0; i < images.GetSize(); ++i) { + lldb::ModuleSP mod_sp = images.GetModuleAtIndexUnlocked(i); + if (objc_runtime->IsModuleObjCLibrary(mod_sp)) { + const Symbol *symbol = + mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name, + lldb::eSymbolTypeCode); + if (symbol && + (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) { + class_name_getter_function_name = g_class_getNameRaw_symbol_name; + } + } + } + } + + // Substitute in the correct class_getName / class_getNameRaw function name, + // concatenate the two parts of our expression text. The format string + // has two %s's, so provide the name twice. + int prefix_string_size = snprintf (nullptr, 0, + g_shared_cache_class_name_funcptr, + class_name_getter_function_name.AsCString(), + class_name_getter_function_name.AsCString()); + + char *class_name_func_ptr_expr = (char*) malloc (prefix_string_size + 1); + snprintf (class_name_func_ptr_expr, prefix_string_size + 1, + g_shared_cache_class_name_funcptr, + class_name_getter_function_name.AsCString(), + class_name_getter_function_name.AsCString()); + std::string shared_class_expression = class_name_func_ptr_expr; + shared_class_expression += g_get_shared_cache_class_info_body; + free (class_name_func_ptr_expr); + m_get_shared_cache_class_info_code.reset( GetTargetRef().GetUtilityFunctionForLanguage( - g_get_shared_cache_class_info_body, eLanguageTypeObjC, + shared_class_expression.c_str(), eLanguageTypeObjC, g_get_shared_cache_class_info_name, error)); if (error.Fail()) { if (log) @@ -1589,7 +1663,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { } } - if (!m_get_shared_cache_class_info_code.get()) + if (!m_get_shared_cache_class_info_code) return DescriptorMapUpdateResult::Fail(); // Next make the function caller for our implementation utility function. @@ -1662,7 +1736,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { options.SetTryAllThreads(false); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); - options.SetTimeout(g_utility_function_timeout); + options.SetTimeout(process->GetUtilityExpressionTimeout()); options.SetIsForUtilityExpr(true); Value return_value; @@ -1686,9 +1760,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { if (log) log->Printf("Discovered %u ObjC classes in shared cache\n", num_class_infos); -#ifdef LLDB_CONFIGURATION_DEBUG assert(num_class_infos <= num_classes); -#endif if (num_class_infos > 0) { if (num_class_infos > num_classes) { num_class_infos = num_classes; @@ -1737,7 +1809,7 @@ bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return false; uint32_t num_map_table_isas = 0; @@ -1946,13 +2018,13 @@ AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) { } DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() { - if (!m_decl_vendor_ap.get()) - m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this)); + if (!m_decl_vendor_up) + m_decl_vendor_up.reset(new AppleObjCDeclVendor(*this)); - return m_decl_vendor_ap.get(); + return m_decl_vendor_up.get(); } -lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(const ConstString &name) { +lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { lldb::addr_t ret = LLDB_INVALID_ADDRESS; const char *name_cstr = name.AsCString(); @@ -2022,18 +2094,18 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_value"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; if (log) log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); @@ -2550,7 +2622,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() { if (!m_encoding_to_type_sp) - m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this)); + m_encoding_to_type_sp = + std::make_shared<AppleObjCTypeEncodingParser>(*this); return m_encoding_to_type_sp; } @@ -2558,8 +2631,8 @@ lldb_private::AppleObjCRuntime::ObjCISA AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) { ObjCISA ret = isa; - if (m_non_pointer_isa_cache_ap) - m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret); + if (m_non_pointer_isa_cache_up) + m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret); return ret; } @@ -2629,6 +2702,8 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { value.SetCompilerType(voidstar); exception = ValueObjectConstResult::Create(frame_sp.get(), value, ConstString("exception")); + exception = ValueObjectRecognizerSynthesizedValue::Create( + *exception, eValueTypeVariableArgument); exception = exception->GetDynamicValue(eDynamicDontRunTarget); m_arguments = ValueObjectListSP(new ValueObjectList()); @@ -2641,7 +2716,8 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { }; class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer { - lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame) { + lldb::RecognizedStackFrameSP + RecognizeFrame(lldb::StackFrameSP frame) override { return lldb::RecognizedStackFrameSP( new ObjCExceptionRecognizedStackFrame(frame)); }; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index aa91f857219b2..a0fd39dc03b20 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -1,9 +1,8 @@ //===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,9 +14,10 @@ #include <mutex> #include "AppleObjCRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + class RemoteNXMapTable; namespace lldb_private { @@ -26,9 +26,7 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime { public: ~AppleObjCRuntimeV2() override = default; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -38,13 +36,14 @@ public: static lldb_private::ConstString GetPluginNameStatic(); - static bool classof(const ObjCLanguageRuntime *runtime) { - switch (runtime->GetRuntimeVersion()) { - case ObjCRuntimeVersions::eAppleObjC_V2: - return true; - default: - return false; - } + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || AppleObjCRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); } // These are generic runtime functions: @@ -56,9 +55,7 @@ public: UtilityFunction *CreateObjectChecker(const char *) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -80,14 +77,14 @@ public: DeclVendor *GetDeclVendor() override; - lldb::addr_t LookupRuntimeSymbol(const ConstString &name) override; + lldb::addr_t LookupRuntimeSymbol(ConstString name) override; EncodingToTypeSP GetEncodingToType() override; bool IsTaggedPointer(lldb::addr_t ptr) override; TaggedPointerVendor *GetTaggedPointerVendor() override { - return m_tagged_pointer_vendor_ap.get(); + return m_tagged_pointer_vendor_up.get(); } lldb::addr_t GetTaggedPointerObfuscator(); @@ -327,14 +324,14 @@ private: lldb::addr_t m_get_shared_cache_class_info_args; std::mutex m_get_shared_cache_class_info_args_mutex; - std::unique_ptr<DeclVendor> m_decl_vendor_ap; + std::unique_ptr<DeclVendor> m_decl_vendor_up; lldb::addr_t m_tagged_pointer_obfuscator; lldb::addr_t m_isa_hash_table_ptr; HashTableSignature m_hash_signature; bool m_has_object_getClass; bool m_loaded_objc_opt; - std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap; - std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap; + std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up; + std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up; EncodingToTypeSP m_encoding_to_type_sp; bool m_noclasses_warning_emitted; llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index e9182c5909773..b3eb09caa86dc 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -1,15 +1,13 @@ //===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "AppleObjCTrampolineHandler.h" - #include "AppleThreadPlanStepThroughObjCTrampoline.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" @@ -25,7 +23,6 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -37,6 +34,10 @@ #include "llvm/ADT/STLExtras.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + +#include <memory> + using namespace lldb; using namespace lldb_private; @@ -457,8 +458,9 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { size_t num_modules = target_modules.GetSize(); if (!m_objc_module_sp) { for (size_t i = 0; i < num_modules; i++) { - if (process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary( - target_modules.GetModuleAtIndexUnlocked(i))) { + if (ObjCLanguageRuntime::Get(*process_sp) + ->IsModuleObjCLibrary( + target_modules.GetModuleAtIndexUnlocked(i))) { m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i); break; } @@ -470,7 +472,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(trampoline_name, eSymbolTypeData); - if (trampoline_symbol != NULL) { + if (trampoline_symbol != nullptr) { m_trampoline_header = trampoline_symbol->GetLoadAddress(&target); if (m_trampoline_header == LLDB_INVALID_ADDRESS) return false; @@ -480,7 +482,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(changed_name, eSymbolTypeCode); - if (changed_symbol != NULL) { + if (changed_symbol != nullptr) { const Address changed_symbol_addr = changed_symbol->GetAddress(); if (!changed_symbol_addr.IsValid()) return false; @@ -541,7 +543,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( Status error; DataExtractor data; error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data, - 0, NULL); + 0, nullptr); lldb::offset_t offset = 0; lldb::addr_t region_addr = data.GetPointer(&offset); @@ -668,7 +670,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( ConstString msg_forward_name("_objc_msgForward"); ConstString msg_forward_stret_name("_objc_msgForward_stret"); - Target *target = process_sp ? &process_sp->GetTarget() : NULL; + Target *target = process_sp ? &process_sp->GetTarget() : nullptr; const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_name, eSymbolTypeCode); @@ -748,9 +750,9 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( } // Build our vtable dispatch handler here: - m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp)); - if (m_vtables_ap.get()) - m_vtables_ap->ReadRegions(); + m_vtables_up.reset(new AppleObjCVTables(process_sp, m_objc_module_sp)); + if (m_vtables_up) + m_vtables_up->ReadRegions(); } lldb::addr_t @@ -770,8 +772,8 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, // First stage is to make the ClangUtility to hold our injected function: - if (!m_impl_code.get()) { - if (m_lookup_implementation_function_code != NULL) { + if (!m_impl_code) { + if (m_lookup_implementation_function_code != nullptr) { Status error; m_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( m_lookup_implementation_function_code, eLanguageTypeObjC, @@ -864,8 +866,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (!found_it) { uint32_t flags; - if (m_vtables_ap.get()) { - found_it = m_vtables_ap->IsAddressInVTables(curr_pc, flags); + if (m_vtables_up) { + found_it = m_vtables_up->IsAddressInVTables(curr_pc, flags); if (found_it) { this_dispatch.name = "vtable"; this_dispatch.stret_return = @@ -886,11 +888,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - const ABI *abi = NULL; + const ABI *abi = nullptr; ProcessSP process_sp(thread.CalculateProcess()); if (process_sp) abi = process_sp->GetABI().get(); - if (abi == NULL) + if (abi == nullptr) return ret_plan_sp; TargetSP target_sp(thread.CalculateTarget()); @@ -1036,8 +1038,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, isa_addr, sel_addr); } ObjCLanguageRuntime *objc_runtime = - thread.GetProcess()->GetObjCLanguageRuntime(); - assert(objc_runtime != NULL); + ObjCLanguageRuntime::Get(*thread.GetProcess()); + assert(objc_runtime != nullptr); impl_addr = objc_runtime->LookupInMethodCache(isa_addr, sel_addr); } @@ -1049,8 +1051,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, log->Printf("Found implementation address in cache: 0x%" PRIx64, impl_addr); - ret_plan_sp.reset( - new ThreadPlanRunToAddress(thread, impl_addr, stop_others)); + ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, impl_addr, + stop_others); } else { // We haven't seen this class/selector pair yet. Look it up. StreamString errors; @@ -1129,9 +1131,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, // is not safe to run only one thread. So we override the // stop_others value passed in to us here: const bool trampoline_stop_others = false; - ret_plan_sp.reset(new AppleThreadPlanStepThroughObjCTrampoline( + ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughObjCTrampoline>( thread, this, dispatch_values, isa_addr, sel_addr, - trampoline_stop_others)); + trampoline_stop_others); if (log) { StreamString s; ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index fe3390757d080..d120d671eeb3e 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -1,9 +1,8 @@ //===-- AppleObjCTrampolineHandler.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -37,7 +36,7 @@ public: struct DispatchFunction { public: - typedef enum { eFixUpNone, eFixUpFixed, eFixUpToFix } FixUpState; + enum FixUpState { eFixUpNone, eFixUpFixed, eFixUpToFix }; const char *name; bool stret_return; @@ -75,8 +74,9 @@ private: class VTableRegion { public: VTableRegion() - : m_valid(false), m_owner(NULL), m_header_addr(LLDB_INVALID_ADDRESS), - m_code_start_addr(0), m_code_end_addr(0), m_next_region(0) {} + : m_valid(false), m_owner(nullptr), + m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0), + m_code_end_addr(0), m_next_region(0) {} VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); @@ -150,7 +150,7 @@ private: lldb::addr_t m_impl_stret_fn_addr; lldb::addr_t m_msg_forward_addr; lldb::addr_t m_msg_forward_stret_addr; - std::unique_ptr<AppleObjCVTables> m_vtables_ap; + std::unique_ptr<AppleObjCVTables> m_vtables_up; }; } // namespace lldb_private diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 9bb1a4e0ee42b..26654e9212b9b 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -1,9 +1,8 @@ //===-- AppleObjCTypeEncodingParser.cpp -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -24,8 +23,8 @@ using namespace lldb_utility; AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( ObjCLanguageRuntime &runtime) : ObjCLanguageRuntime::EncodingToType(), m_runtime(runtime) { - if (!m_scratch_ast_ctx_ap) - m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess() + if (!m_scratch_ast_ctx_up) + m_scratch_ast_ctx_up.reset(new ClangASTContext(runtime.GetProcess() ->GetTarget() .GetArchitecture() .GetTriple() @@ -246,25 +245,19 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( if (!decl_vendor) return clang::QualType(); - const bool append = false; - const uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; - - uint32_t num_types = - decl_vendor->FindDecls(ConstString(name), append, max_matches, decls); + auto types = decl_vendor->FindTypes(ConstString(name), /*max_matches*/ 1); // The user can forward-declare something that has no definition. The runtime // doesn't prohibit this at all. This is a rare and very weird case. We keep // this assert in debug builds so we catch other weird cases. #ifdef LLDB_CONFIGURATION_DEBUG - assert(num_types); + assert(!types.empty()); #else - if (!num_types) + if (types.empty()) return ast_ctx.getObjCIdType(); #endif - return ClangUtil::GetQualType( - ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); + return ClangUtil::GetQualType(types.front().GetPointerType()); } else { // We're going to resolve this dynamically anyway, so just smile and wave. return ast_ctx.getObjCIdType(); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h index fac564e331653..e576e8f283f20 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h @@ -1,9 +1,8 @@ //===-- AppleObjCTypeEncodingParser.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -12,9 +11,10 @@ #include "clang/AST/ASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + namespace lldb_utility { class StringLexer; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 2b54d0a542d95..d18435c9c6dbc 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -1,32 +1,32 @@ //===-- AppleThreadPlanStepThroughObjCTrampoline.cpp -//--------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "AppleThreadPlanStepThroughObjCTrampoline.h" + #include "AppleObjCTrampolineHandler.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Utility/Log.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + +#include <memory> + using namespace lldb; using namespace lldb_private; -//---------------------------------------------------------------------- // ThreadPlanStepThroughObjCTrampoline constructor -//---------------------------------------------------------------------- AppleThreadPlanStepThroughObjCTrampoline:: AppleThreadPlanStepThroughObjCTrampoline( Thread &thread, AppleObjCTrampolineHandler *trampoline_handler, @@ -37,12 +37,10 @@ AppleThreadPlanStepThroughObjCTrampoline:: eVoteNoOpinion), m_trampoline_handler(trampoline_handler), m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values), - m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(NULL), + m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr), m_stop_others(stop_others) {} -//---------------------------------------------------------------------- // Destructor -//---------------------------------------------------------------------- AppleThreadPlanStepThroughObjCTrampoline:: ~AppleThreadPlanStepThroughObjCTrampoline() {} @@ -174,8 +172,8 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { target_addr); ObjCLanguageRuntime *objc_runtime = - GetThread().GetProcess()->GetObjCLanguageRuntime(); - assert(objc_runtime != NULL); + ObjCLanguageRuntime::Get(*GetThread().GetProcess()); + assert(objc_runtime != nullptr); objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr); if (log) log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 @@ -184,8 +182,8 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { // Extract the target address from the value: - m_run_to_sp.reset( - new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others)); + m_run_to_sp = std::make_shared<ThreadPlanRunToAddress>( + m_thread, target_so_addr, m_stop_others); m_thread.QueueThreadPlan(m_run_to_sp, false); m_run_to_sp->SetPrivate(true); return false; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h index 5758e19f83ca8..96f37851a35fc 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h @@ -1,9 +1,8 @@ //===-- AppleThreadPlanStepThroughObjCTrampoline.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp new file mode 100644 index 0000000000000..631c15c46ce85 --- /dev/null +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -0,0 +1,436 @@ +//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "clang/AST/Type.h" + +#include "ObjCLanguageRuntime.h" + +#include "lldb/Core/MappedHash.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Timer.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DJB.h" + +using namespace lldb; +using namespace lldb_private; + +char ObjCLanguageRuntime::ID = 0; + +// Destructor +ObjCLanguageRuntime::~ObjCLanguageRuntime() {} + +ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process) + : LanguageRuntime(process), m_impl_cache(), + m_has_new_literals_and_indexing(eLazyBoolCalculate), + m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(), + m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(), + m_negative_complete_class_cache() {} + +bool ObjCLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) { + static ConstString g_self = ConstString("self"); + static ConstString g_cmd = ConstString("_cmd"); + return name == g_self || name == g_cmd; +} + +bool ObjCLanguageRuntime::AddClass(ObjCISA isa, + const ClassDescriptorSP &descriptor_sp, + const char *class_name) { + if (isa != 0) { + m_isa_to_descriptor[isa] = descriptor_sp; + // class_name is assumed to be valid + m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa)); + return true; + } + return false; +} + +void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, + lldb::addr_t selector, + lldb::addr_t impl_addr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) { + log->Printf("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 + " implementation 0x%" PRIx64 ".", + class_addr, selector, impl_addr); + } + m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>( + ClassAndSel(class_addr, selector), impl_addr)); +} + +lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr, + lldb::addr_t selector) { + MsgImplMap::iterator pos, end = m_impl_cache.end(); + pos = m_impl_cache.find(ClassAndSel(class_addr, selector)); + if (pos != end) + return (*pos).second; + return LLDB_INVALID_ADDRESS; +} + +lldb::TypeSP +ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { + CompleteClassMap::iterator complete_class_iter = + m_complete_class_cache.find(name); + + if (complete_class_iter != m_complete_class_cache.end()) { + // Check the weak pointer to make sure the type hasn't been unloaded + TypeSP complete_type_sp(complete_class_iter->second.lock()); + + if (complete_type_sp) + return complete_type_sp; + else + m_complete_class_cache.erase(name); + } + + if (m_negative_complete_class_cache.count(name) > 0) + return TypeSP(); + + const ModuleList &modules = m_process->GetTarget().GetImages(); + + SymbolContextList sc_list; + const size_t matching_symbols = + modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + + if (matching_symbols) { + SymbolContext sc; + + sc_list.GetContextAtIndex(0, sc); + + ModuleSP module_sp(sc.module_sp); + + if (!module_sp) + return TypeSP(); + + const bool exact_match = true; + const uint32_t max_matches = UINT32_MAX; + TypeList types; + + llvm::DenseSet<SymbolFile *> searched_symbol_files; + const uint32_t num_types = module_sp->FindTypes( + name, exact_match, max_matches, searched_symbol_files, types); + + if (num_types) { + uint32_t i; + for (i = 0; i < num_types; ++i) { + TypeSP type_sp(types.GetTypeAtIndex(i)); + + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_sp->GetForwardCompilerType())) { + if (type_sp->IsCompleteObjCClass()) { + m_complete_class_cache[name] = type_sp; + return type_sp; + } + } + } + } + } + m_negative_complete_class_cache.insert(name); + return TypeSP(); +} + +size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type, + const char *ivar_name) { + return LLDB_INVALID_IVAR_OFFSET; +} + +bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid( + lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged, + bool check_version_specific) const { + if (!value) + return allow_NULLs; + if ((value % 2) == 1 && allow_tagged) + return true; + if ((value % ptr_size) == 0) + return (check_version_specific ? CheckPointer(value, ptr_size) : true); + else + return false; +} + +ObjCLanguageRuntime::ObjCISA +ObjCLanguageRuntime::GetISA(ConstString name) { + ISAToDescriptorIterator pos = GetDescriptorIterator(name); + if (pos != m_isa_to_descriptor.end()) + return pos->first; + return 0; +} + +ObjCLanguageRuntime::ISAToDescriptorIterator +ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) { + ISAToDescriptorIterator end = m_isa_to_descriptor.end(); + + if (name) { + UpdateISAToDescriptorMap(); + if (m_hash_to_isa_map.empty()) { + // No name hashes were provided, we need to just linearly power through + // the names and find a match + for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin(); + pos != end; ++pos) { + if (pos->second->GetClassName() == name) + return pos; + } + } else { + // Name hashes were provided, so use them to efficiently lookup name to + // isa/descriptor + const uint32_t name_hash = llvm::djbHash(name.GetStringRef()); + std::pair<HashToISAIterator, HashToISAIterator> range = + m_hash_to_isa_map.equal_range(name_hash); + for (HashToISAIterator range_pos = range.first; range_pos != range.second; + ++range_pos) { + ISAToDescriptorIterator pos = + m_isa_to_descriptor.find(range_pos->second); + if (pos != m_isa_to_descriptor.end()) { + if (pos->second->GetClassName() == name) + return pos; + } + } + } + } + return end; +} + +std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, + ObjCLanguageRuntime::ISAToDescriptorIterator> +ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) { + if (update_if_needed) + UpdateISAToDescriptorMapIfNeeded(); + + return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator, + ObjCLanguageRuntime::ISAToDescriptorIterator>( + m_isa_to_descriptor.begin(), m_isa_to_descriptor.end()); +} + +ObjCLanguageRuntime::ObjCISA +ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) { + ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa)); + if (objc_class_sp) { + ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass()); + if (objc_super_class_sp) + return objc_super_class_sp->GetISA(); + } + return 0; +} + +ConstString +ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) { + ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa)); + if (objc_class_sp) + return objc_class_sp->GetClassName(); + return ConstString(); +} + +ObjCLanguageRuntime::ClassDescriptorSP +ObjCLanguageRuntime::GetClassDescriptorFromClassName( + ConstString class_name) { + ISAToDescriptorIterator pos = GetDescriptorIterator(class_name); + if (pos != m_isa_to_descriptor.end()) + return pos->second; + return ClassDescriptorSP(); +} + +ObjCLanguageRuntime::ClassDescriptorSP +ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) { + ClassDescriptorSP objc_class_sp; + // if we get an invalid VO (which might still happen when playing around with + // pointers returned by the expression parser, don't consider this a valid + // ObjC object) + if (valobj.GetCompilerType().IsValid()) { + addr_t isa_pointer = valobj.GetPointerValue(); + if (isa_pointer != LLDB_INVALID_ADDRESS) { + ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); + + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + Status error; + ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); + if (isa != LLDB_INVALID_ADDRESS) + objc_class_sp = GetClassDescriptorFromISA(isa); + } + } + } + return objc_class_sp; +} + +ObjCLanguageRuntime::ClassDescriptorSP +ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) { + ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( + GetClassDescriptor(valobj)); + if (objc_class_sp) { + if (!objc_class_sp->IsKVO()) + return objc_class_sp; + + ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); + if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) + return non_kvo_objc_class_sp; + } + return ClassDescriptorSP(); +} + +ObjCLanguageRuntime::ClassDescriptorSP +ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) { + if (isa) { + UpdateISAToDescriptorMap(); + ObjCLanguageRuntime::ISAToDescriptorIterator pos = + m_isa_to_descriptor.find(isa); + if (pos != m_isa_to_descriptor.end()) + return pos->second; + } + return ClassDescriptorSP(); +} + +ObjCLanguageRuntime::ClassDescriptorSP +ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) { + if (isa) { + ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa); + if (objc_class_sp && objc_class_sp->IsValid()) { + if (!objc_class_sp->IsKVO()) + return objc_class_sp; + + ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass()); + if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid()) + return non_kvo_objc_class_sp; + } + } + return ClassDescriptorSP(); +} + +CompilerType +ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name, + bool for_expression) { + if (m_scratch_ast_ctx_up) + return RealizeType(*m_scratch_ast_ctx_up, name, for_expression); + return CompilerType(); +} + +CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType( + ClangASTContext &ast_ctx, const char *name, bool for_expression) { + clang::ASTContext *clang_ast = ast_ctx.getASTContext(); + if (!clang_ast) + return CompilerType(); + return RealizeType(*clang_ast, name, for_expression); +} + +ObjCLanguageRuntime::EncodingToType::~EncodingToType() {} + +ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() { + return nullptr; +} + +bool ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type, + uint64_t &size) { + void *opaque_ptr = compiler_type.GetOpaqueQualType(); + size = m_type_size_cache.Lookup(opaque_ptr); + // an ObjC object will at least have an ISA, so 0 is definitely not OK + if (size > 0) + return true; + + ClassDescriptorSP class_descriptor_sp = + GetClassDescriptorFromClassName(compiler_type.GetTypeName()); + if (!class_descriptor_sp) + return false; + + int32_t max_offset = INT32_MIN; + uint64_t sizeof_max = 0; + bool found = false; + + for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) { + const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx); + int32_t cur_offset = ivar.m_offset; + if (cur_offset > max_offset) { + max_offset = cur_offset; + sizeof_max = ivar.m_size; + found = true; + } + } + + size = 8 * (max_offset + sizeof_max); + if (found) + m_type_size_cache.Insert(opaque_ptr, size); + + return found; +} + +lldb::BreakpointPreconditionSP +ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language, + bool throw_bp) { + if (language != eLanguageTypeObjC) + return lldb::BreakpointPreconditionSP(); + if (!throw_bp) + return lldb::BreakpointPreconditionSP(); + BreakpointPreconditionSP precondition_sp( + new ObjCLanguageRuntime::ObjCExceptionPrecondition()); + return precondition_sp; +} + +// Exception breakpoint Precondition class for ObjC: +void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName( + const char *class_name) { + m_class_names.insert(class_name); +} + +ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {} + +bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition( + StoppointCallbackContext &context) { + return true; +} + +void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription( + Stream &stream, lldb::DescriptionLevel level) {} + +Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition( + Args &args) { + Status error; + if (args.GetArgumentCount() > 0) + error.SetErrorString( + "The ObjC Exception breakpoint doesn't support extra options."); + return error; +} + +llvm::Optional<CompilerType> +ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { + CompilerType class_type; + bool is_pointer_type = false; + + if (ClangASTContext::IsObjCObjectPointerType(base_type, &class_type)) + is_pointer_type = true; + else if (ClangASTContext::IsObjCObjectOrInterfaceType(base_type)) + class_type = base_type; + else + return llvm::None; + + if (!class_type) + return llvm::None; + + ConstString class_name(class_type.GetConstTypeName()); + if (!class_name) + return llvm::None; + + TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name); + if (!complete_objc_class_type_sp) + return llvm::None; + + CompilerType complete_class( + complete_objc_class_type_sp->GetFullCompilerType()); + if (complete_class.GetCompleteType()) { + if (is_pointer_type) + return complete_class.GetPointerType(); + else + return complete_class; + } + + return llvm::None; +} diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h new file mode 100644 index 0000000000000..1925c78ed3420 --- /dev/null +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h @@ -0,0 +1,429 @@ +//===-- ObjCLanguageRuntime.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ObjCLanguageRuntime_h_ +#define liblldb_ObjCLanguageRuntime_h_ + +#include <functional> +#include <map> +#include <memory> +#include <unordered_set> + +#include "llvm/Support/Casting.h" + +#include "lldb/Breakpoint/BreakpointPrecondition.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/ThreadSafeDenseMap.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" + +class CommandObjectObjC_ClassTable_Dump; + +namespace lldb_private { + +class UtilityFunction; + +class ObjCLanguageRuntime : public LanguageRuntime { +public: + enum class ObjCRuntimeVersions { + eObjC_VersionUnknown = 0, + eAppleObjC_V1 = 1, + eAppleObjC_V2 = 2 + }; + + typedef lldb::addr_t ObjCISA; + + class ClassDescriptor; + typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP; + + // the information that we want to support retrieving from an ObjC class this + // needs to be pure virtual since there are at least 2 different + // implementations of the runtime, and more might come + class ClassDescriptor { + public: + ClassDescriptor() + : m_is_kvo(eLazyBoolCalculate), m_is_cf(eLazyBoolCalculate), + m_type_wp() {} + + virtual ~ClassDescriptor() = default; + + virtual ConstString GetClassName() = 0; + + virtual ClassDescriptorSP GetSuperclass() = 0; + + virtual ClassDescriptorSP GetMetaclass() const = 0; + + // virtual if any implementation has some other version-specific rules but + // for the known v1/v2 this is all that needs to be done + virtual bool IsKVO() { + if (m_is_kvo == eLazyBoolCalculate) { + const char *class_name = GetClassName().AsCString(); + if (class_name && *class_name) + m_is_kvo = + (LazyBool)(strstr(class_name, "NSKVONotifying_") == class_name); + } + return (m_is_kvo == eLazyBoolYes); + } + + // virtual if any implementation has some other version-specific rules but + // for the known v1/v2 this is all that needs to be done + virtual bool IsCFType() { + if (m_is_cf == eLazyBoolCalculate) { + const char *class_name = GetClassName().AsCString(); + if (class_name && *class_name) + m_is_cf = (LazyBool)(strcmp(class_name, "__NSCFType") == 0 || + strcmp(class_name, "NSCFType") == 0); + } + return (m_is_cf == eLazyBoolYes); + } + + virtual bool IsValid() = 0; + + virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr, + uint64_t *value_bits = nullptr, + uint64_t *payload = nullptr) = 0; + + virtual uint64_t GetInstanceSize() = 0; + + // use to implement version-specific additional constraints on pointers + virtual bool CheckPointer(lldb::addr_t value, uint32_t ptr_size) const { + return true; + } + + virtual ObjCISA GetISA() = 0; + + // This should return true iff the interface could be completed + virtual bool + Describe(std::function<void(ObjCISA)> const &superclass_func, + std::function<bool(const char *, const char *)> const + &instance_method_func, + std::function<bool(const char *, const char *)> const + &class_method_func, + std::function<bool(const char *, const char *, lldb::addr_t, + uint64_t)> const &ivar_func) const { + return false; + } + + lldb::TypeSP GetType() { return m_type_wp.lock(); } + + void SetType(const lldb::TypeSP &type_sp) { m_type_wp = type_sp; } + + struct iVarDescriptor { + ConstString m_name; + CompilerType m_type; + uint64_t m_size; + int32_t m_offset; + }; + + virtual size_t GetNumIVars() { return 0; } + + virtual iVarDescriptor GetIVarAtIndex(size_t idx) { + return iVarDescriptor(); + } + + protected: + bool IsPointerValid(lldb::addr_t value, uint32_t ptr_size, + bool allow_NULLs = false, bool allow_tagged = false, + bool check_version_specific = false) const; + + private: + LazyBool m_is_kvo; + LazyBool m_is_cf; + lldb::TypeWP m_type_wp; + }; + + class EncodingToType { + public: + virtual ~EncodingToType(); + + virtual CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name, + bool for_expression); + virtual CompilerType RealizeType(const char *name, bool for_expression); + + virtual CompilerType RealizeType(clang::ASTContext &ast_ctx, + const char *name, bool for_expression) = 0; + + protected: + std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_up; + }; + + class ObjCExceptionPrecondition : public BreakpointPrecondition { + public: + ObjCExceptionPrecondition(); + + ~ObjCExceptionPrecondition() override = default; + + bool EvaluatePrecondition(StoppointCallbackContext &context) override; + void GetDescription(Stream &stream, lldb::DescriptionLevel level) override; + Status ConfigurePrecondition(Args &args) override; + + protected: + void AddClassName(const char *class_name); + + private: + std::unordered_set<std::string> m_class_names; + }; + + static lldb::BreakpointPreconditionSP + GetBreakpointExceptionPrecondition(lldb::LanguageType language, + bool throw_bp); + + class TaggedPointerVendor { + public: + virtual ~TaggedPointerVendor() = default; + + virtual bool IsPossibleTaggedPointer(lldb::addr_t ptr) = 0; + + virtual ObjCLanguageRuntime::ClassDescriptorSP + GetClassDescriptor(lldb::addr_t ptr) = 0; + + protected: + TaggedPointerVendor() = default; + + private: + DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor); + }; + + ~ObjCLanguageRuntime() override; + + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || LanguageRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); + } + + static ObjCLanguageRuntime *Get(Process &process) { + return llvm::cast_or_null<ObjCLanguageRuntime>( + process.GetLanguageRuntime(lldb::eLanguageTypeObjC)); + } + + virtual TaggedPointerVendor *GetTaggedPointerVendor() { return nullptr; } + + typedef std::shared_ptr<EncodingToType> EncodingToTypeSP; + + virtual EncodingToTypeSP GetEncodingToType(); + + virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value); + + ClassDescriptorSP GetNonKVOClassDescriptor(ValueObject &in_value); + + virtual ClassDescriptorSP + GetClassDescriptorFromClassName(ConstString class_name); + + virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa); + + ClassDescriptorSP GetNonKVOClassDescriptor(ObjCISA isa); + + lldb::LanguageType GetLanguageType() const override { + return lldb::eLanguageTypeObjC; + } + + virtual bool IsModuleObjCLibrary(const lldb::ModuleSP &module_sp) = 0; + + virtual bool ReadObjCLibrary(const lldb::ModuleSP &module_sp) = 0; + + virtual bool HasReadObjCLibrary() = 0; + + lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, lldb::addr_t sel); + + void AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t sel, + lldb::addr_t impl_addr); + + TypeAndOrName LookupInClassNameCache(lldb::addr_t class_addr); + + void AddToClassNameCache(lldb::addr_t class_addr, const char *name, + lldb::TypeSP type_sp); + + void AddToClassNameCache(lldb::addr_t class_addr, + const TypeAndOrName &class_or_type_name); + + lldb::TypeSP LookupInCompleteClassCache(ConstString &name); + + llvm::Optional<CompilerType> GetRuntimeType(CompilerType base_type) override; + + virtual UtilityFunction *CreateObjectChecker(const char *) = 0; + + virtual ObjCRuntimeVersions GetRuntimeVersion() const { + return ObjCRuntimeVersions::eObjC_VersionUnknown; + } + + bool IsValidISA(ObjCISA isa) { + UpdateISAToDescriptorMap(); + return m_isa_to_descriptor.count(isa) > 0; + } + + virtual void UpdateISAToDescriptorMapIfNeeded() = 0; + + void UpdateISAToDescriptorMap() { + if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id) { + UpdateISAToDescriptorMapIfNeeded(); + } + } + + virtual ObjCISA GetISA(ConstString name); + + virtual ConstString GetActualTypeName(ObjCISA isa); + + virtual ObjCISA GetParentClass(ObjCISA isa); + + // Finds the byte offset of the child_type ivar in parent_type. If it can't + // find the offset, returns LLDB_INVALID_IVAR_OFFSET. + + virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, + const char *ivar_name); + + bool HasNewLiteralsAndIndexing() { + if (m_has_new_literals_and_indexing == eLazyBoolCalculate) { + if (CalculateHasNewLiteralsAndIndexing()) + m_has_new_literals_and_indexing = eLazyBoolYes; + else + m_has_new_literals_and_indexing = eLazyBoolNo; + } + + return (m_has_new_literals_and_indexing == eLazyBoolYes); + } + + void SymbolsDidLoad(const ModuleList &module_list) override { + m_negative_complete_class_cache.clear(); + } + + bool GetTypeBitSize(const CompilerType &compiler_type, + uint64_t &size) override; + + /// Check whether the name is "self" or "_cmd" and should show up in + /// "frame variable". + bool IsWhitelistedRuntimeValue(ConstString name) override; + +protected: + // Classes that inherit from ObjCLanguageRuntime can see and modify these + ObjCLanguageRuntime(Process *process); + + virtual bool CalculateHasNewLiteralsAndIndexing() { return false; } + + bool ISAIsCached(ObjCISA isa) const { + return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end(); + } + + bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp) { + if (isa != 0) { + m_isa_to_descriptor[isa] = descriptor_sp; + return true; + } + return false; + } + + bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, + const char *class_name); + + bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, + uint32_t class_name_hash) { + if (isa != 0) { + m_isa_to_descriptor[isa] = descriptor_sp; + m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa)); + return true; + } + return false; + } + +private: + // We keep a map of <Class,Selector>->Implementation so we don't have to call + // the resolver function over and over. + + // FIXME: We need to watch for the loading of Protocols, and flush the cache + // for any + // class that we see so changed. + + struct ClassAndSel { + ClassAndSel() { + sel_addr = LLDB_INVALID_ADDRESS; + class_addr = LLDB_INVALID_ADDRESS; + } + + ClassAndSel(lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) + : class_addr(in_class_addr), sel_addr(in_sel_addr) {} + + bool operator==(const ClassAndSel &rhs) { + if (class_addr == rhs.class_addr && sel_addr == rhs.sel_addr) + return true; + else + return false; + } + + bool operator<(const ClassAndSel &rhs) const { + if (class_addr < rhs.class_addr) + return true; + else if (class_addr > rhs.class_addr) + return false; + else { + if (sel_addr < rhs.sel_addr) + return true; + else + return false; + } + } + + lldb::addr_t class_addr; + lldb::addr_t sel_addr; + }; + + typedef std::map<ClassAndSel, lldb::addr_t> MsgImplMap; + typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; + typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; + typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; + typedef HashToISAMap::iterator HashToISAIterator; + typedef ThreadSafeDenseMap<void *, uint64_t> TypeSizeCache; + + MsgImplMap m_impl_cache; + LazyBool m_has_new_literals_and_indexing; + ISAToDescriptorMap m_isa_to_descriptor; + HashToISAMap m_hash_to_isa_map; + TypeSizeCache m_type_size_cache; + +protected: + uint32_t m_isa_to_descriptor_stop_id; + + typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; + CompleteClassMap m_complete_class_cache; + + struct ConstStringSetHelpers { + size_t operator()(ConstString arg) const // for hashing + { + return (size_t)arg.GetCString(); + } + bool operator()(ConstString arg1, + ConstString arg2) const // for equality + { + return arg1.operator==(arg2); + } + }; + typedef std::unordered_set<ConstString, ConstStringSetHelpers, + ConstStringSetHelpers> + CompleteClassSet; + CompleteClassSet m_negative_complete_class_cache; + + ISAToDescriptorIterator GetDescriptorIterator(ConstString name); + + friend class ::CommandObjectObjC_ClassTable_Dump; + + std::pair<ISAToDescriptorIterator, ISAToDescriptorIterator> + GetDescriptorIteratorPair(bool update_if_needed = true); + + void ReadObjCLibraryIfNeeded(const ModuleList &module_list); + + DISALLOW_COPY_AND_ASSIGN(ObjCLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjCLanguageRuntime_h_ diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 2c12cf9af6370..60549663db66e 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -1,9 +1,8 @@ //===-- RenderScriptExpressionOpts.cpp --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h index 647558171d1c6..3ec4e37b6db04 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h @@ -1,9 +1,8 @@ //===-- RenderScriptExpressionOpts.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -35,7 +34,7 @@ public: RenderScriptRuntimeModulePass(const lldb_private::Process *process) : ModulePass(ID), m_process_ptr(process) {} - bool runOnModule(llvm::Module &module); + bool runOnModule(llvm::Module &module) override; private: const lldb_private::Process *m_process_ptr; diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index fa775d9bfa94a..c9cd34cf379d0 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -1,14 +1,11 @@ //===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringSwitch.h" - #include "RenderScriptRuntime.h" #include "RenderScriptScriptGroup.h" @@ -41,12 +38,18 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Status.h" +#include "llvm/ADT/StringSwitch.h" + +#include <memory> + using namespace lldb; using namespace lldb_private; using namespace lldb_renderscript; #define FMT_COORD "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")" +char RenderScriptRuntime::ID = 0; + namespace { // The empirical_type adds a basic level of validation to arbitrary data @@ -591,7 +594,7 @@ struct RenderScriptRuntime::Element { array_size; // Number of items in array, only needed for structs ConstString type_name; // Name of type, only needed for structs - static const ConstString & + static ConstString GetFallbackStructName(); // Print this as the type name of a struct Element // If we can't resolve the actual struct name @@ -691,7 +694,7 @@ struct RenderScriptRuntime::AllocationDetails { } }; -const ConstString &RenderScriptRuntime::Element::GetFallbackStructName() { +ConstString RenderScriptRuntime::Element::GetFallbackStructName() { static const ConstString FallbackStructName("struct"); return FallbackStructName; } @@ -789,9 +792,7 @@ const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = { // RS_TYPE_MATRIX_2X2 {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4}}; -//------------------------------------------------------------------ // Static Functions -//------------------------------------------------------------------ LanguageRuntime * RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language) { @@ -1029,17 +1030,13 @@ void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) { } } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ lldb_private::ConstString RenderScriptRuntime::GetPluginName() { return GetPluginNameStatic(); } uint32_t RenderScriptRuntime::GetPluginVersion() { return 1; } -bool RenderScriptRuntime::IsVTableName(const char *name) { return false; } - bool RenderScriptRuntime::GetDynamicTypeAndAddress( ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, @@ -1126,9 +1123,9 @@ bool RenderScriptRuntime::HookCallback(void *baton, RuntimeHook *hook = (RuntimeHook *)baton; ExecutionContext exe_ctx(ctx->exe_ctx_ref); - RenderScriptRuntime *lang_rt = - (RenderScriptRuntime *)exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *lang_rt = llvm::cast<RenderScriptRuntime>( + exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); lang_rt->HookCallback(hook, exe_ctx); @@ -1212,7 +1209,7 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( } } if (!group) { - group.reset(new RSScriptGroupDescriptor); + group = std::make_shared<RSScriptGroupDescriptor>(); group->m_name = group_name; m_scriptGroups.push_back(group); } else { @@ -1501,9 +1498,9 @@ void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) { - auto &allocation_ap = *iter; // get the unique pointer - if (allocation_ap->address.isValid() && - *allocation_ap->address.get() == addr_t(args[eRsAlloc])) { + auto &allocation_up = *iter; // get the unique pointer + if (allocation_up->address.isValid() && + *allocation_up->address.get() == addr_t(args[eRsAlloc])) { m_allocations.erase(iter); if (log) log->Printf("%s - deleted allocation entry.", __FUNCTION__); @@ -1975,8 +1972,8 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, // We want 4 elements from packed data const uint32_t num_exprs = 4; - assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && - "Invalid number of expressions"); + static_assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1), + "Invalid number of expressions"); char expr_bufs[num_exprs][jit_max_expr_size]; uint64_t results[num_exprs]; @@ -2034,8 +2031,8 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, // We want 4 elements from packed data const uint32_t num_exprs = 4; - assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && - "Invalid number of expressions"); + static_assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1), + "Invalid number of expressions"); char expr_bufs[num_exprs][jit_max_expr_size]; uint64_t results[num_exprs]; @@ -2093,8 +2090,8 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, } const short num_exprs = 3; - assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && - "Invalid number of expressions"); + static_assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1), + "Invalid number of expressions"); char expr_buffer[jit_max_expr_size]; uint64_t results; @@ -2362,7 +2359,7 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem, size_diff); for (uint32_t i = 0; i < size_diff; ++i) { - const ConstString &name = elem.children[num_children + i].type_name; + ConstString name = elem.children[num_children + i].type_name; if (strcmp(name.AsCString(), "#rs_padding") < 0) found = false; } @@ -2855,7 +2852,7 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { switch (GetModuleKind(module_sp)) { case eModuleKindKernelObj: { RSModuleDescriptorSP module_desc; - module_desc.reset(new RSModuleDescriptor(module_sp)); + module_desc = std::make_shared<RSModuleDescriptor>(module_sp); if (module_desc->ParseRSInfo()) { m_rsmodules.push_back(module_desc); module_desc->WarnIfVersionMismatch(GetProcess() @@ -3593,7 +3590,7 @@ void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) { // Given the name of a kernel this function creates a breakpoint using our own // breakpoint resolver, and returns the Breakpoint shared pointer. BreakpointSP -RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) { +RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); @@ -3621,7 +3618,7 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) { } BreakpointSP -RenderScriptRuntime::CreateReductionBreakpoint(const ConstString &name, +RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, int kernel_types) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); @@ -3862,7 +3859,7 @@ bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target, } BreakpointSP -RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name, +RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, bool stop_on_all) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); @@ -3892,7 +3889,7 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name, bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target, Stream &strm, - const ConstString &name, + ConstString name, bool multi) { InitSearchFilter(target); BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi); @@ -4125,9 +4122,9 @@ public: ~CommandObjectRenderScriptRuntimeModuleDump() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); runtime->DumpModules(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -4160,9 +4157,9 @@ public: ~CommandObjectRenderScriptRuntimeKernelList() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); runtime->DumpKernels(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -4407,9 +4404,9 @@ public: return false; } - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); auto &outstream = result.GetOutputStream(); auto &target = m_exe_ctx.GetTargetSP(); @@ -4591,9 +4588,9 @@ public: ~CommandObjectRenderScriptRuntimeContextDump() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); runtime->DumpContexts(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -4983,9 +4980,9 @@ public: ~CommandObjectRenderScriptRuntimeStatus() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( - eLanguageTypeExtRenderScript); + RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( + eLanguageTypeExtRenderScript)); runtime->DumpStatus(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 31714dd4a4539..3923221d4302c 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -1,9 +1,8 @@ //===-- RenderScriptRuntime.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -20,10 +19,11 @@ #include "llvm/ADT/StringRef.h" #include "lldb/Core/Module.h" #include "lldb/Expression/LLVMUserExpression.h" -#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/lldb-private.h" +#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" + namespace lldb_private { namespace lldb_renderscript { @@ -246,7 +246,7 @@ typedef std::vector<RSScriptGroupDescriptorSP> RSScriptGroupList; class RSScriptGroupBreakpointResolver : public BreakpointResolver { public: - RSScriptGroupBreakpointResolver(Breakpoint *bp, const ConstString &name, + RSScriptGroupBreakpointResolver(Breakpoint *bp, ConstString name, const RSScriptGroupList &groups, bool stop_on_all) : BreakpointResolver(bp, BreakpointResolver::NameResolver), @@ -276,7 +276,7 @@ public: protected: const RSScriptGroupDescriptorSP - FindScriptGroup(const ConstString &name) const { + FindScriptGroup(ConstString name) const { for (auto sg : m_script_groups) { if (ConstString::Compare(sg->m_name, name) == 0) return sg; @@ -302,9 +302,7 @@ public: ~RenderScriptRuntime() override; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -317,6 +315,16 @@ public: static lldb_private::ConstString GetPluginNameStatic(); + static char ID; + + bool isA(const void *ClassID) const override { + return ClassID == &ID || CPPLanguageRuntime::isA(ClassID); + } + + static bool classof(const LanguageRuntime *runtime) { + return runtime->isA(&ID); + } + static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp); static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp); @@ -324,8 +332,6 @@ public: static void ModulesDidLoad(const lldb::ProcessSP &process_sp, const ModuleList &module_list); - bool IsVTableName(const char *name) override; - bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, @@ -366,7 +372,7 @@ public: int kernel_types = ~(0)); bool PlaceBreakpointOnScriptGroup(lldb::TargetSP target, Stream &strm, - const ConstString &name, bool stop_on_all); + ConstString name, bool stop_on_all); void SetBreakAllKernels(bool do_break, lldb::TargetSP target); @@ -388,7 +394,7 @@ public: return m_scriptGroups; }; - bool IsKnownKernel(const ConstString &name) { + bool IsKnownKernel(ConstString name) { for (const auto &module : m_rsmodules) for (const auto &kernel : module->m_kernels) if (kernel.m_name == name) @@ -396,9 +402,7 @@ public: return false; } - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -429,12 +433,12 @@ protected: bool EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result); - lldb::BreakpointSP CreateScriptGroupBreakpoint(const ConstString &name, + lldb::BreakpointSP CreateScriptGroupBreakpoint(ConstString name, bool multi); - lldb::BreakpointSP CreateKernelBreakpoint(const ConstString &name); + lldb::BreakpointSP CreateKernelBreakpoint(ConstString name); - lldb::BreakpointSP CreateReductionBreakpoint(const ConstString &name, + lldb::BreakpointSP CreateReductionBreakpoint(ConstString name, int kernel_types); void BreakOnModuleKernels( diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp index 7786d686ad6a2..45d0d028d0474 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp @@ -1,9 +1,8 @@ //===-- RenderScriptScriptGroup.cpp -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h index 5c5608c998620..c25e240f6d527 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.h @@ -1,9 +1,8 @@ //===-- RenderScriptScriptGroup.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp index 0b298c90a50b1..4725e8c5b0eb6 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp @@ -1,9 +1,8 @@ //===-- RenderScriptx86ABIFixups.cpp ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -193,8 +192,9 @@ bool fixupX86StructRetCalls(llvm::Module &module) { llvm::LoadInst *new_func_addr_load = new llvm::LoadInst(new_func_ptr, "load_func_pointer", call_inst); // and create a callinstruction from it - llvm::CallInst *new_call_inst = llvm::CallInst::Create( - new_func_addr_load, new_call_args, "new_func_call", call_inst); + llvm::CallInst *new_call_inst = + llvm::CallInst::Create(new_func_type, new_func_addr_load, new_call_args, + "new_func_call", call_inst); new_call_inst->setCallingConv(call_inst->getCallingConv()); new_call_inst->setTailCall(call_inst->isTailCall()); llvm::LoadInst *lldb_save_result_address = diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h index b2caea49bd1e1..a5efc999aea4e 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h @@ -1,9 +1,8 @@ //===-- RenderScriptx86ABIFixups.h ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// |