diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI | |
parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) | |
download | src-f3fbd1c0586ff6ec7895991e6c28f61a503c36a8.tar.gz src-f3fbd1c0586ff6ec7895991e6c28f61a503c36a8.zip |
Vendor import of lldb release_39 branch r276489:vendor/lldb/lldb-release_39-r276489
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=303241
svn path=/vendor/lldb/lldb-release_39-r276489/; revision=303242; tag=vendor/lldb/lldb-release_39-r276489
Diffstat (limited to 'source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI')
3 files changed, 266 insertions, 151 deletions
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 8e2cfb5570d9..c49feb07200e 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -13,13 +13,18 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -43,68 +48,26 @@ ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc); } -bool -ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, - lldb::DynamicValueType use_dynamic, - TypeAndOrName &class_type_or_name, - Address &dynamic_address, - Value::ValueType &value_type) +TypeAndOrName +ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, + lldb::addr_t vtable_load_addr) { - // 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)) + if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) { - // 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()); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - - char memory_buffer[16]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - process->GetByteOrder(), - process->GetAddressByteSize()); - size_t address_byte_size = process->GetAddressByteSize(); - Error error; - size_t bytes_read = process->ReadMemory (original_ptr, - memory_buffer, - address_byte_size, - error); - if (!error.Success() || (bytes_read != address_byte_size)) - { - return false; - } - - lldb::offset_t offset = 0; - lldb::addr_t vtable_address_point = data.GetAddress (&offset); - - if (offset == 0) - return false; - - // Now find the symbol that contains this address: - - SymbolContext sc; - Address address_point_address; - if (target && !target->GetSectionLoadList().IsEmpty()) + // 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_address_point, address_point_address)) + if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, vtable_addr)) { - target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc); + // 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) { @@ -119,52 +82,56 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 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); - class_type_or_name.SetName (class_name); + 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<SymbolFile *> 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, - class_types); + 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 false; + return TypeAndOrName(); } if (num_matches == 1) { type_sp = class_types.GetTypeAtIndex(0); - 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()); - - class_type_or_name.SetTypeSP(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) { @@ -191,7 +158,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { - if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ())) + 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", @@ -199,74 +166,112 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, in_value.GetTypeName().AsCString(), type_sp->GetID(), type_sp->GetName().GetCString()); - class_type_or_name.SetTypeSP(type_sp); - break; + type_info.SetTypeSP(type_sp); } } } - - if (i == num_matches) - { - if (log) - 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()); - return false; - } - } - - // 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->GetFullCompilerType ())) - { - // 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 address. - Address offset_to_top_address = address_point_address; - int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); - offset_to_top_address.Slide (slide); - - Error error; - lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); - - size_t bytes_read = process->ReadMemory (offset_to_top_location, - memory_buffer, - address_byte_size, - error); - - if (!error.Success() || (bytes_read != address_byte_size)) - { - return false; - } - - offset = 0; - int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize()); - - // 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 (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) + if (log && i == num_matches) { - dynamic_address.SetRawAddress(dynamic_addr); + 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()); } - return true; } + if (type_info) + SetDynamicTypeInfo(vtable_addr, type_info); + return type_info; } } } } } - + 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; + } + + 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; + } + } + } + return class_type_or_name.IsEmpty() == false; } @@ -336,12 +341,94 @@ ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType return NULL; } +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; + +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(); + } +}; + +class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword +{ +public: + CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "cplusplus", "Commands for operating on the C++ language runtime.", + "cplusplus <subcommand> [<subcommand-options>]") + { + LoadSubCommand ("demangle", CommandObjectSP (new CommandObjectMultiwordItaniumABI_Demangle (interpreter))); + } + + ~CommandObjectMultiwordItaniumABI() override = default; +}; + void ItaniumABILanguageRuntime::Initialize() { PluginManager::RegisterPlugin (GetPluginNameStatic(), "Itanium ABI for the C++ language", - CreateInstance); + CreateInstance, + [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP { + return CommandObjectSP(new CommandObjectMultiwordItaniumABI(interpreter)); + }); } void @@ -408,6 +495,7 @@ ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch exception_names.size(), eFunctionNameTypeBase, eLanguageTypeUnknown, + 0, eLazyBoolNo)); return resolver_sp; @@ -510,3 +598,21 @@ ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP sto m_cxx_exception_bp_sp->GetID()); } + +TypeAndOrName +ItaniumABILanguageRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr) +{ + std::lock_guard<std::mutex> 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<std::mutex> 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 c06b9863a9bf..86bd728d6c6f 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -12,12 +12,15 @@ // C Includes // C++ Includes +#include <map> +#include <mutex> #include <vector> // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Symbol/Type.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Core/Value.h" @@ -100,9 +103,29 @@ namespace lldb_private { bool is_internal); private: - ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead. - - lldb::BreakpointSP m_cxx_exception_bp_sp; + typedef std::map<lldb_private::Address, TypeAndOrName> 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 diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile deleted file mode 100644 index ac87437f9d2a..000000000000 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/LangRuntime/C++/ItaniumABI/Makefile --*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../../.. -LIBRARYNAME := lldbPluginCXXItaniumABI -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile |