From 14f1b3e8826ce43b978db93a62d1166055db5394 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 2 Jan 2017 19:26:05 +0000 Subject: Vendor import of lldb trunk r290819: https://llvm.org/svn/llvm-project/lldb/trunk@290819 --- .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 975 ++++++++++----------- .../ItaniumABI/ItaniumABILanguageRuntime.h | 192 ++-- 2 files changed, 552 insertions(+), 615 deletions(-) (limited to 'source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI') diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index c49feb07200e..ddfbd864e92c 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -1,4 +1,5 @@ -//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===// +//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- +//C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -40,579 +41,533 @@ using namespace lldb_private; static const char *vtable_demangled_prefix = "vtable for "; -bool -ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) -{ - const bool check_cxx = true; - const bool check_objc = false; - return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc); +bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) { + const bool check_cxx = true; + const bool check_objc = false; + return in_value.GetCompilerType().IsPossibleDynamicType(NULL, check_cxx, + check_objc); } -TypeAndOrName -ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, - lldb::addr_t vtable_load_addr) -{ - if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) - { - // Find the symbol that contains the "vtable_load_addr" address - Address vtable_addr; - Target &target = m_process->GetTarget(); - if (!target.GetSectionLoadList().IsEmpty()) - { - if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, vtable_addr)) - { - // See if we have cached info for this type already - TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr); - if (type_info) - return type_info; - - SymbolContext sc; - target.GetImages().ResolveSymbolContextForAddress(vtable_addr, eSymbolContextSymbol, sc); - Symbol *symbol = sc.symbol; - if (symbol != NULL) - { - const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString(); - if (name && strstr(name, vtable_demangled_prefix) == name) - { - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n", - original_ptr, - in_value.GetTypeName().GetCString(), - name); - // We are a C++ class, that's good. Get the class name and look it up: - const char *class_name = name + strlen(vtable_demangled_prefix); - type_info.SetName(class_name); - const bool exact_match = true; - TypeList class_types; - - uint32_t num_matches = 0; - // First look in the module that the vtable symbol came from - // and look for a single exact match. - llvm::DenseSet searched_symbol_files; - if (sc.module_sp) - { - num_matches = sc.module_sp->FindTypes (sc, - ConstString(class_name), - exact_match, - 1, - searched_symbol_files, - class_types); - } - - // If we didn't find a symbol, then move on to the entire - // module list in the target and get as many unique matches - // as possible - if (num_matches == 0) - { - num_matches = target.GetImages().FindTypes(sc, ConstString(class_name), exact_match, - UINT32_MAX, searched_symbol_files, class_types); - } - - lldb::TypeSP type_sp; - if (num_matches == 0) - { - if (log) - log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr); - return TypeAndOrName(); - } - if (num_matches == 1) - { - type_sp = class_types.GetTypeAtIndex(0); - if (type_sp) - { - if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType())) - { - if (log) - log->Printf("0x%16.16" PRIx64 - ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(), - type_sp->GetName().GetCString()); - type_info.SetTypeSP(type_sp); - } - } - } - else if (num_matches > 1) - { - size_t i; - if (log) - { - for (i = 0; i < num_matches; i++) - { - type_sp = class_types.GetTypeAtIndex(i); - if (type_sp) - { - if (log) - log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, - in_value.GetTypeName().AsCString(), - type_sp->GetID(), - type_sp->GetName().GetCString()); - } - } - } - - for (i = 0; i < num_matches; i++) - { - type_sp = class_types.GetTypeAtIndex(i); - if (type_sp) - { - if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType())) - { - if (log) - log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, - in_value.GetTypeName().AsCString(), - type_sp->GetID(), - type_sp->GetName().GetCString()); - type_info.SetTypeSP(type_sp); - } - } - } - - if (log && i == num_matches) - { - log->Printf("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic " - "types, didn't find a C++ match\n", - original_ptr, in_value.GetTypeName().AsCString()); - } - } - if (type_info) - SetDynamicTypeInfo(vtable_addr, type_info); - return type_info; - } +TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( + ValueObject &in_value, lldb::addr_t original_ptr, + lldb::addr_t vtable_load_addr) { + if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) { + // Find the symbol that contains the "vtable_load_addr" address + Address vtable_addr; + Target &target = m_process->GetTarget(); + if (!target.GetSectionLoadList().IsEmpty()) { + if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, + vtable_addr)) { + // See if we have cached info for this type already + TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr); + if (type_info) + return type_info; + + SymbolContext sc; + target.GetImages().ResolveSymbolContextForAddress( + vtable_addr, eSymbolContextSymbol, sc); + Symbol *symbol = sc.symbol; + if (symbol != NULL) { + const char *name = + symbol->GetMangled() + .GetDemangledName(lldb::eLanguageTypeC_plus_plus) + .AsCString(); + if (name && strstr(name, vtable_demangled_prefix) == name) { + Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("0x%16.16" PRIx64 + ": static-type = '%s' has vtable symbol '%s'\n", + original_ptr, in_value.GetTypeName().GetCString(), + name); + // We are a C++ class, that's good. Get the class name and look it + // up: + const char *class_name = name + strlen(vtable_demangled_prefix); + type_info.SetName(class_name); + const bool exact_match = true; + TypeList class_types; + + uint32_t num_matches = 0; + // First look in the module that the vtable symbol came from + // and look for a single exact match. + llvm::DenseSet searched_symbol_files; + if (sc.module_sp) { + num_matches = sc.module_sp->FindTypes( + sc, ConstString(class_name), exact_match, 1, + searched_symbol_files, class_types); + } + + // If we didn't find a symbol, then move on to the entire + // module list in the target and get as many unique matches + // as possible + if (num_matches == 0) { + num_matches = target.GetImages().FindTypes( + sc, ConstString(class_name), exact_match, UINT32_MAX, + searched_symbol_files, class_types); + } + + lldb::TypeSP type_sp; + if (num_matches == 0) { + if (log) + log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", + original_ptr); + return TypeAndOrName(); + } + if (num_matches == 1) { + type_sp = class_types.GetTypeAtIndex(0); + if (type_sp) { + if (ClangASTContext::IsCXXClassType( + type_sp->GetForwardCompilerType())) { + if (log) + log->Printf( + "0x%16.16" PRIx64 + ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 + "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); + type_info.SetTypeSP(type_sp); + } + } + } else if (num_matches > 1) { + size_t i; + if (log) { + for (i = 0; i < num_matches; i++) { + type_sp = class_types.GetTypeAtIndex(i); + if (type_sp) { + if (log) + log->Printf( + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types: uid={0x%" PRIx64 "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); + } } + } + + for (i = 0; i < num_matches; i++) { + type_sp = class_types.GetTypeAtIndex(i); + if (type_sp) { + if (ClangASTContext::IsCXXClassType( + type_sp->GetForwardCompilerType())) { + if (log) + log->Printf( + "0x%16.16" PRIx64 ": static-type = '%s' has multiple " + "matching dynamic types, picking " + "this one: uid={0x%" PRIx64 + "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); + type_info.SetTypeSP(type_sp); + } + } + } + + if (log && i == num_matches) { + log->Printf( + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types, didn't find a C++ match\n", + original_ptr, in_value.GetTypeName().AsCString()); + } } + if (type_info) + SetDynamicTypeInfo(vtable_addr, type_info); + return type_info; + } } + } } - return TypeAndOrName(); + } + return TypeAndOrName(); } -bool -ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, - TypeAndOrName &class_type_or_name, Address &dynamic_address, - Value::ValueType &value_type) -{ - // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0 - // in the object. That will point to the "address point" within the vtable (not the beginning of the - // vtable.) We can then look up the symbol containing this "address point" and that symbol's name - // demangled will contain the full class name. - // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the - // start of the value object which holds the dynamic type. - // - - class_type_or_name.Clear(); - value_type = Value::ValueType::eValueTypeScalar; - - // Only a pointer or reference type can have a different dynamic and static type: - if (CouldHaveDynamicValue(in_value)) - { - // First job, pull out the address at 0 offset from the object. - AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); - if (original_ptr == LLDB_INVALID_ADDRESS) - return false; - - ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == nullptr) - return false; - - Error error; - const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error); - - if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) - { - return false; - } +bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( + ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &dynamic_address, + Value::ValueType &value_type) { + // For Itanium, if the type has a vtable pointer in the object, it will be at + // offset 0 + // in the object. That will point to the "address point" within the vtable + // (not the beginning of the + // vtable.) We can then look up the symbol containing this "address point" + // and that symbol's name + // demangled will contain the full class name. + // The second pointer above the "address point" is the "offset_to_top". We'll + // use that to get the + // start of the value object which holds the dynamic type. + // + + class_type_or_name.Clear(); + value_type = Value::ValueType::eValueTypeScalar; + + // Only a pointer or reference type can have a different dynamic and static + // type: + if (CouldHaveDynamicValue(in_value)) { + // First job, pull out the address at 0 offset from the object. + AddressType address_type; + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); + if (original_ptr == LLDB_INVALID_ADDRESS) + return false; + + ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == nullptr) + return false; + + Error error; + const lldb::addr_t vtable_address_point = + process->ReadPointerFromMemory(original_ptr, error); + + if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) { + return false; + } - class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point); - - if (class_type_or_name) - { - TypeSP type_sp = class_type_or_name.GetTypeSP(); - // 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 (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType())) - { - // The dynamic type we found was the same type, - // so we don't have a dynamic type here... - return false; - } + class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, + vtable_address_point); + + if (class_type_or_name) { + TypeSP type_sp = class_type_or_name.GetTypeSP(); + // 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 (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), + type_sp->GetForwardCompilerType())) { + // The dynamic type we found was the same type, + // so we don't have a dynamic type here... + return false; + } - // The offset_to_top is two pointers above the vtable pointer. - const uint32_t addr_byte_size = process->GetAddressByteSize(); - const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size; - // Watch for underflow, offset_to_top_location should be less than vtable_address_point - if (offset_to_top_location >= vtable_address_point) - return false; - const int64_t offset_to_top = - process->ReadSignedIntegerFromMemory(offset_to_top_location, addr_byte_size, INT64_MIN, error); - - if (offset_to_top == INT64_MIN) - return false; - // So the dynamic type is a value that starts at offset_to_top - // above the original address. - lldb::addr_t dynamic_addr = original_ptr + offset_to_top; - if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(dynamic_addr, dynamic_address)) - { - dynamic_address.SetRawAddress(dynamic_addr); - } - return true; - } + // The offset_to_top is two pointers above the vtable pointer. + const uint32_t addr_byte_size = process->GetAddressByteSize(); + const lldb::addr_t offset_to_top_location = + vtable_address_point - 2 * addr_byte_size; + // Watch for underflow, offset_to_top_location should be less than + // vtable_address_point + if (offset_to_top_location >= vtable_address_point) + return false; + const int64_t offset_to_top = process->ReadSignedIntegerFromMemory( + offset_to_top_location, addr_byte_size, INT64_MIN, error); + + if (offset_to_top == INT64_MIN) + return false; + // So the dynamic type is a value that starts at offset_to_top + // above the original address. + lldb::addr_t dynamic_addr = original_ptr + offset_to_top; + if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress( + dynamic_addr, dynamic_address)) { + dynamic_address.SetRawAddress(dynamic_addr); } + return true; + } } + } - return class_type_or_name.IsEmpty() == false; + return class_type_or_name.IsEmpty() == false; } -TypeAndOrName -ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name, - ValueObject& static_value) -{ - CompilerType static_type(static_value.GetCompilerType()); - Flags static_type_flags(static_type.GetTypeInfo()); - - TypeAndOrName ret(type_and_or_name); - if (type_and_or_name.HasType()) - { - // The type will always be the type of the dynamic object. If our parent's type was a pointer, - // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type - // should be okay... - CompilerType orig_type = type_and_or_name.GetCompilerType(); - CompilerType corrected_type = orig_type; - if (static_type_flags.AllSet(eTypeIsPointer)) - corrected_type = orig_type.GetPointerType (); - else if (static_type_flags.AllSet(eTypeIsReference)) - corrected_type = orig_type.GetLValueReferenceType(); - ret.SetCompilerType(corrected_type); - } - else - { - // If we are here we need to adjust our dynamic type name to include the correct & or * symbol - std::string corrected_name (type_and_or_name.GetName().GetCString()); - if (static_type_flags.AllSet(eTypeIsPointer)) - corrected_name.append(" *"); - else if (static_type_flags.AllSet(eTypeIsReference)) - corrected_name.append(" &"); - // the parent type should be a correctly pointer'ed or referenc'ed type - ret.SetCompilerType(static_type); - ret.SetName(corrected_name.c_str()); - } - return ret; +TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType( + const TypeAndOrName &type_and_or_name, ValueObject &static_value) { + CompilerType static_type(static_value.GetCompilerType()); + Flags static_type_flags(static_type.GetTypeInfo()); + + TypeAndOrName ret(type_and_or_name); + if (type_and_or_name.HasType()) { + // The type will always be the type of the dynamic object. If our parent's + // type was a pointer, + // then our type should be a pointer to the type of the dynamic object. If + // a reference, then the original type + // should be okay... + CompilerType orig_type = type_and_or_name.GetCompilerType(); + CompilerType corrected_type = orig_type; + if (static_type_flags.AllSet(eTypeIsPointer)) + corrected_type = orig_type.GetPointerType(); + else if (static_type_flags.AllSet(eTypeIsReference)) + corrected_type = orig_type.GetLValueReferenceType(); + ret.SetCompilerType(corrected_type); + } else { + // If we are here we need to adjust our dynamic type name to include the + // correct & or * symbol + std::string corrected_name(type_and_or_name.GetName().GetCString()); + if (static_type_flags.AllSet(eTypeIsPointer)) + corrected_name.append(" *"); + else if (static_type_flags.AllSet(eTypeIsReference)) + corrected_name.append(" &"); + // the parent type should be a correctly pointer'ed or referenc'ed type + ret.SetCompilerType(static_type); + ret.SetName(corrected_name.c_str()); + } + return ret; } -bool -ItaniumABILanguageRuntime::IsVTableName (const char *name) -{ - if (name == NULL) - return false; - - // Can we maybe ask Clang about this? - if (strstr (name, "_vptr$") == name) - return true; - else - return false; +bool ItaniumABILanguageRuntime::IsVTableName(const char *name) { + if (name == NULL) + return false; + + // Can we maybe ask Clang about this? + if (strstr(name, "_vptr$") == name) + return true; + else + return false; } //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ LanguageRuntime * -ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) -{ - // FIXME: We have to check the process and make sure we actually know that this process supports - // the Itanium ABI. - if (language == eLanguageTypeC_plus_plus || - language == eLanguageTypeC_plus_plus_03 || - language == eLanguageTypeC_plus_plus_11 || - language == eLanguageTypeC_plus_plus_14) - return new ItaniumABILanguageRuntime (process); - else - return NULL; +ItaniumABILanguageRuntime::CreateInstance(Process *process, + lldb::LanguageType language) { + // FIXME: We have to check the process and make sure we actually know that + // this process supports + // the Itanium ABI. + if (language == eLanguageTypeC_plus_plus || + language == eLanguageTypeC_plus_plus_03 || + language == eLanguageTypeC_plus_plus_11 || + language == eLanguageTypeC_plus_plus_14) + return new ItaniumABILanguageRuntime(process); + else + return NULL; } -class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed -{ +class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed { public: - CommandObjectMultiwordItaniumABI_Demangle (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "demangle", - "Demangle a C++ mangled name.", - "language cplusplus demangle") - { - CommandArgumentEntry arg; - CommandArgumentData index_arg; - - // Define the first (and only) variant of this arg. - index_arg.arg_type = eArgTypeSymbol; - index_arg.arg_repetition = eArgRepeatPlus; - - // There is only one variant this argument could be; put it into the argument entry. - arg.push_back (index_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back (arg); - } - - ~CommandObjectMultiwordItaniumABI_Demangle() override = default; - + CommandObjectMultiwordItaniumABI_Demangle(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "demangle", + "Demangle a C++ mangled name.", + "language cplusplus demangle") { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeSymbol; + index_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg.push_back(index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg); + } + + ~CommandObjectMultiwordItaniumABI_Demangle() override = default; + protected: - bool - DoExecute(Args& command, CommandReturnObject &result) override - { - bool demangled_any = false; - bool error_any = false; - for (size_t i = 0; i < command.GetArgumentCount(); i++) - { - auto arg = command.GetArgumentAtIndex(i); - if (arg && *arg) - { - ConstString mangled_cs(arg); - - // the actual Mangled class should be strict about this, but on the command line - // if you're copying mangled names out of 'nm' on Darwin, they will come out with - // an extra underscore - be willing to strip this on behalf of the user - // This is the moral equivalent of the -_/-n options to c++filt - if (mangled_cs.GetStringRef().startswith("__Z")) - mangled_cs.SetCString(arg+1); - - Mangled mangled(mangled_cs, true); - if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) - { - ConstString demangled(mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus)); - demangled_any = true; - result.AppendMessageWithFormat("%s ---> %s\n", arg, demangled.GetCString()); - } - else - { - error_any = true; - result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", arg); - } - } - } - - result.SetStatus(error_any ? lldb::eReturnStatusFailed : - (demangled_any ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult)); - return result.Succeeded(); + bool DoExecute(Args &command, CommandReturnObject &result) override { + bool demangled_any = false; + bool error_any = false; + for (auto &entry : command.entries()) { + if (entry.ref.empty()) + continue; + + // the actual Mangled class should be strict about this, but on the + // command line if you're copying mangled names out of 'nm' on Darwin, + // they will come out with an extra underscore - be willing to strip + // this on behalf of the user. This is the moral equivalent of the -_/-n + // options to c++filt + auto name = entry.ref; + if (name.startswith("__Z")) + name = name.drop_front(); + + Mangled mangled(name, true); + if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) { + ConstString demangled( + mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus)); + demangled_any = true; + result.AppendMessageWithFormat("%s ---> %s\n", entry.ref.str().c_str(), + demangled.GetCString()); + } else { + error_any = true; + result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", + entry.ref.str().c_str()); + } } + + result.SetStatus( + error_any ? lldb::eReturnStatusFailed + : (demangled_any ? lldb::eReturnStatusSuccessFinishResult + : lldb::eReturnStatusSuccessFinishNoResult)); + return result.Succeeded(); + } }; -class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword -{ +class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword { public: - CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "cplusplus", "Commands for operating on the C++ language runtime.", - "cplusplus []") - { - LoadSubCommand ("demangle", CommandObjectSP (new CommandObjectMultiwordItaniumABI_Demangle (interpreter))); - } - - ~CommandObjectMultiwordItaniumABI() override = default; + CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "cplusplus", + "Commands for operating on the C++ language runtime.", + "cplusplus []") { + LoadSubCommand( + "demangle", + CommandObjectSP( + new CommandObjectMultiwordItaniumABI_Demangle(interpreter))); + } + + ~CommandObjectMultiwordItaniumABI() override = default; }; -void -ItaniumABILanguageRuntime::Initialize() -{ - PluginManager::RegisterPlugin (GetPluginNameStatic(), - "Itanium ABI for the C++ language", - CreateInstance, - [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP { - return CommandObjectSP(new CommandObjectMultiwordItaniumABI(interpreter)); - }); +void ItaniumABILanguageRuntime::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "Itanium ABI for the C++ language", CreateInstance, + [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP { + return CommandObjectSP( + new CommandObjectMultiwordItaniumABI(interpreter)); + }); } -void -ItaniumABILanguageRuntime::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); +void ItaniumABILanguageRuntime::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -lldb_private::ConstString -ItaniumABILanguageRuntime::GetPluginNameStatic() -{ - static ConstString g_name("itanium"); - return g_name; +lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginNameStatic() { + static ConstString g_name("itanium"); + return g_name; } //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ -lldb_private::ConstString -ItaniumABILanguageRuntime::GetPluginName() -{ - return GetPluginNameStatic(); +lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginName() { + return GetPluginNameStatic(); } -uint32_t -ItaniumABILanguageRuntime::GetPluginVersion() -{ - return 1; +uint32_t ItaniumABILanguageRuntime::GetPluginVersion() { return 1; } + +BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver( + Breakpoint *bkpt, bool catch_bp, bool throw_bp) { + return CreateExceptionResolver(bkpt, catch_bp, throw_bp, false); } -BreakpointResolverSP -ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) -{ - return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false); +BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver( + Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) { + // One complication here is that most users DON'T want to stop at + // __cxa_allocate_expression, but until we can do + // anything better with predicting unwinding the expression parser does. So + // we have two forms of the exception + // breakpoints, one for expressions that leaves out __cxa_allocate_exception, + // and one that includes it. + // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint + // in the runtime the former. + static const char *g_catch_name = "__cxa_begin_catch"; + static const char *g_throw_name1 = "__cxa_throw"; + static const char *g_throw_name2 = "__cxa_rethrow"; + static const char *g_exception_throw_name = "__cxa_allocate_exception"; + std::vector exception_names; + exception_names.reserve(4); + if (catch_bp) + exception_names.push_back(g_catch_name); + + if (throw_bp) { + exception_names.push_back(g_throw_name1); + exception_names.push_back(g_throw_name2); + } + + if (for_expressions) + exception_names.push_back(g_exception_throw_name); + + BreakpointResolverSP resolver_sp(new BreakpointResolverName( + bkpt, exception_names.data(), exception_names.size(), + eFunctionNameTypeBase, eLanguageTypeUnknown, 0, eLazyBoolNo)); + + return resolver_sp; } -BreakpointResolverSP -ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) -{ - // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do - // anything better with predicting unwinding the expression parser does. So we have two forms of the exception - // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it. - // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former. - static const char *g_catch_name = "__cxa_begin_catch"; - static const char *g_throw_name1 = "__cxa_throw"; - static const char *g_throw_name2 = "__cxa_rethrow"; - static const char *g_exception_throw_name = "__cxa_allocate_exception"; - std::vector exception_names; - exception_names.reserve(4); - if (catch_bp) - exception_names.push_back(g_catch_name); - - if (throw_bp) - { - exception_names.push_back(g_throw_name1); - exception_names.push_back(g_throw_name2); - } +lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() { + Target &target = m_process->GetTarget(); - if (for_expressions) - exception_names.push_back(g_exception_throw_name); - - BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt, - exception_names.data(), - exception_names.size(), - eFunctionNameTypeBase, - eLanguageTypeUnknown, - 0, - eLazyBoolNo)); - - return resolver_sp; + 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", false)); + filter_modules.Append(FileSpec("libSystem.B.dylib", false)); + return target.GetSearchFilterForModuleList(&filter_modules); + } else { + return LanguageRuntime::CreateExceptionSearchFilter(); + } } +lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint( + bool catch_bp, bool throw_bp, bool for_expressions, bool is_internal) { + Target &target = m_process->GetTarget(); + FileSpecList filter_modules; + BreakpointResolverSP exception_resolver_sp = + CreateExceptionResolver(NULL, catch_bp, throw_bp, for_expressions); + SearchFilterSP filter_sp(CreateExceptionSearchFilter()); + const bool hardware = false; + const bool resolve_indirect_functions = false; + return target.CreateBreakpoint(filter_sp, exception_resolver_sp, is_internal, + hardware, resolve_indirect_functions); +} +void ItaniumABILanguageRuntime::SetExceptionBreakpoints() { + if (!m_process) + return; -lldb::SearchFilterSP -ItaniumABILanguageRuntime::CreateExceptionSearchFilter () -{ - Target &target = m_process->GetTarget(); + const bool catch_bp = false; + const bool throw_bp = true; + const bool is_internal = true; + const bool for_expressions = true; - 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", false)); - filter_modules.Append(FileSpec("libSystem.B.dylib", false)); - return target.GetSearchFilterForModuleList(&filter_modules); - } - else - { - return LanguageRuntime::CreateExceptionSearchFilter(); - } -} - -lldb::BreakpointSP -ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp, - bool throw_bp, - bool for_expressions, - bool is_internal) -{ - Target &target = m_process->GetTarget(); - FileSpecList filter_modules; - BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions); - SearchFilterSP filter_sp (CreateExceptionSearchFilter ()); - const bool hardware = false; - const bool resolve_indirect_functions = false; - return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions); -} + // For the exception breakpoints set by the Expression parser, we'll be a + // little more aggressive and + // stop at exception allocation as well. -void -ItaniumABILanguageRuntime::SetExceptionBreakpoints () -{ - if (!m_process) - return; - - const bool catch_bp = false; - const bool throw_bp = true; - const bool is_internal = true; - const bool for_expressions = true; - - // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and - // stop at exception allocation as well. - + if (m_cxx_exception_bp_sp) { + m_cxx_exception_bp_sp->SetEnabled(true); + } else { + m_cxx_exception_bp_sp = CreateExceptionBreakpoint( + catch_bp, throw_bp, for_expressions, is_internal); if (m_cxx_exception_bp_sp) - { - m_cxx_exception_bp_sp->SetEnabled (true); - } - else - { - m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal); - if (m_cxx_exception_bp_sp) - m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception"); - } - + m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception"); + } } -void -ItaniumABILanguageRuntime::ClearExceptionBreakpoints () -{ - if (!m_process) - return; - - if (m_cxx_exception_bp_sp) - { - m_cxx_exception_bp_sp->SetEnabled (false); - } +void ItaniumABILanguageRuntime::ClearExceptionBreakpoints() { + if (!m_process) + return; + + if (m_cxx_exception_bp_sp) { + m_cxx_exception_bp_sp->SetEnabled(false); + } } -bool -ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet () -{ - return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled(); +bool ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet() { + return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled(); } -bool -ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) -{ - if (!m_process) - return false; - - if (!stop_reason || - stop_reason->GetStopReason() != eStopReasonBreakpoint) - return false; - - uint64_t break_site_id = stop_reason->GetValue(); - return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id, - m_cxx_exception_bp_sp->GetID()); - +bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop( + lldb::StopInfoSP stop_reason) { + if (!m_process) + return false; + + if (!stop_reason || stop_reason->GetStopReason() != eStopReasonBreakpoint) + return false; + + uint64_t break_site_id = stop_reason->GetValue(); + return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint( + break_site_id, m_cxx_exception_bp_sp->GetID()); } -TypeAndOrName -ItaniumABILanguageRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr) -{ - std::lock_guard locker(m_dynamic_type_map_mutex); - DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr); - if (pos == m_dynamic_type_map.end()) - return TypeAndOrName(); - else - return pos->second; +TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo( + const lldb_private::Address &vtable_addr) { + std::lock_guard locker(m_dynamic_type_map_mutex); + DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr); + if (pos == m_dynamic_type_map.end()) + return TypeAndOrName(); + else + return pos->second; } -void -ItaniumABILanguageRuntime::SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) -{ - std::lock_guard locker(m_dynamic_type_map_mutex); - m_dynamic_type_map[vtable_addr] = type_info; +void ItaniumABILanguageRuntime::SetDynamicTypeInfo( + const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) { + std::lock_guard locker(m_dynamic_type_map_mutex); + m_dynamic_type_map[vtable_addr] = type_info; } diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index 86bd728d6c6f..480c32691c8b 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -18,116 +18,98 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Core/Value.h" #include "lldb/Symbol/Type.h" -#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" -#include "lldb/Core/Value.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" namespace lldb_private { - - class ItaniumABILanguageRuntime : - public lldb_private::CPPLanguageRuntime - { - public: - ~ItaniumABILanguageRuntime() override = default; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void - Initialize(); - - static void - Terminate(); - - static lldb_private::LanguageRuntime * - CreateInstance (Process *process, lldb::LanguageType language); - - static lldb_private::ConstString - GetPluginNameStatic(); - - bool - IsVTableName(const char *name) override; - - bool - GetDynamicTypeAndAddress(ValueObject &in_value, - lldb::DynamicValueType use_dynamic, - TypeAndOrName &class_type_or_name, - Address &address, - Value::ValueType &value_type) override; - - TypeAndOrName - FixUpDynamicType(const TypeAndOrName& type_and_or_name, - ValueObject& static_value) override; - - bool - CouldHaveDynamicValue(ValueObject &in_value) override; - - void - SetExceptionBreakpoints() override; - - void - ClearExceptionBreakpoints() override; - - bool - ExceptionBreakpointsAreSet() override; - - bool - ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override; - - lldb::BreakpointResolverSP - CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override; - - lldb::SearchFilterSP - CreateExceptionSearchFilter() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString - GetPluginName() override; - - uint32_t - GetPluginVersion() override; - - protected: - lldb::BreakpointResolverSP - CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions); - - lldb::BreakpointSP - CreateExceptionBreakpoint(bool catch_bp, - bool throw_bp, - bool for_expressions, - bool is_internal); - - private: - typedef std::map DynamicTypeCache; - - 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::BreakpointSP m_cxx_exception_bp_sp; - DynamicTypeCache m_dynamic_type_map; - std::mutex m_dynamic_type_map_mutex; - - TypeAndOrName - GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, lldb::addr_t vtable_addr); - - TypeAndOrName - GetDynamicTypeInfo(const lldb_private::Address &vtable_addr); - - void - SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info); - }; - + +class ItaniumABILanguageRuntime : public lldb_private::CPPLanguageRuntime { +public: + ~ItaniumABILanguageRuntime() override = default; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void Initialize(); + + static void Terminate(); + + static lldb_private::LanguageRuntime * + CreateInstance(Process *process, lldb::LanguageType language); + + static lldb_private::ConstString GetPluginNameStatic(); + + bool IsVTableName(const char *name) override; + + bool GetDynamicTypeAndAddress(ValueObject &in_value, + lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, + Address &address, + Value::ValueType &value_type) override; + + TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, + ValueObject &static_value) override; + + bool CouldHaveDynamicValue(ValueObject &in_value) override; + + void SetExceptionBreakpoints() override; + + void ClearExceptionBreakpoints() override; + + bool ExceptionBreakpointsAreSet() override; + + bool ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override; + + lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, + bool catch_bp, + bool throw_bp) override; + + lldb::SearchFilterSP CreateExceptionSearchFilter() override; + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + +protected: + lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, + bool catch_bp, + bool throw_bp, + bool for_expressions); + + lldb::BreakpointSP CreateExceptionBreakpoint(bool catch_bp, bool throw_bp, + bool for_expressions, + bool is_internal); + +private: + typedef std::map DynamicTypeCache; + + 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::BreakpointSP m_cxx_exception_bp_sp; + DynamicTypeCache m_dynamic_type_map; + std::mutex m_dynamic_type_map_mutex; + + TypeAndOrName GetTypeInfoFromVTableAddress(ValueObject &in_value, + lldb::addr_t original_ptr, + lldb::addr_t vtable_addr); + + TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr); + + void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, + const TypeAndOrName &type_info); +}; + } // namespace lldb_private #endif // liblldb_ItaniumABILanguageRuntime_h_ -- cgit v1.2.3