diff options
author | Ed Maste <emaste@FreeBSD.org> | 2016-01-04 01:16:32 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2016-01-04 01:16:32 +0000 |
commit | 9f2f44ceeb195c67fbbf0953f03c530f6f1e59d4 (patch) | |
tree | 1a3cc0a2c3d432ddf9ffc14f06bd43e8097fc93c /contrib/llvm/tools/lldb/source/Plugins/SymbolFile | |
parent | 0a97e59728ecf251d065745cb716ffe32b24aa28 (diff) | |
parent | 3bd2e91faeb9eeec1aae82c64a3253afff551cfd (diff) | |
download | src-9f2f44ceeb195c67fbbf0953f03c530f6f1e59d4.tar.gz src-9f2f44ceeb195c67fbbf0953f03c530f6f1e59d4.zip |
Merge LLDB 3.8
As with previous imports a number of plugins not immediately relevant
to FreeBSD have been excluded:
ABIMacOSX_i386
ABIMacOSX_arm
ABIMacOSX_arm64
ABISysV_hexagon
AppleObjCRuntimeV2
AppleObjCRuntimeV1
SystemRuntimeMacOSX
RenderScriptRuntime
GoLanguageRuntime
GoLanguage
ObjCLanguage
ObjCPlusPlusLanguage
ObjectFilePECOFF
DynamicLoaderWindowsDYLD
platform_linux
platform_netbsd
PlatformWindows
PlatformKalimba
platform_android
DynamicLoaderMacOSXDYLD
ObjectContainerUniversalMachO
PlatformRemoteiOS
PlatformMacOSX
OperatingSystemGo
Notes
Notes:
svn path=/projects/clang380-import/; revision=293127
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/SymbolFile')
49 files changed, 10375 insertions, 8103 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp new file mode 100644 index 000000000000..c0754a1fdd54 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -0,0 +1,56 @@ +//===-- DIERef.cpp ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DIERef.h" +#include "DWARFCompileUnit.h" +#include "DWARFFormValue.h" + +DIERef::DIERef() : + cu_offset(DW_INVALID_OFFSET), + die_offset(DW_INVALID_OFFSET) +{} + +DIERef::DIERef(dw_offset_t d) : + cu_offset(DW_INVALID_OFFSET), + die_offset(d) +{} + +DIERef::DIERef(dw_offset_t c, dw_offset_t d) : + cu_offset(c), + die_offset(d) +{} + +DIERef::DIERef(lldb::user_id_t uid) : + cu_offset(uid>>32), + die_offset(uid&0xffffffff) +{} + +DIERef::DIERef(const DWARFFormValue& form_value) : + cu_offset(DW_INVALID_OFFSET), + die_offset(DW_INVALID_OFFSET) +{ + if (form_value.IsValid()) + { + const DWARFCompileUnit* dwarf_cu = form_value.GetCompileUnit(); + if (dwarf_cu) + { + if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) + cu_offset = dwarf_cu->GetBaseObjOffset(); + else + cu_offset = dwarf_cu->GetOffset(); + } + die_offset = form_value.Reference(); + } +} + +lldb::user_id_t +DIERef::GetUID() const +{ + return ((lldb::user_id_t)cu_offset) << 32 | die_offset; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h new file mode 100644 index 000000000000..a5484db6bd6c --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -0,0 +1,42 @@ +//===-- DIERef.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DIERef_h_ +#define SymbolFileDWARF_DIERef_h_ + +#include "lldb/Core/dwarf.h" +#include "lldb/lldb-defines.h" + +class DWARFFormValue; + +struct DIERef +{ + DIERef(); + + explicit + DIERef(dw_offset_t d); + + DIERef(dw_offset_t c, dw_offset_t d); + + explicit + DIERef(lldb::user_id_t uid); + + explicit + DIERef(const DWARFFormValue& form_value); + + lldb::user_id_t + GetUID() const; + + dw_offset_t cu_offset; + dw_offset_t die_offset; +}; + +typedef std::vector<DIERef> DIEArray; + +#endif // SymbolFileDWARF_DIERef_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h new file mode 100644 index 000000000000..ab20844bfcfd --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -0,0 +1,65 @@ +//===-- DWARFASTParser.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParser_h_ +#define SymbolFileDWARF_DWARFASTParser_h_ + +#include "DWARFDefines.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" + +class DWARFDIE; + +class DWARFASTParser +{ +public: + virtual ~DWARFASTParser() {} + + virtual lldb::TypeSP + ParseTypeFromDWARF (const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + lldb_private::Log *log, + bool *type_is_new_ptr) = 0; + + virtual lldb_private::Function * + ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc, + const DWARFDIE &die) = 0; + + virtual bool + CanCompleteType (const lldb_private::CompilerType &compiler_type) + { + return false; + } + + virtual bool + CompleteType (const lldb_private::CompilerType &compiler_type) + { + return false; + } + + virtual bool + CompleteTypeFromDWARF (const DWARFDIE &die, + lldb_private::Type *type, + lldb_private::CompilerType &compiler_type) = 0; + + virtual lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) = 0; + + virtual lldb_private::CompilerDeclContext + GetDeclContextForUIDFromDWARF (const DWARFDIE &die) = 0; + + virtual lldb_private::CompilerDeclContext + GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0; + + virtual std::vector<DWARFDIE> + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0; +}; + +#endif // SymbolFileDWARF_DWARFASTParser_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp new file mode 100644 index 000000000000..68a0285b69df --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -0,0 +1,4034 @@ +//===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserClang.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" +#include "DWARFDeclContext.h" +#include "DWARFDefines.h" +#include "DWARFDIE.h" +#include "DWARFDIECollection.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDebugMap.h" +#include "UniqueDWARFASTType.h" + +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Value.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/TypeMap.h" +#include "lldb/Target/Language.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +#include <map> +#include <vector> + +//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN + +#ifdef ENABLE_DEBUG_PRINTF +#include <stdio.h> +#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + + +using namespace lldb; +using namespace lldb_private; +DWARFASTParserClang::DWARFASTParserClang (ClangASTContext &ast) : + m_ast (ast), + m_die_to_decl_ctx (), + m_decl_ctx_to_die () +{ +} + +DWARFASTParserClang::~DWARFASTParserClang () +{ +} + + +static AccessType +DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility) +{ + switch (dwarf_accessibility) + { + case DW_ACCESS_public: return eAccessPublic; + case DW_ACCESS_private: return eAccessPrivate; + case DW_ACCESS_protected: return eAccessProtected; + default: break; + } + return eAccessNone; +} + +static bool +DeclKindIsCXXClass (clang::Decl::Kind decl_kind) +{ + switch (decl_kind) + { + case clang::Decl::CXXRecord: + case clang::Decl::ClassTemplateSpecialization: + return true; + default: + break; + } + return false; +} + +struct BitfieldInfo +{ + uint64_t bit_size; + uint64_t bit_offset; + + BitfieldInfo () : + bit_size (LLDB_INVALID_ADDRESS), + bit_offset (LLDB_INVALID_ADDRESS) + { + } + + void + Clear() + { + bit_size = LLDB_INVALID_ADDRESS; + bit_offset = LLDB_INVALID_ADDRESS; + } + + bool IsValid () + { + return (bit_size != LLDB_INVALID_ADDRESS) && + (bit_offset != LLDB_INVALID_ADDRESS); + } +}; + + +ClangASTImporter & +DWARFASTParserClang::GetClangASTImporter() +{ + if (!m_clang_ast_importer_ap) + { + m_clang_ast_importer_ap.reset (new ClangASTImporter); + } + return *m_clang_ast_importer_ap; +} + + +TypeSP +DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log) +{ + ModuleSP dwo_module_sp = die.GetContainingDWOModule(); + if (dwo_module_sp) + { + // This type comes from an external DWO module + std::vector<CompilerContext> dwo_context; + die.GetDWOContext(dwo_context); + TypeMap dwo_types; + if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types)) + { + const size_t num_dwo_types = dwo_types.GetSize(); + if (num_dwo_types == 1) + { + // We found a real definition for this type elsewhere + // so lets use it and cache the fact that we found + // a complete type for this die + TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0); + if (dwo_type_sp) + { + lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType(); + + lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type); + + //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString()); + if (type) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + TypeSP type_sp (new Type (die.GetID(), + dwarf, + dwo_type_sp->GetName(), + dwo_type_sp->GetByteSize(), + NULL, + LLDB_INVALID_UID, + Type::eEncodingInvalid, + &dwo_type_sp->GetDeclaration(), + type, + Type::eResolveStateForward)); + + dwarf->GetTypeList()->Insert(type_sp); + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); + if (tag_decl) + LinkDeclContextToDIE(tag_decl, die); + else + { + clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + } + return type_sp; + } + } + } + } + } + return TypeSP(); +} + +TypeSP +DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, + const DWARFDIE &die, + Log *log, + bool *type_is_new_ptr) +{ + TypeSP type_sp; + + if (type_is_new_ptr) + *type_is_new_ptr = false; + + AccessType accessibility = eAccessNone; + if (die) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (log) + { + DWARFDIE context_die; + clang::DeclContext *context = GetClangDeclContextContainingDIE (die, &context_die); + + dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')", + die.GetOffset(), + static_cast<void*>(context), + context_die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); + + } + // + // Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); + // if (log && dwarf_cu) + // { + // StreamString s; + // die->DumpLocation (this, dwarf_cu, s); + // dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); + // + // } + + Type *type_ptr = dwarf->GetDIEToType().lookup (die.GetDIE()); + TypeList* type_list = dwarf->GetTypeList(); + if (type_ptr == NULL) + { + if (type_is_new_ptr) + *type_is_new_ptr = true; + + const dw_tag_t tag = die.Tag(); + + bool is_forward_declaration = false; + DWARFAttributes attributes; + const char *type_name_cstr = NULL; + ConstString type_name_const_str; + Type::ResolveState resolve_state = Type::eResolveStateUnresolved; + uint64_t byte_size = 0; + Declaration decl; + + Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; + CompilerType clang_type; + DWARFFormValue form_value; + + dw_attr_t attr; + + switch (tag) + { + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_typedef: + case DW_TAG_const_type: + case DW_TAG_restrict_type: + case DW_TAG_volatile_type: + case DW_TAG_unspecified_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + const size_t num_attributes = die.GetAttributes (attributes); + uint32_t encoding = 0; + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + + if (num_attributes > 0) + { + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: + + type_name_cstr = form_value.AsCString(); + // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't + // include the "&"... + if (tag == DW_TAG_reference_type) + { + if (strchr (type_name_cstr, '&') == NULL) + type_name_cstr = NULL; + } + if (type_name_cstr) + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; + case DW_AT_encoding: encoding = form_value.Unsigned(); break; + case DW_AT_type: encoding_uid = DIERef(form_value).GetUID(); break; + default: + case DW_AT_sibling: + break; + } + } + } + } + + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); + + switch (tag) + { + default: + break; + + case DW_TAG_unspecified_type: + if (strcmp(type_name_cstr, "nullptr_t") == 0 || + strcmp(type_name_cstr, "decltype(nullptr)") == 0 ) + { + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); + break; + } + // Fall through to base type below in case we can handle the type there... + + case DW_TAG_base_type: + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, + encoding, + byte_size * 8); + break; + + case DW_TAG_pointer_type: encoding_data_type = Type::eEncodingIsPointerUID; break; + case DW_TAG_reference_type: encoding_data_type = Type::eEncodingIsLValueReferenceUID; break; + case DW_TAG_rvalue_reference_type: encoding_data_type = Type::eEncodingIsRValueReferenceUID; break; + case DW_TAG_typedef: encoding_data_type = Type::eEncodingIsTypedefUID; break; + case DW_TAG_const_type: encoding_data_type = Type::eEncodingIsConstUID; break; + case DW_TAG_restrict_type: encoding_data_type = Type::eEncodingIsRestrictUID; break; + case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break; + } + + if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) + { + bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); + + if (translation_unit_is_objc) + { + if (type_name_cstr != NULL) + { + static ConstString g_objc_type_name_id("id"); + static ConstString g_objc_type_name_Class("Class"); + static ConstString g_objc_type_name_selector("SEL"); + + if (type_name_const_str == g_objc_type_name_id) + { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + + } + else if (type_name_const_str == g_objc_type_name_Class) + { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.", + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + } + else if (type_name_const_str == g_objc_type_name_selector) + { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + } + } + else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID) + { + // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id". + + const DWARFDIE encoding_die = die.GetDIE(encoding_uid); + + if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) + { + if (const char *struct_name = encoding_die.GetName()) + { + if (!strcmp(struct_name, "objc_object")) + { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.", + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + } + } + } + } + } + } + + type_sp.reset( new Type (die.GetID(), + dwarf, + type_name_const_str, + byte_size, + NULL, + encoding_uid, + encoding_data_type, + &decl, + clang_type, + resolve_state)); + + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + + // Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false); + // if (encoding_type != NULL) + // { + // if (encoding_type != DIE_IS_BEING_PARSED) + // type_sp->SetEncodingType(encoding_type); + // else + // m_indirect_fixups.push_back(type_sp.get()); + // } + } + break; + + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + bool byte_size_valid = false; + + LanguageType class_language = eLanguageTypeUnknown; + bool is_complete_objc_class = false; + //bool struct_is_class = false; + const size_t num_attributes = die.GetAttributes (attributes); + if (num_attributes > 0) + { + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: + if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid()) + { + // llvm-gcc outputs invalid DW_AT_decl_file attributes that always + // point to the compile unit file, so we clear this invalid value + // so that we can still unique types efficiently. + decl.SetFile(FileSpec ("<invalid>", false)); + } + else + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); + break; + + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + byte_size_valid = true; + break; + + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + + case DW_AT_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + + case DW_AT_APPLE_objc_complete_type: + is_complete_objc_class = form_value.Signed(); + break; + + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_start_scope: + case DW_AT_visibility: + default: + case DW_AT_sibling: + break; + } + } + } + } + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively + // and clang isn't good and sharing the stack space for variables in different blocks. + std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); + + if (type_name_const_str) + { + LanguageType die_language = die.GetLanguage(); + bool handled = false; + if (Language::LanguageIsCPlusPlus(die_language)) + { + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + { + handled = true; + ConstString const_qualified_name(qualified_name); + if (dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die, Declaration(), + byte_size_valid ? byte_size : -1, + *unique_ast_entry_ap)) + { + type_sp = unique_ast_entry_ap->m_type_sp; + if (type_sp) + { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + } + + if (!handled) + { + if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, + byte_size_valid ? byte_size : -1, + *unique_ast_entry_ap)) + { + type_sp = unique_ast_entry_ap->m_type_sp; + if (type_sp) + { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + } + + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) + { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } + else if (tag == DW_TAG_union_type) + { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } + else if (tag == DW_TAG_class_type) + { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } + + if (byte_size_valid && byte_size == 0 && type_name_cstr && + die.HasChildren() == false && + sc.comp_unit->GetLanguage() == eLanguageTypeObjC) + { + // Work around an issue with clang at the moment where + // forward declarations for objective C classes are emitted + // as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are + // no children, and the byte size is zero. + is_forward_declaration = true; + } + + if (class_language == eLanguageTypeObjC || + class_language == eLanguageTypeObjC_plus_plus) + { + if (!is_complete_objc_class && die.Supports_DW_AT_APPLE_objc_complete_type()) + { + // We have a valid eSymbolTypeObjCClass class symbol whose + // name matches the current objective C class that we + // are trying to find and this DIE isn't the complete + // definition (we checked is_complete_objc_class above and + // know it is false), so the real definition is in here somewhere + type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); + + if (!type_sp) + { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) + { + // We weren't able to find a full declaration in + // this DWARF, see if we have a declaration anywhere + // else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); + } + } + + if (type_sp) + { + if (log) + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64, + static_cast<void*>(this), + die.GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr, + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere + // so lets use it and cache the fact that we found + // a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + + + if (is_forward_declaration) + { + // We have a forward declaration to a type and we need + // to try and find a full declaration. We look in the + // current type index just in case we have a forward + // declaration followed by an actual declarations in the + // DWARF. If this fails, we need to look elsewhere... + if (log) + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", + static_cast<void*>(this), + die.GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr); + } + + // See if the type comes from a DWO module and if so, track down that type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + + if (!type_sp) + { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) + { + // We weren't able to find a full declaration in + // this DWARF, see if we have a declaration anywhere + // else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + } + } + + if (type_sp) + { + if (log) + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void*>(this), + die.GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr, + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere + // so lets use it and cache the fact that we found + // a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( + dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID()))); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert (tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE())); + if (!clang_type) + { + clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); + if (accessibility == eAccessNone && decl_ctx) + { + // Check the decl context that contains this class/struct/union. + // If it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass (containing_decl_kind)) + accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual (die)); + + if (type_name_cstr && strchr (type_name_cstr, '<')) + { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos (die, template_param_infos)) + { + clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl (decl_ctx, + accessibility, + type_name_cstr, + tag_decl_kind, + template_param_infos); + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl (decl_ctx, + class_template_decl, + tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType (class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata (class_template_decl, metadata); + m_ast.SetMetadata (class_specialization_decl, metadata); + } + } + + if (!clang_type_was_created) + { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType (decl_ctx, + accessibility, + type_name_cstr, + tag_decl_kind, + class_language, + &metadata); + } + } + + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang + // types for function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp.reset (new Type (die.GetID(), + dwarf, + type_name_const_str, + byte_size, + NULL, + LLDB_INVALID_UID, + Type::eEncodingIsUID, + &decl, + clang_type, + Type::eResolveStateForward)); + + type_sp->SetIsCompleteObjCClass(is_complete_objc_class); + + + // Add our type to the unique type map so we don't + // end up creating many copies of the same type over + // and over in the ASTContext for our module + unique_ast_entry_ap->m_type_sp = type_sp; + unique_ast_entry_ap->m_die = die; + unique_ast_entry_ap->m_declaration = decl; + unique_ast_entry_ap->m_byte_size = byte_size; + dwarf->GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, + *unique_ast_entry_ap); + + if (is_forward_declaration && die.HasChildren()) + { + // Check to see if the DIE actually has a definition, some version of GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram, + // members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) + { + switch (child_die.Tag()) + { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } + + if (!is_forward_declaration) + { + // Always start the definition for a class type so that + // if the class has child classes or types that require + // the class to be created for use as their decl contexts + // the class will be ready to accept these child definitions. + if (die.HasChildren() == false) + { + // No children for this struct/union/class, lets finish it + ClangASTContext::StartTagDeclarationDefinition (clang_type); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(clang_type); + + if (record_decl) + m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo())); + } + } + else if (clang_type_was_created) + { + // Start the definition if the class is not objective C since + // the underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ class/union/structs + // we want to start the definition in case the class is needed as the + // declaration context for a contained class or type without the need + // to complete that type.. + + if (class_language != eLanguageTypeObjC && + class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition (clang_type); + + // Leave this as a forward declaration until we need + // to know the details of the type. lldb_private::Type + // will automatically call the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" + // When the definition needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count(ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + assert(((SymbolFileDWARF*)m_ast.GetSymbolFile())->UserIDMatches(die.GetDIERef().GetUID()) && + "Adding incorrect type to forward declaration map"); + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie()[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die.GetDIERef(); + m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true); + } + } + } + break; + + case DW_TAG_enumeration_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + DWARFFormValue encoding_form; + + const size_t num_attributes = die.GetAttributes (attributes); + if (num_attributes > 0) + { + uint32_t i; + + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_type: encoding_form = form_value; break; + case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; + case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; + case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break; + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_bit_stride: + case DW_AT_byte_stride: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_start_scope: + case DW_AT_visibility: + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_sibling: + break; + } + } + } + + if (is_forward_declaration) + { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + + if (!type_sp) + { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) + { + // We weren't able to find a full declaration in + // this DWARF, see if we have a declaration anywhere + // else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + } + } + + if (type_sp) + { + if (log) + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void*>(this), + die.GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr, + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere + // so lets use it and cache the fact that we found + // a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( + dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID()))); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + + } + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + + CompilerType enumerator_clang_type; + clang_type.SetCompilerType (&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE())); + if (!clang_type) + { + if (encoding_form.IsValid()) + { + Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form).GetUID()); + if (enumerator_type) + enumerator_clang_type = enumerator_type->GetFullCompilerType (); + } + + if (!enumerator_clang_type) + enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, + DW_ATE_signed, + byte_size * 8); + + clang_type = m_ast.CreateEnumerationType (type_name_cstr, + GetClangDeclContextContainingDIE (die, nullptr), + decl, + enumerator_clang_type); + } + else + { + enumerator_clang_type = m_ast.GetEnumerationIntegerType (clang_type.GetOpaqueQualType()); + } + + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die); + + type_sp.reset( new Type (die.GetID(), + dwarf, + type_name_const_str, + byte_size, + NULL, + DIERef(encoding_form).GetUID(), + Type::eEncodingIsUID, + &decl, + clang_type, + Type::eResolveStateForward)); + + ClangASTContext::StartTagDeclarationDefinition (clang_type); + if (die.HasChildren()) + { + SymbolContext cu_sc(die.GetLLDBCompileUnit()); + bool is_signed = false; + enumerator_clang_type.IsIntegerType(is_signed); + ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die); + } + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + } + } + break; + + case DW_TAG_inlined_subroutine: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + DWARFFormValue type_die_form; + bool is_variadic = false; + bool is_inline = false; + bool is_static = false; + bool is_virtual = false; + bool is_explicit = false; + bool is_artificial = false; + DWARFFormValue specification_die_form; + DWARFFormValue abstract_origin_die_form; + dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; + + unsigned type_quals = 0; + clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern + + + const size_t num_attributes = die.GetAttributes (attributes); + if (num_attributes > 0) + { + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&dwarf->get_debug_str_data()); break; + case DW_AT_type: type_die_form = form_value; break; + case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; + case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; + case DW_AT_inline: is_inline = form_value.Boolean(); break; + case DW_AT_virtuality: is_virtual = form_value.Boolean(); break; + case DW_AT_explicit: is_explicit = form_value.Boolean(); break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; + + + case DW_AT_external: + if (form_value.Unsigned()) + { + if (storage == clang::SC_None) + storage = clang::SC_Extern; + else + storage = clang::SC_PrivateExtern; + } + break; + + case DW_AT_specification: + specification_die_form = form_value; + break; + + case DW_AT_abstract_origin: + abstract_origin_die_form = form_value; + break; + + case DW_AT_object_pointer: + object_pointer_die_offset = form_value.Reference(); + break; + + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_address_class: + case DW_AT_calling_convention: + case DW_AT_data_location: + case DW_AT_elemental: + case DW_AT_entry_pc: + case DW_AT_frame_base: + case DW_AT_high_pc: + case DW_AT_low_pc: + case DW_AT_prototyped: + case DW_AT_pure: + case DW_AT_ranges: + case DW_AT_recursive: + case DW_AT_return_addr: + case DW_AT_segment: + case DW_AT_start_scope: + case DW_AT_static_link: + case DW_AT_trampoline: + case DW_AT_visibility: + case DW_AT_vtable_elem_location: + case DW_AT_description: + case DW_AT_sibling: + break; + } + } + } + } + + std::string object_pointer_name; + if (object_pointer_die_offset != DW_INVALID_OFFSET) + { + DWARFDIE object_pointer_die = die.GetDIE (object_pointer_die_offset); + if (object_pointer_die) + { + const char *object_pointer_name_cstr = object_pointer_die.GetName(); + if (object_pointer_name_cstr) + object_pointer_name = object_pointer_name_cstr; + } + } + + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + + CompilerType return_clang_type; + Type *func_type = NULL; + + if (type_die_form.IsValid()) + func_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + + if (func_type) + return_clang_type = func_type->GetForwardCompilerType (); + else + return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); + + + std::vector<CompilerType> function_param_types; + std::vector<clang::ParmVarDecl*> function_param_decls; + + // Parse the function children for the parameters + + DWARFDIE decl_ctx_die; + clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, &decl_ctx_die); + const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind(); + + const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind); + // Start off static. This will be set to false in ParseChildParameters(...) + // if we find a "this" parameters as the first parameter + if (is_cxx_method) + is_static = true; + + if (die.HasChildren()) + { + bool skip_artificial = true; + ParseChildParameters (sc, + containing_decl_ctx, + die, + skip_artificial, + is_static, + is_variadic, + function_param_types, + function_param_decls, + type_quals); + } + + // clang_type will get the function prototype clang type after this call + clang_type = m_ast.CreateFunctionType (return_clang_type, + function_param_types.data(), + function_param_types.size(), + is_variadic, + type_quals); + + bool ignore_containing_context = false; + + if (type_name_cstr) + { + bool type_handled = false; + if (tag == DW_TAG_subprogram || + tag == DW_TAG_inlined_subroutine) + { + ObjCLanguage::MethodName objc_method (type_name_cstr, true); + if (objc_method.IsValid(true)) + { + CompilerType class_opaque_type; + ConstString class_name(objc_method.GetClassName()); + if (class_name) + { + TypeSP complete_objc_class_type_sp (dwarf->FindCompleteObjCDefinitionTypeForDIE (DWARFDIE(), class_name, false)); + + if (complete_objc_class_type_sp) + { + CompilerType type_clang_forward_type = complete_objc_class_type_sp->GetForwardCompilerType (); + if (ClangASTContext::IsObjCObjectOrInterfaceType(type_clang_forward_type)) + class_opaque_type = type_clang_forward_type; + } + } + + if (class_opaque_type) + { + // If accessibility isn't set to anything valid, assume public for + // now... + if (accessibility == eAccessNone) + accessibility = eAccessPublic; + + clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType (class_opaque_type, + type_name_cstr, + clang_type, + accessibility, + is_artificial); + type_handled = objc_method_decl != NULL; + if (type_handled) + { + LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die); + m_ast.SetMetadataAsUserID (objc_method_decl, die.GetID()); + } + else + { + dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", + die.GetOffset(), + tag, + DW_TAG_value_to_name(tag)); + } + } + } + else if (is_cxx_method) + { + // Look at the parent of this DIE and see if is is + // a class or struct and see if this is actually a + // C++ method + Type *class_type = dwarf->ResolveType (decl_ctx_die); + if (class_type) + { + bool alternate_defn = false; + if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE()) + { + alternate_defn = true; + + // We uniqued the parent class of this function to another class + // so we now need to associate all dies under "decl_ctx_die" to + // DIEs in the DIE for "class_type"... + SymbolFileDWARF *class_symfile = NULL; + DWARFDIE class_type_die; + + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) + { + class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID())); + class_type_die = class_symfile->DebugInfo()->GetDIE (DIERef(class_type->GetID())); + } + else + { + class_symfile = dwarf; + class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID())); + } + if (class_type_die) + { + DWARFDIECollection failures; + + CopyUniqueClassMethodTypes (decl_ctx_die, + class_type_die, + class_type, + failures); + + // FIXME do something with these failures that's smarter than + // just dropping them on the ground. Unfortunately classes don't + // like having stuff added to them after their definitions are + // complete... + + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) + { + type_sp = type_ptr->shared_from_this(); + break; + } + } + } + + if (specification_die_form.IsValid()) + { + // We have a specification which we are going to base our function + // prototype off of, so we need this type to be completed so that the + // m_die_to_decl_ctx for the method in the specification has a valid + // clang decl context. + class_type->GetForwardCompilerType (); + // If we have a specification, then the function type should have been + // made with the specification and not with this die. + DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form)); + clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (spec_die); + if (spec_clang_decl_ctx) + { + LinkDeclContextToDIE(spec_clang_decl_ctx, die); + } + else + { + dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8" PRIx64 ") has no decl\n", + die.GetID(), + specification_die_form.Reference()); + } + type_handled = true; + } + else if (abstract_origin_die_form.IsValid()) + { + // We have a specification which we are going to base our function + // prototype off of, so we need this type to be completed so that the + // m_die_to_decl_ctx for the method in the abstract origin has a valid + // clang decl context. + class_type->GetForwardCompilerType (); + + DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE (DIERef(abstract_origin_die_form)); + clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (abs_die); + if (abs_clang_decl_ctx) + { + LinkDeclContextToDIE (abs_clang_decl_ctx, die); + } + else + { + dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8" PRIx64 ") has no decl\n", + die.GetID(), + abstract_origin_die_form.Reference()); + } + type_handled = true; + } + else + { + CompilerType class_opaque_type = class_type->GetForwardCompilerType (); + if (ClangASTContext::IsCXXClassType(class_opaque_type)) + { + if (class_opaque_type.IsBeingDefined () || alternate_defn) + { + if (!is_static && !die.HasChildren()) + { + // We have a C++ member function with no children (this pointer!) + // and clang will get mad if we try and make a function that isn't + // well formed in the DWARF, so we will just skip it... + type_handled = true; + } + else + { + bool add_method = true; + if (alternate_defn) + { + // If an alternate definition for the class exists, then add the method only if an + // equivalent is not already present. + clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(class_opaque_type.GetOpaqueQualType()); + if (record_decl) + { + for (auto method_iter = record_decl->method_begin(); + method_iter != record_decl->method_end(); + method_iter++) + { + clang::CXXMethodDecl *method_decl = *method_iter; + if (method_decl->getNameInfo().getAsString() == std::string(type_name_cstr)) + { + if (method_decl->getType() == ClangASTContext::GetQualType(clang_type)) + { + add_method = false; + LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die); + type_handled = true; + + break; + } + } + } + } + } + + if (add_method) + { + // REMOVE THE CRASH DESCRIPTION BELOW + Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s", + type_name_cstr, + class_type->GetName().GetCString(), + die.GetID(), + dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str()); + + const bool is_attr_used = false; + // Neither GCC 4.2 nor clang++ currently set a valid accessibility + // in the DWARF for C++ methods... Default to public for now... + if (accessibility == eAccessNone) + accessibility = eAccessPublic; + + clang::CXXMethodDecl *cxx_method_decl; + cxx_method_decl = m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(), + type_name_cstr, + clang_type, + accessibility, + is_virtual, + is_static, + is_inline, + is_explicit, + is_attr_used, + is_artificial); + + type_handled = cxx_method_decl != NULL; + + if (type_handled) + { + LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die); + + Host::SetCrashDescription (NULL); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + if (!object_pointer_name.empty()) + { + metadata.SetObjectPtrName(object_pointer_name.c_str()); + if (log) + log->Printf ("Setting object pointer name: %s on method object %p.\n", + object_pointer_name.c_str(), + static_cast<void*>(cxx_method_decl)); + } + m_ast.SetMetadata (cxx_method_decl, metadata); + } + else + { + ignore_containing_context = true; + } + } + } + } + else + { + // We were asked to parse the type for a method in a class, yet the + // class hasn't been asked to complete itself through the + // clang::ExternalASTSource protocol, so we need to just have the + // class complete itself and do things the right way, then our + // DIE should then have an entry in the dwarf->GetDIEToType() map. First + // we need to modify the dwarf->GetDIEToType() so it doesn't think we are + // trying to parse this DIE anymore... + dwarf->GetDIEToType()[die.GetDIE()] = NULL; + + // Now we get the full type to force our class type to complete itself + // using the clang::ExternalASTSource protocol which will parse all + // base classes and all methods (including the method for this DIE). + class_type->GetFullCompilerType (); + + // The type for this DIE should have been filled in the function call above + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) + { + type_sp = type_ptr->shared_from_this(); + break; + } + + // FIXME This is fixing some even uglier behavior but we really need to + // uniq the methods of each class as well as the class itself. + // <rdar://problem/11240464> + type_handled = true; + } + } + } + } + } + } + + if (!type_handled) + { + // We just have a function that isn't part of a class + clang::FunctionDecl *function_decl = m_ast.CreateFunctionDeclaration (ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, + type_name_cstr, + clang_type, + storage, + is_inline); + + // if (template_param_infos.GetSize() > 0) + // { + // clang::FunctionTemplateDecl *func_template_decl = CreateFunctionTemplateDecl (containing_decl_ctx, + // function_decl, + // type_name_cstr, + // template_param_infos); + // + // CreateFunctionTemplateSpecializationInfo (function_decl, + // func_template_decl, + // template_param_infos); + // } + // Add the decl to our DIE to decl context map + assert (function_decl); + LinkDeclContextToDIE(function_decl, die); + if (!function_param_decls.empty()) + m_ast.SetFunctionParameters (function_decl, + &function_param_decls.front(), + function_param_decls.size()); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + if (!object_pointer_name.empty()) + { + metadata.SetObjectPtrName(object_pointer_name.c_str()); + if (log) + log->Printf ("Setting object pointer name: %s on function object %p.", + object_pointer_name.c_str(), + static_cast<void*>(function_decl)); + } + m_ast.SetMetadata (function_decl, metadata); + } + } + type_sp.reset( new Type (die.GetID(), + dwarf, + type_name_const_str, + 0, + NULL, + LLDB_INVALID_UID, + Type::eEncodingIsUID, + &decl, + clang_type, + Type::eResolveStateFull)); + assert(type_sp.get()); + } + break; + + case DW_TAG_array_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + DWARFFormValue type_die_form; + int64_t first_index = 0; + uint32_t byte_stride = 0; + uint32_t bit_stride = 0; + bool is_vector = false; + const size_t num_attributes = die.GetAttributes (attributes); + + if (num_attributes > 0) + { + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_type: type_die_form = form_value; break; + case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break; + case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; + case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break; + case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break; + case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; + case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_ordering: + case DW_AT_start_scope: + case DW_AT_visibility: + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_sibling: + break; + } + } + } + + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + + Type *element_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + + if (element_type) + { + std::vector<uint64_t> element_orders; + ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride); + if (byte_stride == 0 && bit_stride == 0) + byte_stride = element_type->GetByteSize(); + CompilerType array_element_type = element_type->GetForwardCompilerType (); + uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; + if (element_orders.size() > 0) + { + uint64_t num_elements = 0; + std::vector<uint64_t>::const_reverse_iterator pos; + std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend(); + for (pos = element_orders.rbegin(); pos != end; ++pos) + { + num_elements = *pos; + clang_type = m_ast.CreateArrayType (array_element_type, + num_elements, + is_vector); + array_element_type = clang_type; + array_element_bit_stride = num_elements ? + array_element_bit_stride * num_elements : + array_element_bit_stride; + } + } + else + { + clang_type = m_ast.CreateArrayType (array_element_type, 0, is_vector); + } + ConstString empty_name; + type_sp.reset( new Type (die.GetID(), + dwarf, + empty_name, + array_element_bit_stride / 8, + NULL, + DIERef(type_die_form).GetUID(), + Type::eEncodingIsUID, + &decl, + clang_type, + Type::eResolveStateFull)); + type_sp->SetEncodingType (element_type); + } + } + } + break; + + case DW_TAG_ptr_to_member_type: + { + DWARFFormValue type_die_form; + DWARFFormValue containing_type_die_form; + + const size_t num_attributes = die.GetAttributes (attributes); + + if (num_attributes > 0) { + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_type: + type_die_form = form_value; break; + case DW_AT_containing_type: + containing_type_die_form = form_value; break; + } + } + } + + Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form).GetUID()); + + CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType (); + CompilerType class_clang_type = class_type->GetLayoutCompilerType (); + + clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, pointee_clang_type); + + byte_size = clang_type.GetByteSize(nullptr); + + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL, + LLDB_INVALID_UID, Type::eEncodingIsUID, NULL, clang_type, + Type::eResolveStateForward)); + } + + break; + } + default: + dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", + die.GetOffset(), + tag, + DW_TAG_value_to_name(tag)); + break; + } + + if (type_sp.get()) + { + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope * symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit) + { + symbol_context_scope = sc.comp_unit; + } + else if (sc.function != NULL && sc_parent_die) + { + symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != NULL) + { + type_sp->SetSymbolContextScope(symbol_context_scope); + } + + // We are ready to put this type into the uniqued list up at the module level + type_list->Insert (type_sp); + + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + } + } + else if (type_ptr != DIE_IS_BEING_PARSED) + { + type_sp = type_ptr->shared_from_this(); + } + } + return type_sp; +} + +// DWARF parsing functions + +class DWARFASTParserClang::DelayedAddObjCClassProperty +{ +public: + DelayedAddObjCClassProperty(const CompilerType &class_opaque_type, + const char *property_name, + const CompilerType &property_opaque_type, // The property type is only required if you don't have an ivar decl + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + const ClangASTMetadata *metadata) : + m_class_opaque_type (class_opaque_type), + m_property_name (property_name), + m_property_opaque_type (property_opaque_type), + m_ivar_decl (ivar_decl), + m_property_setter_name (property_setter_name), + m_property_getter_name (property_getter_name), + m_property_attributes (property_attributes) + { + if (metadata != NULL) + { + m_metadata_ap.reset(new ClangASTMetadata()); + *m_metadata_ap = *metadata; + } + } + + DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs) + { + *this = rhs; + } + + DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs) + { + m_class_opaque_type = rhs.m_class_opaque_type; + m_property_name = rhs.m_property_name; + m_property_opaque_type = rhs.m_property_opaque_type; + m_ivar_decl = rhs.m_ivar_decl; + m_property_setter_name = rhs.m_property_setter_name; + m_property_getter_name = rhs.m_property_getter_name; + m_property_attributes = rhs.m_property_attributes; + + if (rhs.m_metadata_ap.get()) + { + m_metadata_ap.reset (new ClangASTMetadata()); + *m_metadata_ap = *rhs.m_metadata_ap; + } + return *this; + } + + bool + Finalize() + { + return ClangASTContext::AddObjCClassProperty (m_class_opaque_type, + m_property_name, + m_property_opaque_type, + m_ivar_decl, + m_property_setter_name, + m_property_getter_name, + m_property_attributes, + m_metadata_ap.get()); + } + +private: + CompilerType m_class_opaque_type; + const char *m_property_name; + CompilerType m_property_opaque_type; + clang::ObjCIvarDecl *m_ivar_decl; + const char *m_property_setter_name; + const char *m_property_getter_name; + uint32_t m_property_attributes; + std::unique_ptr<ClangASTMetadata> m_metadata_ap; +}; + +bool +DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die, + ClangASTContext::TemplateParameterInfos &template_param_infos) +{ + const dw_tag_t tag = die.Tag(); + + switch (tag) + { + case DW_TAG_template_type_parameter: + case DW_TAG_template_value_parameter: + { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes (attributes); + const char *name = NULL; + Type *lldb_type = NULL; + CompilerType clang_type; + uint64_t uval64 = 0; + bool uval64_valid = false; + if (num_attributes > 0) + { + DWARFFormValue form_value; + for (size_t i=0; i<num_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + + switch (attr) + { + case DW_AT_name: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + name = form_value.AsCString(); + break; + + case DW_AT_type: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + lldb_type = die.ResolveTypeUID(DIERef(form_value).GetUID()); + if (lldb_type) + clang_type = lldb_type->GetForwardCompilerType (); + } + break; + + case DW_AT_const_value: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + uval64_valid = true; + uval64 = form_value.Unsigned(); + } + break; + default: + break; + } + } + + clang::ASTContext *ast = m_ast.getASTContext(); + if (!clang_type) + clang_type = m_ast.GetBasicType(eBasicTypeVoid); + + if (clang_type) + { + bool is_signed = false; + if (name && name[0]) + template_param_infos.names.push_back(name); + else + template_param_infos.names.push_back(NULL); + + if (tag == DW_TAG_template_value_parameter && + lldb_type != NULL && + clang_type.IsIntegerType (is_signed) && + uval64_valid) + { + llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed); + template_param_infos.args.push_back (clang::TemplateArgument (*ast, + llvm::APSInt(apint), + ClangASTContext::GetQualType(clang_type))); + } + else + { + template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type))); + } + } + else + { + return false; + } + + } + } + return true; + + default: + break; + } + return false; +} + +bool +DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die, + ClangASTContext::TemplateParameterInfos &template_param_infos) +{ + + if (!parent_die) + return false; + + Args template_parameter_names; + for (DWARFDIE die = parent_die.GetFirstChild(); + die.IsValid(); + die = die.GetSibling()) + { + const dw_tag_t tag = die.Tag(); + + switch (tag) + { + case DW_TAG_template_type_parameter: + case DW_TAG_template_value_parameter: + ParseTemplateDIE (die, template_param_infos); + break; + + default: + break; + } + } + if (template_param_infos.args.empty()) + return false; + return template_param_infos.args.size() == template_param_infos.names.size(); +} + +bool +DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type) +{ + if (m_clang_ast_importer_ap) + return ClangASTContext::CanImport(compiler_type, GetClangASTImporter()); + else + return false; +} + +bool +DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type) +{ + if (CanCompleteType(compiler_type)) + { + if (ClangASTContext::Import(compiler_type, GetClangASTImporter())) + { + ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); + return true; + } + else + { + ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false); + } + } + return false; +} + +bool +DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, + lldb_private::Type *type, + CompilerType &clang_type) +{ + // Disable external storage for this type so we don't get anymore + // clang::ExternalASTSource queries for this type. + m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false); + + if (!die) + return false; + + const dw_tag_t tag = die.Tag(); + + SymbolFileDWARF *dwarf = die.GetDWARF(); + + Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log, + "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", + die.GetID(), + die.GetTagAsCString(), + type->GetName().AsCString()); + assert (clang_type); + DWARFAttributes attributes; + switch (tag) + { + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + { + LayoutInfo layout_info; + + { + if (die.HasChildren()) + { + LanguageType class_language = eLanguageTypeUnknown; + if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) + { + class_language = eLanguageTypeObjC; + // For objective C we don't start the definition when + // the class is created. + ClangASTContext::StartTagDeclarationDefinition (clang_type); + } + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) + { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } + else if (tag == DW_TAG_union_type) + { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } + else if (tag == DW_TAG_class_type) + { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } + + SymbolContext sc(die.GetLLDBCompileUnit()); + std::vector<clang::CXXBaseSpecifier *> base_classes; + std::vector<int> member_accessibilities; + bool is_a_class = false; + // Parse members and base classes first + DWARFDIECollection member_function_dies; + + DelayedPropertyList delayed_properties; + ParseChildMembers (sc, + die, + clang_type, + class_language, + base_classes, + member_accessibilities, + member_function_dies, + delayed_properties, + default_accessibility, + is_a_class, + layout_info); + + // Now parse any methods if there were any... + size_t num_functions = member_function_dies.Size(); + if (num_functions > 0) + { + for (size_t i=0; i<num_functions; ++i) + { + dwarf->ResolveType(member_function_dies.GetDIEAtIndex(i)); + } + } + + if (class_language == eLanguageTypeObjC) + { + ConstString class_name (clang_type.GetTypeName()); + if (class_name) + { + DIEArray method_die_offsets; + dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets); + + if (!method_die_offsets.empty()) + { + DWARFDebugInfo* debug_info = dwarf->DebugInfo(); + + const size_t num_matches = method_die_offsets.size(); + for (size_t i=0; i<num_matches; ++i) + { + const DIERef& die_ref = method_die_offsets[i]; + DWARFDIE method_die = debug_info->GetDIE (die_ref); + + if (method_die) + method_die.ResolveType (); + } + } + + for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end(); + pi != pe; + ++pi) + pi->Finalize(); + } + } + + // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we + // need to tell the clang type it is actually a class. + if (class_language != eLanguageTypeObjC) + { + if (is_a_class && tag_decl_kind != clang::TTK_Class) + m_ast.SetTagTypeKind (ClangASTContext::GetQualType(clang_type), clang::TTK_Class); + } + + // Since DW_TAG_structure_type gets used for both classes + // and structures, we may need to set any DW_TAG_member + // fields to have a "private" access if none was specified. + // When we parsed the child members we tracked that actual + // accessibility value for each DW_TAG_member in the + // "member_accessibilities" array. If the value for the + // member is zero, then it was set to the "default_accessibility" + // which for structs was "public". Below we correct this + // by setting any fields to "private" that weren't correctly + // set. + if (is_a_class && !member_accessibilities.empty()) + { + // This is a class and all members that didn't have + // their access specified are private. + m_ast.SetDefaultAccessForRecordFields (m_ast.GetAsRecordDecl(clang_type), + eAccessPrivate, + &member_accessibilities.front(), + member_accessibilities.size()); + } + + if (!base_classes.empty()) + { + // Make sure all base classes refer to complete types and not + // forward declarations. If we don't do this, clang will crash + // with an assertion in the call to clang_type.SetBaseClassesForClassType() + for (auto &base_class : base_classes) + { + clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); + if (type_source_info) + { + CompilerType base_class_type (&m_ast, type_source_info->getType().getAsOpaquePtr()); + if (base_class_type.GetCompleteType() == false) + { + auto module = dwarf->GetObjectFile()->GetModule(); + module->ReportError ( + ":: Class '%s' has a base class '%s' which does not have a complete definition.", + die.GetName(), + base_class_type.GetTypeName().GetCString()); + if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) + module->ReportError (":: Try compiling the source file with -fno-limit-debug-info."); + + // We have no choice other than to pretend that the base class + // is complete. If we don't do this, clang will crash when we + // call setBases() inside of "clang_type.SetBaseClassesForClassType()" + // below. Since we provide layout assistance, all ivars in this + // class and other classes will be fine, this is the best we can do + // short of crashing. + ClangASTContext::StartTagDeclarationDefinition (base_class_type); + ClangASTContext::CompleteTagDeclarationDefinition (base_class_type); + } + } + } + m_ast.SetBaseClassesForClassType (clang_type.GetOpaqueQualType(), + &base_classes.front(), + base_classes.size()); + + // Clang will copy each CXXBaseSpecifier in "base_classes" + // so we have to free them all. + ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(), + base_classes.size()); + } + } + } + + ClangASTContext::BuildIndirectFields (clang_type); + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + + if (!layout_info.field_offsets.empty() || + !layout_info.base_offsets.empty() || + !layout_info.vbase_offsets.empty() ) + { + if (type) + layout_info.bit_size = type->GetByteSize() * 8; + if (layout_info.bit_size == 0) + layout_info.bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + + clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + { + if (log) + { + ModuleSP module_sp = dwarf->GetObjectFile()->GetModule(); + + if (module_sp) + { + module_sp->LogMessage (log, + "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])", + static_cast<void*>(clang_type.GetOpaqueQualType()), + static_cast<void*>(record_decl), + layout_info.bit_size, + layout_info.alignment, + static_cast<uint32_t>(layout_info.field_offsets.size()), + static_cast<uint32_t>(layout_info.base_offsets.size()), + static_cast<uint32_t>(layout_info.vbase_offsets.size())); + + uint32_t idx; + { + llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos, + end = layout_info.field_offsets.end(); + for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx) + { + module_sp->LogMessage(log, + "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) field[%u] = { bit_offset=%u, name='%s' }", + static_cast<void *>(clang_type.GetOpaqueQualType()), + idx, + static_cast<uint32_t>(pos->second), + pos->first->getNameAsString().c_str()); + } + } + + { + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, + base_end = layout_info.base_offsets.end(); + for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; ++base_pos, ++idx) + { + module_sp->LogMessage(log, + "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) base[%u] = { byte_offset=%u, name='%s' }", + clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(), + base_pos->first->getNameAsString().c_str()); + } + } + { + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos, + vbase_end = layout_info.vbase_offsets.end(); + for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; ++vbase_pos, ++idx) + { + module_sp->LogMessage(log, + "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) vbase[%u] = { byte_offset=%u, name='%s' }", + static_cast<void *>(clang_type.GetOpaqueQualType()), idx, + static_cast<uint32_t>(vbase_pos->second.getQuantity()), + vbase_pos->first->getNameAsString().c_str()); + } + } + + } + } + m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); + } + } + } + + return (bool)clang_type; + + case DW_TAG_enumeration_type: + ClangASTContext::StartTagDeclarationDefinition (clang_type); + if (die.HasChildren()) + { + SymbolContext sc(die.GetLLDBCompileUnit()); + bool is_signed = false; + clang_type.IsIntegerType(is_signed); + ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die); + } + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + return (bool)clang_type; + + default: + assert(false && "not a forward clang type decl!"); + break; + } + + return false; +} + +std::vector<DWARFDIE> +DWARFASTParserClang::GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) +{ + std::vector<DWARFDIE> result; + for (auto it = m_decl_ctx_to_die.find((clang::DeclContext *)decl_context.GetOpaqueDeclContext()); it != m_decl_ctx_to_die.end(); it++) + result.push_back(it->second); + return result; +} + +CompilerDecl +DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die) +{ + clang::Decl *clang_decl = GetClangDeclForDIE(die); + if (clang_decl != nullptr) + return CompilerDecl(&m_ast, clang_decl); + return CompilerDecl(); +} + +CompilerDeclContext +DWARFASTParserClang::GetDeclContextForUIDFromDWARF (const DWARFDIE &die) +{ + clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (die); + if (clang_decl_ctx) + return CompilerDeclContext(&m_ast, clang_decl_ctx); + return CompilerDeclContext(); +} + +CompilerDeclContext +DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) +{ + clang::DeclContext *clang_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); + if (clang_decl_ctx) + return CompilerDeclContext(&m_ast, clang_decl_ctx); + return CompilerDeclContext(); +} + +size_t +DWARFASTParserClang::ParseChildEnumerators (const SymbolContext& sc, + lldb_private::CompilerType &clang_type, + bool is_signed, + uint32_t enumerator_byte_size, + const DWARFDIE &parent_die) +{ + if (!parent_die) + return 0; + + size_t enumerators_added = 0; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + const dw_tag_t tag = die.Tag(); + if (tag == DW_TAG_enumerator) + { + DWARFAttributes attributes; + const size_t num_child_attributes = die.GetAttributes(attributes); + if (num_child_attributes > 0) + { + const char *name = NULL; + bool got_value = false; + int64_t enum_value = 0; + Declaration decl; + + uint32_t i; + for (i=0; i<num_child_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_const_value: + got_value = true; + if (is_signed) + enum_value = form_value.Signed(); + else + enum_value = form_value.Unsigned(); + break; + + case DW_AT_name: + name = form_value.AsCString(); + break; + + case DW_AT_description: + default: + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_sibling: + break; + } + } + } + + if (name && name[0] && got_value) + { + m_ast.AddEnumerationValueToEnumerationType (clang_type.GetOpaqueQualType(), + m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()), + decl, + name, + enum_value, + enumerator_byte_size * 8); + ++enumerators_added; + } + } + } + } + return enumerators_added; +} + +#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) + +class DIEStack +{ +public: + + void Push (const DWARFDIE &die) + { + m_dies.push_back (die); + } + + + void LogDIEs (Log *log) + { + StreamString log_strm; + const size_t n = m_dies.size(); + log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n); + for (size_t i=0; i<n; i++) + { + std::string qualified_name; + const DWARFDIE &die = m_dies[i]; + die.GetQualifiedName(qualified_name); + log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", + (uint64_t)i, + die.GetOffset(), + die.GetTagAsCString(), + qualified_name.c_str()); + } + log->PutCString(log_strm.GetData()); + } + void Pop () + { + m_dies.pop_back(); + } + + class ScopedPopper + { + public: + ScopedPopper (DIEStack &die_stack) : + m_die_stack (die_stack), + m_valid (false) + { + } + + void + Push (const DWARFDIE &die) + { + m_valid = true; + m_die_stack.Push (die); + } + + ~ScopedPopper () + { + if (m_valid) + m_die_stack.Pop(); + } + + + + protected: + DIEStack &m_die_stack; + bool m_valid; + }; + +protected: + typedef std::vector<DWARFDIE> Stack; + Stack m_dies; +}; +#endif + +Function * +DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, + const DWARFDIE &die) +{ + DWARFRangeList func_ranges; + const char *name = NULL; + const char *mangled = NULL; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFExpression frame_base(die.GetCU()); + + const dw_tag_t tag = die.Tag(); + + if (tag != DW_TAG_subprogram) + return NULL; + + if (die.GetDIENamesAndRanges (name, + mangled, + func_ranges, + decl_file, + decl_line, + decl_column, + call_file, + call_line, + call_column, + &frame_base)) + { + + // Union of all ranges in the function DIE (if the function is discontiguous) + AddressRange func_range; + lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0); + lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0); + if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) + { + ModuleSP module_sp (die.GetModule()); + func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList()); + if (func_range.GetBaseAddress().IsValid()) + func_range.SetByteSize(highest_func_addr - lowest_func_addr); + } + + if (func_range.GetBaseAddress().IsValid()) + { + Mangled func_name; + if (mangled) + func_name.SetValue(ConstString(mangled), true); + else if (die.GetParent().Tag() == DW_TAG_compile_unit && + Language::LanguageIsCPlusPlus(die.GetLanguage()) && + name && strcmp(name, "main") != 0) + { + // If the mangled name is not present in the DWARF, generate the demangled name + // using the decl context. We skip if the function is "main" as its name is + // never mangled. + bool is_static = false; + bool is_variadic = false; + unsigned type_quals = 0; + std::vector<CompilerType> param_types; + std::vector<clang::ParmVarDecl*> param_decls; + DWARFDeclContext decl_ctx; + StreamString sstr; + + die.GetDWARFDeclContext(decl_ctx); + sstr << decl_ctx.GetQualifiedName(); + + clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); + ParseChildParameters(sc, + containing_decl_ctx, + die, + true, + is_static, + is_variadic, + param_types, + param_decls, + type_quals); + sstr << "("; + for (size_t i = 0; i < param_types.size(); i++) + { + if (i > 0) + sstr << ", "; + sstr << param_types[i].GetTypeName(); + } + if (is_variadic) + sstr << ", ..."; + sstr << ")"; + if (type_quals & clang::Qualifiers::Const) + sstr << " const"; + + func_name.SetValue(ConstString(sstr.GetData()), false); + } + else + func_name.SetValue(ConstString(name), false); + + FunctionSP func_sp; + std::unique_ptr<Declaration> decl_ap; + if (decl_file != 0 || decl_line != 0 || decl_column != 0) + decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), + decl_line, + decl_column)); + + SymbolFileDWARF *dwarf = die.GetDWARF(); + // Supply the type _only_ if it has already been parsed + Type *func_type = dwarf->GetDIEToType().lookup (die.GetDIE()); + + assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + + if (dwarf->FixupAddress (func_range.GetBaseAddress())) + { + const user_id_t func_user_id = die.GetID(); + func_sp.reset(new Function (sc.comp_unit, + func_user_id, // UserID is the DIE offset + func_user_id, + func_name, + func_type, + func_range)); // first address range + + if (func_sp.get() != NULL) + { + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + return func_sp.get(); + } + } + } + } + return NULL; +} + + +bool +DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, + const DWARFDIE &parent_die, + CompilerType &class_clang_type, + const LanguageType class_language, + std::vector<clang::CXXBaseSpecifier *>& base_classes, + std::vector<int>& member_accessibilities, + DWARFDIECollection& member_function_dies, + DelayedPropertyList& delayed_properties, + AccessType& default_accessibility, + bool &is_a_class, + LayoutInfo &layout_info) +{ + if (!parent_die) + return 0; + + uint32_t member_idx = 0; + BitfieldInfo last_field_info; + + ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); + ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem()); + if (ast == nullptr) + return 0; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + dw_tag_t tag = die.Tag(); + + switch (tag) + { + case DW_TAG_member: + case DW_TAG_APPLE_property: + { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes (attributes); + if (num_attributes > 0) + { + Declaration decl; + //DWARFExpression location; + const char *name = NULL; + const char *prop_name = NULL; + const char *prop_getter_name = NULL; + const char *prop_setter_name = NULL; + uint32_t prop_attributes = 0; + + + bool is_artificial = false; + DWARFFormValue encoding_form; + AccessType accessibility = eAccessNone; + uint32_t member_byte_offset = UINT32_MAX; + size_t byte_size = 0; + size_t bit_offset = 0; + size_t bit_size = 0; + bool is_external = false; // On DW_TAG_members, this means the member is static + uint32_t i; + for (i=0; i<num_attributes && !is_artificial; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: name = form_value.AsCString(); break; + case DW_AT_type: encoding_form = form_value; break; + case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break; + case DW_AT_bit_size: bit_size = form_value.Unsigned(); break; + case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + { + Value initialValue(0); + Value memberOffset(0); + const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data(); + uint32_t block_length = form_value.Unsigned(); + uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); + if (DWARFExpression::Evaluate(NULL, // ExecutionContext * + NULL, // ClangExpressionVariableList * + NULL, // ClangExpressionDeclMap * + NULL, // RegisterContext * + module_sp, + debug_info_data, + die.GetCU(), + block_offset, + block_length, + eRegisterKindDWARF, + &initialValue, + memberOffset, + NULL)) + { + member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + } + } + else + { + // With DWARF 3 and later, if the value is an integer constant, + // this form value is the offset in bytes from the beginning + // of the containing entity. + member_byte_offset = form_value.Unsigned(); + } + break; + + case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; + case DW_AT_APPLE_property_name: prop_name = form_value.AsCString(); + break; + case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString(); + break; + case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString(); + break; + case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break; + case DW_AT_external: is_external = form_value.Boolean(); break; + + default: + case DW_AT_declaration: + case DW_AT_description: + case DW_AT_mutable: + case DW_AT_visibility: + case DW_AT_sibling: + break; + } + } + } + + if (prop_name) + { + ConstString fixed_getter; + ConstString fixed_setter; + + // Check if the property getter/setter were provided as full + // names. We want basenames, so we extract them. + + if (prop_getter_name && prop_getter_name[0] == '-') + { + ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true); + prop_getter_name = prop_getter_method.GetSelector().GetCString(); + } + + if (prop_setter_name && prop_setter_name[0] == '-') + { + ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true); + prop_setter_name = prop_setter_method.GetSelector().GetCString(); + } + + // If the names haven't been provided, they need to be + // filled in. + + if (!prop_getter_name) + { + prop_getter_name = prop_name; + } + if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly)) + { + StreamString ss; + + ss.Printf("set%c%s:", + toupper(prop_name[0]), + &prop_name[1]); + + fixed_setter.SetCString(ss.GetData()); + prop_setter_name = fixed_setter.GetCString(); + } + } + + // Clang has a DWARF generation bug where sometimes it + // represents fields that are references with bad byte size + // and bit size/offset information such as: + // + // DW_AT_byte_size( 0x00 ) + // DW_AT_bit_size( 0x40 ) + // DW_AT_bit_offset( 0xffffffffffffffc0 ) + // + // So check the bit offset to make sure it is sane, and if + // the values are not sane, remove them. If we don't do this + // then we will end up with a crash if we try to use this + // type in an expression when clang becomes unhappy with its + // recycled debug info. + + if (bit_offset > 128) + { + bit_size = 0; + bit_offset = 0; + } + + // FIXME: Make Clang ignore Objective-C accessibility for expressions + if (class_language == eLanguageTypeObjC || + class_language == eLanguageTypeObjC_plus_plus) + accessibility = eAccessNone; + + if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name)) + { + // Not all compilers will mark the vtable pointer + // member as artificial (llvm-gcc). We can't have + // the virtual members in our classes otherwise it + // throws off all child offsets since we end up + // having and extra pointer sized member in our + // class layouts. + is_artificial = true; + } + + // Handle static members + if (is_external && member_byte_offset == UINT32_MAX) + { + Type *var_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + + if (var_type) + { + if (accessibility == eAccessNone) + accessibility = eAccessPublic; + ClangASTContext::AddVariableToRecordType (class_clang_type, + name, + var_type->GetLayoutCompilerType (), + accessibility); + } + break; + } + + if (is_artificial == false) + { + Type *member_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + + clang::FieldDecl *field_decl = NULL; + if (tag == DW_TAG_member) + { + if (member_type) + { + if (accessibility == eAccessNone) + accessibility = default_accessibility; + member_accessibilities.push_back(accessibility); + + uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); + if (bit_size > 0) + { + + BitfieldInfo this_field_info; + this_field_info.bit_offset = field_bit_offset; + this_field_info.bit_size = bit_size; + + ///////////////////////////////////////////////////////////// + // How to locate a field given the DWARF debug information + // + // AT_byte_size indicates the size of the word in which the + // bit offset must be interpreted. + // + // AT_data_member_location indicates the byte offset of the + // word from the base address of the structure. + // + // AT_bit_offset indicates how many bits into the word + // (according to the host endianness) the low-order bit of + // the field starts. AT_bit_offset can be negative. + // + // AT_bit_size indicates the size of the field in bits. + ///////////////////////////////////////////////////////////// + + if (byte_size == 0) + byte_size = member_type->GetByteSize(); + + if (die.GetDWARF()->GetObjectFile()->GetByteOrder() == eByteOrderLittle) + { + this_field_info.bit_offset += byte_size * 8; + this_field_info.bit_offset -= (bit_offset + bit_size); + } + else + { + this_field_info.bit_offset += bit_offset; + } + + // Update the field bit offset we will report for layout + field_bit_offset = this_field_info.bit_offset; + + // If the member to be emitted did not start on a character boundary and there is + // empty space between the last field and this one, then we need to emit an + // anonymous member filling up the space up to its start. There are three cases + // here: + // + // 1 If the previous member ended on a character boundary, then we can emit an + // anonymous member starting at the most recent character boundary. + // + // 2 If the previous member did not end on a character boundary and the distance + // from the end of the previous member to the current member is less than a + // word width, then we can emit an anonymous member starting right after the + // previous member and right before this member. + // + // 3 If the previous member did not end on a character boundary and the distance + // from the end of the previous member to the current member is greater than + // or equal a word width, then we act as in Case 1. + + const uint64_t character_width = 8; + const uint64_t word_width = 32; + + // Objective-C has invalid DW_AT_bit_offset values in older versions + // of clang, so we have to be careful and only insert unnamed bitfields + // if we have a new enough clang. + bool detect_unnamed_bitfields = true; + + if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus) + detect_unnamed_bitfields = die.GetCU()->Supports_unnamed_objc_bitfields (); + + if (detect_unnamed_bitfields) + { + BitfieldInfo anon_field_info; + + if ((this_field_info.bit_offset % character_width) != 0) // not char aligned + { + uint64_t last_field_end = 0; + + if (last_field_info.IsValid()) + last_field_end = last_field_info.bit_offset + last_field_info.bit_size; + + if (this_field_info.bit_offset != last_field_end) + { + if (((last_field_end % character_width) == 0) || // case 1 + (this_field_info.bit_offset - last_field_end >= word_width)) // case 3 + { + anon_field_info.bit_size = this_field_info.bit_offset % character_width; + anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size; + } + else // case 2 + { + anon_field_info.bit_size = this_field_info.bit_offset - last_field_end; + anon_field_info.bit_offset = last_field_end; + } + } + } + + if (anon_field_info.IsValid()) + { + clang::FieldDecl *unnamed_bitfield_decl = + ClangASTContext::AddFieldToRecordType (class_clang_type, + NULL, + m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), + accessibility, + anon_field_info.bit_size); + + layout_info.field_offsets.insert( + std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); + } + } + last_field_info = this_field_info; + } + else + { + last_field_info.Clear(); + } + + CompilerType member_clang_type = member_type->GetLayoutCompilerType (); + if (!member_clang_type.IsCompleteType()) + member_clang_type.GetCompleteType(); + + { + // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>). + // If the current field is at the end of the structure, then there is definitely no room for extra + // elements and we override the type to array[0]. + + CompilerType member_array_element_type; + uint64_t member_array_size; + bool member_array_is_incomplete; + + if (member_clang_type.IsArrayType(&member_array_element_type, + &member_array_size, + &member_array_is_incomplete) && + !member_array_is_incomplete) + { + uint64_t parent_byte_size = parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); + + if (member_byte_offset >= parent_byte_size) + { + if (member_array_size != 1) + { + module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64, + die.GetID(), + name, + encoding_form.Reference(), + parent_die.GetID()); + } + + member_clang_type = m_ast.CreateArrayType(member_array_element_type, 0, false); + } + } + } + + if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false) + { + if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) + module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info", + parent_die.GetOffset(), + parent_die.GetName(), + die.GetOffset(), + name); + else + module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", + parent_die.GetOffset(), + parent_die.GetName(), + die.GetOffset(), + name, + sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); + // We have no choice other than to pretend that the member class + // is complete. If we don't do this, clang will crash when trying + // to layout the class. Since we provide layout assistance, all + // ivars in this class and other classes will be fine, this is + // the best we can do short of crashing. + ClangASTContext::StartTagDeclarationDefinition(member_clang_type); + ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type); + } + + field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type, + name, + member_clang_type, + accessibility, + bit_size); + + m_ast.SetMetadataAsUserID (field_decl, die.GetID()); + + layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset)); + } + else + { + if (name) + module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed", + die.GetID(), + name, + encoding_form.Reference()); + else + module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed", + die.GetID(), + encoding_form.Reference()); + } + } + + if (prop_name != NULL && member_type) + { + clang::ObjCIvarDecl *ivar_decl = NULL; + + if (field_decl) + { + ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl); + assert (ivar_decl != NULL); + } + + ClangASTMetadata metadata; + metadata.SetUserID (die.GetID()); + delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type, + prop_name, + member_type->GetLayoutCompilerType (), + ivar_decl, + prop_setter_name, + prop_getter_name, + prop_attributes, + &metadata)); + + if (ivar_decl) + m_ast.SetMetadataAsUserID (ivar_decl, die.GetID()); + } + } + } + ++member_idx; + } + break; + + case DW_TAG_subprogram: + // Let the type parsing code handle this one for us. + member_function_dies.Append (die); + break; + + case DW_TAG_inheritance: + { + is_a_class = true; + if (default_accessibility == eAccessNone) + default_accessibility = eAccessPrivate; + // TODO: implement DW_TAG_inheritance type parsing + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes (attributes); + if (num_attributes > 0) + { + Declaration decl; + DWARFExpression location(die.GetCU()); + DWARFFormValue encoding_form; + AccessType accessibility = default_accessibility; + bool is_virtual = false; + bool is_base_of_class = true; + off_t member_byte_offset = 0; + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_type: encoding_form = form_value; break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + { + Value initialValue(0); + Value memberOffset(0); + const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data(); + uint32_t block_length = form_value.Unsigned(); + uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); + if (DWARFExpression::Evaluate (NULL, + NULL, + NULL, + NULL, + module_sp, + debug_info_data, + die.GetCU(), + block_offset, + block_length, + eRegisterKindDWARF, + &initialValue, + memberOffset, + NULL)) + { + member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + } + } + else + { + // With DWARF 3 and later, if the value is an integer constant, + // this form value is the offset in bytes from the beginning + // of the containing entity. + member_byte_offset = form_value.Unsigned(); + } + break; + + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + + case DW_AT_virtuality: + is_virtual = form_value.Boolean(); + break; + + case DW_AT_sibling: + break; + + default: + break; + } + } + } + + Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + if (base_class_type == NULL) + { + module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message", + die.GetOffset(), + encoding_form.Reference(), + parent_die.GetOffset()); + break; + } + + CompilerType base_class_clang_type = base_class_type->GetFullCompilerType (); + assert (base_class_clang_type); + if (class_language == eLanguageTypeObjC) + { + ast->SetObjCSuperClass(class_clang_type, base_class_clang_type); + } + else + { + base_classes.push_back (ast->CreateBaseClassSpecifier (base_class_clang_type.GetOpaqueQualType(), + accessibility, + is_virtual, + is_base_of_class)); + + if (is_virtual) + { + // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't + // give us a constant offset, but gives us a DWARF expressions that requires an actual object + // in memory. the DW_AT_data_member_location for a virtual base class looks like: + // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus ) + // Given this, there is really no valid response we can give to clang for virtual base + // class offsets, and this should eventually be removed from LayoutRecordType() in the external + // AST source in clang. + } + else + { + layout_info.base_offsets.insert( + std::make_pair(ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()), + clang::CharUnits::fromQuantity(member_byte_offset))); + } + } + } + } + break; + + default: + break; + } + } + + return true; +} + + +size_t +DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, + clang::DeclContext *containing_decl_ctx, + const DWARFDIE &parent_die, + bool skip_artificial, + bool &is_static, + bool &is_variadic, + std::vector<CompilerType>& function_param_types, + std::vector<clang::ParmVarDecl*>& function_param_decls, + unsigned &type_quals) +{ + if (!parent_die) + return 0; + + size_t arg_idx = 0; + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + const dw_tag_t tag = die.Tag(); + switch (tag) + { + case DW_TAG_formal_parameter: + { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + const char *name = NULL; + Declaration decl; + DWARFFormValue param_type_die_form; + bool is_artificial = false; + // one of None, Auto, Register, Extern, Static, PrivateExtern + + clang::StorageClass storage = clang::SC_None; + uint32_t i; + for (i=0; i<num_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; + case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; + case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_name: name = form_value.AsCString(); + break; + case DW_AT_type: param_type_die_form = form_value; break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; + case DW_AT_location: + // if (form_value.BlockData()) + // { + // const DWARFDataExtractor& debug_info_data = debug_info(); + // uint32_t block_length = form_value.Unsigned(); + // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length); + // } + // else + // { + // } + // break; + case DW_AT_const_value: + case DW_AT_default_value: + case DW_AT_description: + case DW_AT_endianity: + case DW_AT_is_optional: + case DW_AT_segment: + case DW_AT_variable_parameter: + default: + case DW_AT_abstract_origin: + case DW_AT_sibling: + break; + } + } + } + + bool skip = false; + if (skip_artificial) + { + if (is_artificial) + { + // In order to determine if a C++ member function is + // "const" we have to look at the const-ness of "this"... + // Ugly, but that + if (arg_idx == 0) + { + if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) + { + // Often times compilers omit the "this" name for the + // specification DIEs, so we can't rely upon the name + // being in the formal parameter DIE... + if (name == NULL || ::strcmp(name, "this")==0) + { + Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form).GetUID()); + if (this_type) + { + uint32_t encoding_mask = this_type->GetEncodingMask(); + if (encoding_mask & Type::eEncodingIsPointerUID) + { + is_static = false; + + if (encoding_mask & (1u << Type::eEncodingIsConstUID)) + type_quals |= clang::Qualifiers::Const; + if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) + type_quals |= clang::Qualifiers::Volatile; + } + } + } + } + } + skip = true; + } + else + { + + // HACK: Objective C formal parameters "self" and "_cmd" + // are not marked as artificial in the DWARF... + CompileUnit *comp_unit = die.GetLLDBCompileUnit(); + if (comp_unit) + { + switch (comp_unit->GetLanguage()) + { + case eLanguageTypeObjC: + case eLanguageTypeObjC_plus_plus: + if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0)) + skip = true; + break; + default: + break; + } + } + } + } + + if (!skip) + { + Type *type = die.ResolveTypeUID(DIERef(param_type_die_form).GetUID()); + if (type) + { + function_param_types.push_back (type->GetForwardCompilerType ()); + + clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (name, + type->GetForwardCompilerType (), + storage); + assert(param_var_decl); + function_param_decls.push_back(param_var_decl); + + m_ast.SetMetadataAsUserID (param_var_decl, die.GetID()); + } + } + } + arg_idx++; + } + break; + + case DW_TAG_unspecified_parameters: + is_variadic = true; + break; + + case DW_TAG_template_type_parameter: + case DW_TAG_template_value_parameter: + // The one caller of this was never using the template_param_infos, + // and the local variable was taking up a large amount of stack space + // in SymbolFileDWARF::ParseType() so this was removed. If we ever need + // the template params back, we can add them back. + // ParseTemplateDIE (dwarf_cu, die, template_param_infos); + break; + + default: + break; + } + } + return arg_idx; +} + +void +DWARFASTParserClang::ParseChildArrayInfo (const SymbolContext& sc, + const DWARFDIE &parent_die, + int64_t& first_index, + std::vector<uint64_t>& element_orders, + uint32_t& byte_stride, + uint32_t& bit_stride) +{ + if (!parent_die) + return; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + const dw_tag_t tag = die.Tag(); + switch (tag) + { + case DW_TAG_subrange_type: + { + DWARFAttributes attributes; + const size_t num_child_attributes = die.GetAttributes(attributes); + if (num_child_attributes > 0) + { + uint64_t num_elements = 0; + uint64_t lower_bound = 0; + uint64_t upper_bound = 0; + bool upper_bound_valid = false; + uint32_t i; + for (i=0; i<num_child_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + break; + + case DW_AT_count: + num_elements = form_value.Unsigned(); + break; + + case DW_AT_bit_stride: + bit_stride = form_value.Unsigned(); + break; + + case DW_AT_byte_stride: + byte_stride = form_value.Unsigned(); + break; + + case DW_AT_lower_bound: + lower_bound = form_value.Unsigned(); + break; + + case DW_AT_upper_bound: + upper_bound_valid = true; + upper_bound = form_value.Unsigned(); + break; + + default: + case DW_AT_abstract_origin: + case DW_AT_accessibility: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_declaration: + case DW_AT_description: + case DW_AT_sibling: + case DW_AT_threads_scaled: + case DW_AT_type: + case DW_AT_visibility: + break; + } + } + } + + if (num_elements == 0) + { + if (upper_bound_valid && upper_bound >= lower_bound) + num_elements = upper_bound - lower_bound + 1; + } + + element_orders.push_back (num_elements); + } + } + break; + } + } +} + +Type * +DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die) +{ + if (die) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + DWARFFormValue type_die_form; + for (size_t i = 0; i < num_attributes; ++i) + { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + + if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) + return dwarf->ResolveTypeUID(DIERef(form_value).GetUID()); + } + } + } + + return nullptr; +} + +clang::Decl * +DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) +{ + if (!die) + return nullptr; + + switch (die.Tag()) + { + case DW_TAG_variable: + case DW_TAG_constant: + case DW_TAG_formal_parameter: + case DW_TAG_imported_declaration: + case DW_TAG_imported_module: + break; + default: + return nullptr; + } + + DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE()); + if (cache_pos != m_die_to_decl.end()) + return cache_pos->second; + + if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) + { + clang::Decl *decl = GetClangDeclForDIE(spec_die); + m_die_to_decl[die.GetDIE()] = decl; + m_decl_to_die[decl].insert(die.GetDIE()); + return decl; + } + + clang::Decl *decl = nullptr; + switch (die.Tag()) + { + case DW_TAG_variable: + case DW_TAG_constant: + case DW_TAG_formal_parameter: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + Type *type = GetTypeForDIE(die); + const char *name = die.GetName(); + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + decl = m_ast.CreateVariableDeclaration( + decl_context, + name, + ClangASTContext::GetQualType(type->GetForwardCompilerType())); + break; + } + case DW_TAG_imported_declaration: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + + if (dwarf->UserIDMatches(imported_uid)) + { + CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid); + if (imported_decl) + { + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)imported_decl.GetOpaqueDecl())) + decl = m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl); + } + } + break; + } + case DW_TAG_imported_module: + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + + if (dwarf->UserIDMatches(imported_uid)) + { + CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid); + if (imported_decl) + { + clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl)) + decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl); + } + } + break; + } + default: + break; + } + + m_die_to_decl[die.GetDIE()] = decl; + m_decl_to_die[decl].insert(die.GetDIE()); + + return decl; +} + +clang::DeclContext * +DWARFASTParserClang::GetClangDeclContextForDIE (const DWARFDIE &die) +{ + if (die) + { + clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE (die); + if (decl_ctx) + return decl_ctx; + + bool try_parsing_type = true; + switch (die.Tag()) + { + case DW_TAG_compile_unit: + decl_ctx = m_ast.GetTranslationUnitDecl(); + try_parsing_type = false; + break; + + case DW_TAG_namespace: + decl_ctx = ResolveNamespaceDIE (die); + try_parsing_type = false; + break; + + case DW_TAG_lexical_block: + decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die); + try_parsing_type = false; + break; + + default: + break; + } + + if (decl_ctx == nullptr && try_parsing_type) + { + Type* type = die.GetDWARF()->ResolveType (die); + if (type) + decl_ctx = GetCachedClangDeclContextForDIE (die); + } + + if (decl_ctx) + { + LinkDeclContextToDIE (decl_ctx, die); + return decl_ctx; + } + } + return nullptr; +} + +clang::BlockDecl * +DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die) +{ + if (die && die.Tag() == DW_TAG_lexical_block) + { + clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]); + + if (!decl) + { + DWARFDIE decl_context_die; + clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die); + decl = m_ast.CreateBlockDeclaration(decl_context); + + if (decl) + LinkDeclContextToDIE((clang::DeclContext *)decl, die); + } + + return decl; + } + return nullptr; +} + +clang::NamespaceDecl * +DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die) +{ + if (die && die.Tag() == DW_TAG_namespace) + { + // See if we already parsed this namespace DIE and associated it with a + // uniqued namespace declaration + clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]); + if (namespace_decl) + return namespace_decl; + else + { + const char *namespace_name = die.GetName(); + clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); + namespace_decl = m_ast.GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx); + Log *log = nullptr;// (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); + if (log) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (namespace_name) + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", + static_cast<void*>(m_ast.getASTContext()), + die.GetID(), + namespace_name, + static_cast<void*>(namespace_decl), + static_cast<void*>(namespace_decl->getOriginalNamespace())); + } + else + { + dwarf->GetObjectFile()->GetModule()->LogMessage (log, + "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", + static_cast<void*>(m_ast.getASTContext()), + die.GetID(), + static_cast<void*>(namespace_decl), + static_cast<void*>(namespace_decl->getOriginalNamespace())); + } + } + + if (namespace_decl) + LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); + return namespace_decl; + } + } + return nullptr; +} + +clang::DeclContext * +DWARFASTParserClang::GetClangDeclContextContainingDIE (const DWARFDIE &die, + DWARFDIE *decl_ctx_die_copy) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + + DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE (die); + + if (decl_ctx_die_copy) + *decl_ctx_die_copy = decl_ctx_die; + + if (decl_ctx_die) + { + clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (decl_ctx_die); + if (clang_decl_ctx) + return clang_decl_ctx; + } + return m_ast.GetTranslationUnitDecl(); +} + +clang::DeclContext * +DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die) +{ + if (die) + { + DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE()); + if (pos != m_die_to_decl_ctx.end()) + return pos->second; + } + return nullptr; +} + +void +DWARFASTParserClang::LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die) +{ + m_die_to_decl_ctx[die.GetDIE()] = decl_ctx; + // There can be many DIEs for a single decl context + //m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE()); + m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die)); +} + +bool +DWARFASTParserClang::CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die, + const DWARFDIE &dst_class_die, + lldb_private::Type *class_type, + DWARFDIECollection &failures) +{ + if (!class_type || !src_class_die || !dst_class_die) + return false; + if (src_class_die.Tag() != dst_class_die.Tag()) + return false; + + // We need to complete the class type so we can get all of the method types + // parsed so we can then unique those types to their equivalent counterparts + // in "dst_cu" and "dst_class_die" + class_type->GetFullCompilerType (); + + DWARFDIE src_die; + DWARFDIE dst_die; + UniqueCStringMap<DWARFDIE> src_name_to_die; + UniqueCStringMap<DWARFDIE> dst_name_to_die; + UniqueCStringMap<DWARFDIE> src_name_to_die_artificial; + UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial; + for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); src_die = src_die.GetSibling()) + { + if (src_die.Tag() == DW_TAG_subprogram) + { + // Make sure this is a declaration and not a concrete instance by looking + // for DW_AT_declaration set to 1. Sometimes concrete function instances + // are placed inside the class definitions and shouldn't be included in + // the list of things are are tracking here. + if (src_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) + { + const char *src_name = src_die.GetMangledName (); + if (src_name) + { + ConstString src_const_name(src_name); + if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) + src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die); + else + src_name_to_die.Append(src_const_name.GetCString(), src_die); + } + } + } + } + for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); dst_die = dst_die.GetSibling()) + { + if (dst_die.Tag() == DW_TAG_subprogram) + { + // Make sure this is a declaration and not a concrete instance by looking + // for DW_AT_declaration set to 1. Sometimes concrete function instances + // are placed inside the class definitions and shouldn't be included in + // the list of things are are tracking here. + if (dst_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) + { + const char *dst_name = dst_die.GetMangledName (); + if (dst_name) + { + ConstString dst_const_name(dst_name); + if ( dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) + dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die); + else + dst_name_to_die.Append(dst_const_name.GetCString(), dst_die); + } + } + } + } + const uint32_t src_size = src_name_to_die.GetSize (); + const uint32_t dst_size = dst_name_to_die.GetSize (); + Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION)); + + // Is everything kosher so we can go through the members at top speed? + bool fast_path = true; + + if (src_size != dst_size) + { + if (src_size != 0 && dst_size != 0) + { + if (log) + log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)", + src_class_die.GetOffset(), + dst_class_die.GetOffset(), + src_size, + dst_size); + } + + fast_path = false; + } + + uint32_t idx; + + if (fast_path) + { + for (idx = 0; idx < src_size; ++idx) + { + src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); + dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); + + if (src_die.Tag() != dst_die.Tag()) + { + if (log) + log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), + dst_class_die.GetOffset(), + src_die.GetOffset(), + src_die.GetTagAsCString(), + dst_die.GetOffset(), + dst_die.GetTagAsCString()); + fast_path = false; + } + + const char *src_name = src_die.GetMangledName (); + const char *dst_name = dst_die.GetMangledName (); + + // Make sure the names match + if (src_name == dst_name || (strcmp (src_name, dst_name) == 0)) + continue; + + if (log) + log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), + dst_class_die.GetOffset(), + src_die.GetOffset(), + src_name, + dst_die.GetOffset(), + dst_name); + + fast_path = false; + } + } + + DWARFASTParserClang *src_dwarf_ast_parser = (DWARFASTParserClang *)src_die.GetDWARFParser(); + DWARFASTParserClang *dst_dwarf_ast_parser = (DWARFASTParserClang *)dst_die.GetDWARFParser(); + + // Now do the work of linking the DeclContexts and Types. + if (fast_path) + { + // We can do this quickly. Just run across the tables index-for-index since + // we know each node has matching names and tags. + for (idx = 0; idx < src_size; ++idx) + { + src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); + dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); + + clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; + if (src_decl_ctx) + { + if (log) + log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_decl_ctx), + src_die.GetOffset(), dst_die.GetOffset()); + dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); + } + else + { + if (log) + log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); + } + + Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; + if (src_child_type) + { + if (log) + log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_child_type), + src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); + dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; + } + else + { + if (log) + log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); + } + } + } + else + { + // We must do this slowly. For each member of the destination, look + // up a member in the source with the same name, check its tag, and + // unique them if everything matches up. Report failures. + + if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) + { + src_name_to_die.Sort(); + + for (idx = 0; idx < dst_size; ++idx) + { + const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx); + dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); + src_die = src_name_to_die.Find(dst_name, DWARFDIE()); + + if (src_die && (src_die.Tag() == dst_die.Tag())) + { + clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; + if (src_decl_ctx) + { + if (log) + log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_decl_ctx), + src_die.GetOffset(), + dst_die.GetOffset()); + dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); + } + else + { + if (log) + log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); + } + + Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; + if (src_child_type) + { + if (log) + log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_child_type), + src_child_type->GetID(), + src_die.GetOffset(), + dst_die.GetOffset()); + dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; + } + else + { + if (log) + log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); + } + } + else + { + if (log) + log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die.GetOffset()); + + failures.Append(dst_die); + } + } + } + } + + const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize (); + const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize (); + + if (src_size_artificial && dst_size_artificial) + { + dst_name_to_die_artificial.Sort(); + + for (idx = 0; idx < src_size_artificial; ++idx) + { + const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx); + src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx); + dst_die = dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE()); + + if (dst_die) + { + // Both classes have the artificial types, link them + clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; + if (src_decl_ctx) + { + if (log) + log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_decl_ctx), + src_die.GetOffset(), dst_die.GetOffset()); + dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); + } + else + { + if (log) + log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); + } + + Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; + if (src_child_type) + { + if (log) + log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void*>(src_child_type), + src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); + dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; + } + else + { + if (log) + log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); + } + } + } + } + + if (dst_size_artificial) + { + for (idx = 0; idx < dst_size_artificial; ++idx) + { + const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); + dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx); + if (log) + log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die.GetOffset(), dst_name_artificial); + + failures.Append(dst_die); + } + } + + return (failures.Size() != 0); +} + + +bool +DWARFASTParserClang::LayoutRecordType(const clang::RecordDecl *record_decl, + uint64_t &bit_size, + uint64_t &alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) +{ + RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl); + bool success = false; + base_offsets.clear(); + vbase_offsets.clear(); + if (pos != m_record_decl_to_layout_map.end()) + { + bit_size = pos->second.bit_size; + alignment = pos->second.alignment; + field_offsets.swap(pos->second.field_offsets); + base_offsets.swap (pos->second.base_offsets); + vbase_offsets.swap (pos->second.vbase_offsets); + m_record_decl_to_layout_map.erase(pos); + success = true; + } + else + { + bit_size = 0; + alignment = 0; + field_offsets.clear(); + } + return success; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h new file mode 100644 index 000000000000..3814758fdd2c --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -0,0 +1,213 @@ +//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParserClang_h_ +#define SymbolFileDWARF_DWARFASTParserClang_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/CharUnits.h" + +// Project includes +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "DWARFDefines.h" +#include "DWARFASTParser.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserClang : public DWARFASTParser +{ +public: + DWARFASTParserClang (lldb_private::ClangASTContext &ast); + + ~DWARFASTParserClang() override; + + lldb::TypeSP + ParseTypeFromDWARF (const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + lldb_private::Log *log, + bool *type_is_new_ptr) override; + + + lldb_private::Function * + ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc, + const DWARFDIE &die) override; + + bool + CanCompleteType (const lldb_private::CompilerType &compiler_type) override; + + bool + CompleteType (const lldb_private::CompilerType &compiler_type) override; + + bool + CompleteTypeFromDWARF (const DWARFDIE &die, + lldb_private::Type *type, + lldb_private::CompilerType &compiler_type) override; + + lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) override; + + std::vector<DWARFDIE> + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override; + + lldb_private::CompilerDeclContext + GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override; + + lldb_private::CompilerDeclContext + GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) override; + + bool + LayoutRecordType(const clang::RecordDecl *record_decl, + uint64_t &bit_size, + uint64_t &alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); + +protected: + class DelayedAddObjCClassProperty; + typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList; + + struct LayoutInfo + { + LayoutInfo () : + bit_size(0), + alignment(0), + field_offsets(), + base_offsets(), + vbase_offsets() + { + } + uint64_t bit_size; + uint64_t alignment; + llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; + }; + + clang::BlockDecl * + ResolveBlockDIE (const DWARFDIE &die); + + clang::NamespaceDecl * + ResolveNamespaceDIE (const DWARFDIE &die); + + typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap; + + bool + ParseTemplateDIE (const DWARFDIE &die, + lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); + bool + ParseTemplateParameterInfos (const DWARFDIE &parent_die, + lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); + + bool + ParseChildMembers (const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + lldb_private::CompilerType &class_compiler_type, + const lldb::LanguageType class_language, + std::vector<clang::CXXBaseSpecifier *>& base_classes, + std::vector<int>& member_accessibilities, + DWARFDIECollection& member_function_dies, + DelayedPropertyList& delayed_properties, + lldb::AccessType &default_accessibility, + bool &is_a_class, + LayoutInfo &layout_info); + + size_t + ParseChildParameters (const lldb_private::SymbolContext& sc, + clang::DeclContext *containing_decl_ctx, + const DWARFDIE &parent_die, + bool skip_artificial, + bool &is_static, + bool &is_variadic, + std::vector<lldb_private::CompilerType>& function_args, + std::vector<clang::ParmVarDecl*>& function_param_decls, + unsigned &type_quals); + + void + ParseChildArrayInfo (const lldb_private::SymbolContext& sc, + const DWARFDIE &parent_die, + int64_t& first_index, + std::vector<uint64_t>& element_orders, + uint32_t& byte_stride, + uint32_t& bit_stride); + + size_t + ParseChildEnumerators (const lldb_private::SymbolContext& sc, + lldb_private::CompilerType &compiler_type, + bool is_signed, + uint32_t enumerator_byte_size, + const DWARFDIE &parent_die); + + lldb_private::Type * + GetTypeForDIE (const DWARFDIE &die); + + clang::Decl * + GetClangDeclForDIE (const DWARFDIE &die); + + clang::DeclContext * + GetClangDeclContextForDIE (const DWARFDIE &die); + + clang::DeclContext * + GetClangDeclContextContainingDIE (const DWARFDIE &die, + DWARFDIE *decl_ctx_die); + + bool + CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die, + const DWARFDIE &dst_class_die, + lldb_private::Type *class_type, + DWARFDIECollection &failures); + + clang::DeclContext * + GetCachedClangDeclContextForDIE (const DWARFDIE &die); + + void + LinkDeclContextToDIE (clang::DeclContext *decl_ctx, + const DWARFDIE &die); + + void + LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); + + lldb_private::ClangASTImporter & + GetClangASTImporter(); + + lldb::TypeSP + ParseTypeFromDWO (const DWARFDIE &die, lldb_private::Log *log); + + //---------------------------------------------------------------------- + // Return true if this type is a declaration to a type in an external + // module. + //---------------------------------------------------------------------- + lldb::ModuleSP + GetModuleForType (const DWARFDIE &die); + + typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; + //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap; + typedef std::multimap<const clang::DeclContext *, const DWARFDIE> DeclContextToDIEMap; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap; + typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; + + lldb_private::ClangASTContext &m_ast; + DIEToDeclMap m_die_to_decl; + DeclToDIEMap m_decl_to_die; + DIEToDeclContextMap m_die_to_decl_ctx; + DeclContextToDIEMap m_decl_ctx_to_die; + RecordDeclToLayoutMap m_record_decl_to_layout_map; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap; +}; + +#endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp new file mode 100644 index 000000000000..bde2694461e2 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -0,0 +1,828 @@ +//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserGo.h" + +#include "DWARFASTParserGo.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" +#include "DWARFDeclContext.h" +#include "DWARFDefines.h" +#include "DWARFDIE.h" +#include "DWARFDIECollection.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDebugMap.h" +#include "UniqueDWARFASTType.h" + +#include "clang/Basic/Specifiers.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/Value.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/TypeList.h" + +//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN + +#ifdef ENABLE_DEBUG_PRINTF +#include <stdio.h> +#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + +#define DW_AT_go_kind 0x2900 +#define DW_AT_go_key 0x2901 +#define DW_AT_go_elem 0x2902 + +using namespace lldb; +using namespace lldb_private; +DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) + : m_ast(ast) +{ +} + +DWARFASTParserGo::~DWARFASTParserGo() +{ +} + +TypeSP +DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, + bool *type_is_new_ptr) +{ + TypeSP type_sp; + + if (type_is_new_ptr) + *type_is_new_ptr = false; + + if (die) + { + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (log) + { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(), + DW_TAG_value_to_name(die.Tag()), die.GetName()); + } + + Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); + TypeList *type_list = dwarf->GetTypeList(); + if (type_ptr == NULL) + { + if (type_is_new_ptr) + *type_is_new_ptr = true; + + const dw_tag_t tag = die.Tag(); + + bool is_forward_declaration = false; + DWARFAttributes attributes; + const char *type_name_cstr = NULL; + ConstString type_name_const_str; + Type::ResolveState resolve_state = Type::eResolveStateUnresolved; + uint64_t byte_size = 0; + uint64_t go_kind = 0; + Declaration decl; + + Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; + CompilerType compiler_type; + DWARFFormValue form_value; + + dw_attr_t attr; + + switch (tag) + { + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_typedef: + case DW_TAG_unspecified_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + const size_t num_attributes = die.GetAttributes(attributes); + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + + if (num_attributes > 0) + { + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + if (type_name_cstr) + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_encoding: + // = form_value.Unsigned(); + break; + case DW_AT_type: + encoding_uid = form_value.Reference(); + break; + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); + break; + default: + // Do we care about DW_AT_go_key or DW_AT_go_elem? + break; + } + } + } + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()), + DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); + + switch (tag) + { + default: + break; + + case DW_TAG_unspecified_type: + resolve_state = Type::eResolveStateFull; + compiler_type = m_ast.CreateVoidType(type_name_const_str); + break; + + case DW_TAG_base_type: + resolve_state = Type::eResolveStateFull; + compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size); + break; + + case DW_TAG_pointer_type: + encoding_data_type = Type::eEncodingIsPointerUID; + break; + case DW_TAG_typedef: + encoding_data_type = Type::eEncodingIsTypedefUID; + CompilerType impl; + Type *type = dwarf->ResolveTypeUID(encoding_uid); + if (type) + { + if (go_kind == 0 && type->GetName() == type_name_const_str) + { + // Go emits extra typedefs as a forward declaration. Ignore these. + dwarf->m_die_to_type[die.GetDIE()] = type; + return type->shared_from_this(); + } + impl = type->GetForwardCompilerType(); + compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl); + } + break; + } + + type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size, + NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state)); + + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + } + break; + + case DW_TAG_structure_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + bool byte_size_valid = false; + + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + byte_size_valid = true; + break; + + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); + break; + + // TODO: Should we use SLICETYPE's DW_AT_go_elem? + default: + break; + } + } + } + } + + // TODO(ribrdb): Do we need this? + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively + // and clang isn't good and sharing the stack space for variables in different blocks. + std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); + + // Only try and unique the type if it has a name. + if (type_name_const_str && + dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, + byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) + { + // We have already parsed this type or from another + // compile unit. GCC loves to use the "one definition + // rule" which can result in multiple definitions + // of the same class over and over in each compile + // unit. + type_sp = unique_ast_entry_ap->m_type_sp; + if (type_sp) + { + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + DW_TAG_value_to_name(tag), type_name_cstr); + + bool compiler_type_was_created = false; + compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE())); + if (!compiler_type) + { + compiler_type_was_created = true; + compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size); + } + + type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size, + NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateForward)); + + // Add our type to the unique type map so we don't + // end up creating many copies of the same type over + // and over in the ASTContext for our module + unique_ast_entry_ap->m_type_sp = type_sp; + unique_ast_entry_ap->m_die = die; + unique_ast_entry_ap->m_declaration = decl; + unique_ast_entry_ap->m_byte_size = byte_size; + dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap); + + if (!is_forward_declaration) + { + // Always start the definition for a class type so that + // if the class has child classes or types that require + // the class to be created for use as their decl contexts + // the class will be ready to accept these child definitions. + if (die.HasChildren() == false) + { + // No children for this struct/union/class, lets finish it + m_ast.CompleteStructType(compiler_type); + } + else if (compiler_type_was_created) + { + // Leave this as a forward declaration until we need + // to know the details of the type. lldb_private::Type + // will automatically call the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" + // When the definition needs to be defined. + dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType(); + dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); + // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true); + } + } + } + break; + + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + bool is_variadic = false; + clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern + + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_external: + if (form_value.Unsigned()) + { + if (storage == clang::SC_None) + storage = clang::SC_Extern; + else + storage = clang::SC_PrivateExtern; + } + break; + + case DW_AT_high_pc: + case DW_AT_low_pc: + break; + } + } + } + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + DW_TAG_value_to_name(tag), type_name_cstr); + + std::vector<CompilerType> function_param_types; + + // Parse the function children for the parameters + + if (die.HasChildren()) + { + ParseChildParameters(sc, die, is_variadic, function_param_types); + } + + // compiler_type will get the function prototype clang type after this call + compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(), + function_param_types.size(), is_variadic); + + type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL, + LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateFull)); + assert(type_sp.get()); + } + break; + + case DW_TAG_array_type: + { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; + int64_t first_index = 0; + uint32_t byte_stride = 0; + uint32_t bit_stride = 0; + const size_t num_attributes = die.GetAttributes(attributes); + + if (num_attributes > 0) + { + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_type: + type_die_offset = form_value.Reference(); + break; + case DW_AT_byte_size: + break; // byte_size = form_value.Unsigned(); break; + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); + break; + default: + break; + } + } + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + DW_TAG_value_to_name(tag), type_name_cstr); + + Type *element_type = dwarf->ResolveTypeUID(type_die_offset); + + if (element_type) + { + std::vector<uint64_t> element_orders; + ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride); + if (byte_stride == 0) + byte_stride = element_type->GetByteSize(); + CompilerType array_element_type = element_type->GetForwardCompilerType(); + if (element_orders.size() > 0) + { + if (element_orders.size() > 1) + printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr); + compiler_type = + m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]); + } + else + { + compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0); + } + type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, + byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl, + compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(element_type); + } + } + } + break; + + default: + dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), " + "please file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } + + if (type_sp.get()) + { + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit) + { + symbol_context_scope = sc.comp_unit; + } + else if (sc.function != NULL && sc_parent_die) + { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset())); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != NULL) + { + type_sp->SetSymbolContextScope(symbol_context_scope); + } + + // We are ready to put this type into the uniqued list up at the module level + type_list->Insert(type_sp); + + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + } + } + else if (type_ptr != DIE_IS_BEING_PARSED) + { + type_sp = type_ptr->shared_from_this(); + } + } + return type_sp; +} + +size_t +DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, + + const DWARFDIE &parent_die, bool &is_variadic, + std::vector<CompilerType> &function_param_types) +{ + if (!parent_die) + return 0; + + size_t arg_idx = 0; + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + + dw_tag_t tag = die.Tag(); + switch (tag) + { + case DW_TAG_formal_parameter: + { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + Declaration decl; + dw_offset_t param_type_die_offset = DW_INVALID_OFFSET; + + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + // = form_value.AsCString(); + break; + case DW_AT_type: + param_type_die_offset = form_value.Reference(); + break; + case DW_AT_location: + // if (form_value.BlockData()) + // { + // const DWARFDataExtractor& debug_info_data = + // debug_info(); + // uint32_t block_length = form_value.Unsigned(); + // DWARFDataExtractor location(debug_info_data, + // form_value.BlockData() - debug_info_data.GetDataStart(), + // block_length); + // } + // else + // { + // } + // break; + default: + break; + } + } + } + + Type *type = parent_die.ResolveTypeUID(param_type_die_offset); + if (type) + { + function_param_types.push_back(type->GetForwardCompilerType()); + } + } + arg_idx++; + } + break; + + case DW_TAG_unspecified_parameters: + is_variadic = true; + break; + + default: + break; + } + } + return arg_idx; +} + +void +DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, + std::vector<uint64_t> &element_orders, uint32_t &byte_stride, + uint32_t &bit_stride) +{ + if (!parent_die) + return; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + const dw_tag_t tag = die.Tag(); + switch (tag) + { + case DW_TAG_subrange_type: + { + DWARFAttributes attributes; + const size_t num_child_attributes = die.GetAttributes(attributes); + if (num_child_attributes > 0) + { + uint64_t num_elements = 0; + uint32_t i; + for (i = 0; i < num_child_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_count: + num_elements = form_value.Unsigned(); + break; + + default: + case DW_AT_type: + break; + } + } + } + + element_orders.push_back(num_elements); + } + } + break; + } + } +} + +bool +DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &compiler_type) +{ + if (!die) + return false; + + const dw_tag_t tag = die.Tag(); + + SymbolFileDWARF *dwarf = die.GetDWARF(); + Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( + log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()), + DW_TAG_value_to_name(tag), type->GetName().AsCString()); + assert(compiler_type); + DWARFAttributes attributes; + + switch (tag) + { + case DW_TAG_structure_type: + { + { + if (die.HasChildren()) + { + SymbolContext sc(die.GetLLDBCompileUnit()); + + ParseChildMembers(sc, die, compiler_type); + } + } + m_ast.CompleteStructType(compiler_type); + return (bool)compiler_type; + } + + default: + assert(false && "not a forward go type decl!"); + break; + } + + return false; +} + +size_t +DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type) +{ + size_t count = 0; + uint32_t member_idx = 0; + + ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); + GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem()); + if (ast == nullptr) + return 0; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + dw_tag_t tag = die.Tag(); + + switch (tag) + { + case DW_TAG_member: + { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) + { + Declaration decl; + const char *name = NULL; + + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + uint32_t member_byte_offset = UINT32_MAX; + uint32_t i; + for (i = 0; i < num_attributes; ++i) + { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + name = form_value.AsCString(); + break; + case DW_AT_type: + encoding_uid = form_value.Reference(); + break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + { + Value initialValue(0); + Value memberOffset(0); + const DWARFDataExtractor &debug_info_data = + die.GetDWARF()->get_debug_info_data(); + uint32_t block_length = form_value.Unsigned(); + uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); + if (DWARFExpression::Evaluate(NULL, // ExecutionContext * + NULL, // ClangExpressionVariableList * + NULL, // ClangExpressionDeclMap * + NULL, // RegisterContext * + module_sp, debug_info_data, die.GetCU(), + block_offset, block_length, eRegisterKindDWARF, + &initialValue, memberOffset, NULL)) + { + member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + } + } + else + { + // With DWARF 3 and later, if the value is an integer constant, + // this form value is the offset in bytes from the beginning + // of the containing entity. + member_byte_offset = form_value.Unsigned(); + } + break; + + default: + break; + } + } + } + + Type *member_type = die.ResolveTypeUID(encoding_uid); + if (member_type) + { + CompilerType member_go_type = member_type->GetFullCompilerType(); + ConstString name_const_str(name); + m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset); + } + } + ++member_idx; + } + break; + + default: + break; + } + } + + return count; +} + +Function * +DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die) +{ + DWARFRangeList func_ranges; + const char *name = NULL; + const char *mangled = NULL; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFExpression frame_base(die.GetCU()); + + assert(die.Tag() == DW_TAG_subprogram); + + if (die.Tag() != DW_TAG_subprogram) + return NULL; + + if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, + call_column, &frame_base)) + { + // Union of all ranges in the function DIE (if the function is discontiguous) + AddressRange func_range; + lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0); + lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0); + if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) + { + ModuleSP module_sp(die.GetModule()); + func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList()); + if (func_range.GetBaseAddress().IsValid()) + func_range.SetByteSize(highest_func_addr - lowest_func_addr); + } + + if (func_range.GetBaseAddress().IsValid()) + { + Mangled func_name; + func_name.SetValue(ConstString(name), false); + + FunctionSP func_sp; + std::unique_ptr<Declaration> decl_ap; + if (decl_file != 0 || decl_line != 0 || decl_column != 0) + decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, + decl_column)); + + SymbolFileDWARF *dwarf = die.GetDWARF(); + // Supply the type _only_ if it has already been parsed + Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE()); + + assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + + if (dwarf->FixupAddress(func_range.GetBaseAddress())) + { + const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset()); + func_sp.reset(new Function(sc.comp_unit, + dwarf->MakeUserID(func_user_id), // UserID is the DIE offset + dwarf->MakeUserID(func_user_id), func_name, func_type, + func_range)); // first address range + + if (func_sp.get() != NULL) + { + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + return func_sp.get(); + } + } + } + } + return NULL; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h new file mode 100644 index 000000000000..5039fc7f7672 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h @@ -0,0 +1,84 @@ +//===-- DWARFASTParserGo.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParserGo_h_ +#define SymbolFileDWARF_DWARFASTParserGo_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +// Project includes +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/GoASTContext.h" +#include "DWARFDefines.h" +#include "DWARFASTParser.h" +#include "DWARFDIE.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserGo : public DWARFASTParser +{ +public: + DWARFASTParserGo(lldb_private::GoASTContext &ast); + + ~DWARFASTParserGo() override; + + lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, + bool *type_is_new_ptr) override; + + lldb_private::Function * + ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, + const DWARFDIE &die) override; + + bool + CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + lldb_private::CompilerType &go_type) override; + + lldb_private::CompilerDeclContext + GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override + { + return lldb_private::CompilerDeclContext(); + } + + lldb_private::CompilerDeclContext + GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override + { + return lldb_private::CompilerDeclContext(); + } + + lldb_private::CompilerDecl + GetDeclForUIDFromDWARF (const DWARFDIE &die) override + { + return lldb_private::CompilerDecl(); + } + + std::vector<DWARFDIE> + GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override + { + return std::vector<DWARFDIE>(); + } + +private: + size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic, + std::vector<lldb_private::CompilerType> &function_param_types); + void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, + std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride); + + size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::CompilerType &class_compiler_type); + + lldb_private::GoASTContext &m_ast; +}; + +#endif // SymbolFileDWARF_DWARFASTParserGo_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp new file mode 100644 index 000000000000..a522bcb35288 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -0,0 +1,90 @@ +//===-- DWARFAttribute.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFAttribute.h" +#include "DWARFDebugInfo.h" +#include "DWARFCompileUnit.h" + +DWARFAttributes::DWARFAttributes() : + m_infos() +{ +} + +DWARFAttributes::~DWARFAttributes() +{ +} + + +uint32_t +DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const +{ + collection::const_iterator end = m_infos.end(); + collection::const_iterator beg = m_infos.begin(); + collection::const_iterator pos; + for (pos = beg; pos != end; ++pos) + { + if (pos->attr.get_attr() == attr) + return std::distance(beg, pos); + } + return UINT32_MAX; +} + +void +DWARFAttributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form) +{ + AttributeValue attr_value = { cu, attr_die_offset, { attr, form } }; + m_infos.push_back(attr_value); +} + +bool +DWARFAttributes::ContainsAttribute(dw_attr_t attr) const +{ + return FindAttributeIndex(attr) != UINT32_MAX; +} + +bool +DWARFAttributes::RemoveAttribute(dw_attr_t attr) +{ + uint32_t attr_index = FindAttributeIndex(attr); + if (attr_index != UINT32_MAX) + { + m_infos.erase(m_infos.begin() + attr_index); + return true; + } + return false; +} + +bool +DWARFAttributes::ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const +{ + const DWARFCompileUnit *cu = CompileUnitAtIndex(i); + form_value.SetCompileUnit(cu); + form_value.SetForm(FormAtIndex(i)); + lldb::offset_t offset = DIEOffsetAtIndex(i); + return form_value.ExtractValue(cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset); +} + +uint64_t +DWARFAttributes::FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const +{ + const uint32_t attr_idx = FindAttributeIndex (attr); + if (attr_idx != UINT32_MAX) + return FormValueAsUnsignedAtIndex (attr_idx, fail_value); + return fail_value; +} + +uint64_t +DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const +{ + DWARFFormValue form_value; + if (ExtractFormValueAtIndex(i, form_value)) + return form_value.Reference(); + return fail_value; +} + diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h index 40c8af3d6e8e..f5ca9cce525e 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -10,36 +10,72 @@ #ifndef SymbolFileDWARF_DWARFAttribute_h_ #define SymbolFileDWARF_DWARFAttribute_h_ +#include "llvm/ADT/SmallVector.h" #include "DWARFDefines.h" #include <vector> +class DWARFCompileUnit; +class DWARFFormValue; + class DWARFAttribute { public: DWARFAttribute(dw_attr_t attr, dw_form_t form) : - m_attr_form ( attr << 16 | form ) + m_attr (attr), + m_form (form) { } - void set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; } - void set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); } - void set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; } - dw_attr_t get_attr() const { return m_attr_form >> 16; } - dw_form_t get_form() const { return (dw_form_t)m_attr_form; } - void get(dw_attr_t& attr, dw_form_t& form) const + void set (dw_attr_t attr, dw_form_t form) { m_attr = attr; m_form = form; } + void set_attr (dw_attr_t attr) { m_attr = attr; } + void set_form (dw_form_t form) { m_form = form; } + dw_attr_t get_attr () const { return m_attr; } + dw_form_t get_form () const { return m_form; } + void get (dw_attr_t& attr, dw_form_t& form) const { - uint32_t attr_form = m_attr_form; - attr = attr_form >> 16; - form = (dw_form_t)attr_form; + attr = m_attr; + form = m_form; } - bool operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; } + bool operator == (const DWARFAttribute& rhs) const { return m_attr == rhs.m_attr && m_form == rhs.m_form; } typedef std::vector<DWARFAttribute> collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; protected: - uint32_t m_attr_form; // Upper 16 bits is attribute, lower 16 bits is form + dw_attr_t m_attr; + dw_form_t m_form; }; +class DWARFAttributes +{ +public: + DWARFAttributes(); + ~DWARFAttributes(); + + void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form); + const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; } + dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; } + dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr.get_attr(); } + dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); } + bool ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const; + uint64_t FormValueAsUnsignedAtIndex (uint32_t i, uint64_t fail_value) const; + uint64_t FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const; + uint32_t FindAttributeIndex(dw_attr_t attr) const; + bool ContainsAttribute(dw_attr_t attr) const; + bool RemoveAttribute(dw_attr_t attr); + void Clear() { m_infos.clear(); } + size_t Size() const { return m_infos.size(); } + +protected: + struct AttributeValue + { + const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values + dw_offset_t die_offset; + DWARFAttribute attr; + }; + typedef llvm::SmallVector<AttributeValue, 8> collection; + collection m_infos; +}; + #endif // SymbolFileDWARF_DWARFAttribute_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 60933108c97a..e7cb2b413ad7 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -12,12 +12,13 @@ #include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Host/StringConvert.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/ObjCLanguageRuntime.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" @@ -27,6 +28,7 @@ #include "LogChannelDWARF.h" #include "NameToDIE.h" #include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDebugMap.h" using namespace lldb; @@ -52,10 +54,16 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : m_producer_version_minor (0), m_producer_version_update (0), m_language_type (eLanguageTypeUnknown), - m_is_dwarf64 (false) + m_is_dwarf64 (false), + m_is_optimized (eLazyBoolCalculate), + m_addr_base (0), + m_base_obj_offset (DW_INVALID_OFFSET) { } +DWARFCompileUnit::~DWARFCompileUnit() +{} + void DWARFCompileUnit::Clear() { @@ -71,6 +79,9 @@ DWARFCompileUnit::Clear() m_producer = eProducerInvalid; m_language_type = eLanguageTypeUnknown; m_is_dwarf64 = false; + m_is_optimized = eLazyBoolCalculate; + m_addr_base = 0; + m_base_obj_offset = DW_INVALID_OFFSET; } bool @@ -128,6 +139,9 @@ DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) if (keep_compile_unit_die) m_die_array.push_back(tmp_array.front()); } + + if (m_dwo_symbol_file) + m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die); } //---------------------------------------------------------------------- @@ -174,7 +188,8 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) die_index_stack.reserve(32); die_index_stack.push_back(0); bool prev_die_had_children = false; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); while (offset < next_cu_offset && die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) { @@ -188,12 +203,12 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) const bool null_die = die.IsNULL(); if (depth == 0) { - uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); + if (initial_die_array_size == 0) + AddCompileUnitDIE(die); + uint64_t base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); + base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_entry_pc, 0); SetBaseAddress (base_addr); - if (initial_die_array_size == 0) - AddDIE (die); if (cu_die_only) return 1; } @@ -283,9 +298,83 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) verbose_log->PutCString (strm.GetString().c_str()); } - return m_die_array.size(); + if (!m_dwo_symbol_file) + return m_die_array.size(); + + DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit(); + size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only); + return m_die_array.size() + dwo_die_count - 1; // We have 2 CU die, but we waht to count it only as one } +void +DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry& die) +{ + assert (m_die_array.empty() && "Compile unit DIE already added"); + AddDIE(die); + + DWARFDebugInfoEntry& cu_die = m_die_array.front(); + + const char* dwo_name = cu_die.GetAttributeValueAsString(m_dwarf2Data, + this, + DW_AT_GNU_dwo_name, + nullptr); + if (!dwo_name) + return; + + FileSpec dwo_file(dwo_name, true); + if (dwo_file.IsRelative()) + { + const char* comp_dir = cu_die.GetAttributeValueAsString(m_dwarf2Data, + this, + DW_AT_comp_dir, + nullptr); + if (!comp_dir) + return; + + dwo_file.SetFile(comp_dir, true); + dwo_file.AppendPathComponent(dwo_name); + } + + if (!dwo_file.Exists()) + return; + + DataBufferSP dwo_file_data_sp; + lldb::offset_t dwo_file_data_offset = 0; + ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(m_dwarf2Data->GetObjectFile()->GetModule(), + &dwo_file, + 0 /* file_offset */, + dwo_file.GetByteSize(), + dwo_file_data_sp, + dwo_file_data_offset); + if (dwo_obj_file == nullptr) + return; + + std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file(new SymbolFileDWARFDwo(dwo_obj_file, this)); + + DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit(); + if (!dwo_cu) + return; // Can't fetch the compile unit from the dwo file. + + DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); + if (!dwo_cu_die.IsValid()) + return; // Can't fetch the compile unit DIE from the dwo file. + + uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data, + this, + DW_AT_GNU_dwo_id, + 0); + uint64_t sub_dwo_id = dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); + if (main_dwo_id != sub_dwo_id) + return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to a differectn compilation. + + m_dwo_symbol_file = std::move(dwo_symbol_file); + + dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data, + this, + DW_AT_GNU_addr_base, + 0); + dwo_cu->SetAddrBase(addr_base, m_offset); +} dw_offset_t DWARFCompileUnit::GetAbbrevOffset() const @@ -373,6 +462,16 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) g_default_addr_size = addr_size; } +lldb::user_id_t +DWARFCompileUnit::GetID () const +{ + dw_offset_t local_id = m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; + if (m_dwarf2Data) + return m_dwarf2Data->MakeUserID(local_id); + else + return local_id; +} + void DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, DWARFDebugAranges* debug_aranges) @@ -381,13 +480,15 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, // in order to produce a compile unit level set of address ranges that // is accurate. + size_t num_debug_aranges = debug_aranges->GetNumRanges(); + // First get the compile unit DIE only and check if it has a DW_AT_ranges - const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly(); + const DWARFDebugInfoEntry* die = GetCompileUnitDIEPtrOnly(); const dw_offset_t cu_offset = GetOffset(); if (die) { - DWARFDebugRanges::RangeList ranges; + DWARFRangeList ranges; const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false); if (num_ranges > 0) { @@ -397,7 +498,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, // this with recent GCC builds. for (size_t i=0; i<num_ranges; ++i) { - const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i); + const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd()); } @@ -411,11 +512,11 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, // and then throwing them all away to keep memory usage down. const bool clear_dies = ExtractDIEsIfNeeded (false) > 1; - die = DIE(); + die = DIEPtr(); if (die) die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); - if (debug_aranges->IsEmpty()) + if (debug_aranges->GetNumRanges() == num_debug_aranges) { // We got nothing from the functions, maybe we have a line tables only // situation. Check the line tables and build the arange table from this. @@ -437,7 +538,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, { const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx); debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd()); - printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); } } } @@ -446,7 +546,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, } } - if (debug_aranges->IsEmpty()) + if (debug_aranges->GetNumRanges() == num_debug_aranges) { // We got nothing from the functions, maybe we have a line tables only // situation. Check the line tables and build the arange table from this. @@ -465,7 +565,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, { const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx); debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); - printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); } } } @@ -493,119 +592,85 @@ DWARFCompileUnit::GetFunctionAranges () "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]", GetOffset()); } - const DWARFDebugInfoEntry* die = DIE(); + const DWARFDebugInfoEntry* die = DIEPtr(); if (die) die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); + + if (m_dwo_symbol_file) + { + DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit(); + const DWARFDebugInfoEntry* dwo_die = dwo_cu->DIEPtr(); + if (dwo_die) + dwo_die->BuildFunctionAddressRangeTable (m_dwo_symbol_file.get(), + dwo_cu, + m_func_aranges_ap.get()); + } + const bool minimize = false; m_func_aranges_ap->Sort(minimize); } return *m_func_aranges_ap.get(); } -bool -DWARFCompileUnit::LookupAddress -( - const dw_addr_t address, - DWARFDebugInfoEntry** function_die_handle, - DWARFDebugInfoEntry** block_die_handle -) +DWARFDIE +DWARFCompileUnit::LookupAddress (const dw_addr_t address) { - bool success = false; - - if (function_die_handle != NULL && DIE()) + if (DIE()) { - const DWARFDebugAranges &func_aranges = GetFunctionAranges (); // Re-check the aranges auto pointer contents in case it was created above if (!func_aranges.IsEmpty()) - { - *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address)); - if (*function_die_handle != NULL) - { - success = true; - if (block_die_handle != NULL) - { - DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild(); - while (child) - { - if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle)) - break; - child = child->GetSibling(); - } - } - } - } + return GetDIE(func_aranges.FindAddress(address)); } - return success; + return DWARFDIE(); } //---------------------------------------------------------------------- // Compare function DWARFDebugAranges::Range structures //---------------------------------------------------------------------- -static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) +static bool CompareDIEOffset (const DWARFDebugInfoEntry& die, const dw_offset_t die_offset) { - return die1.GetOffset() < die2.GetOffset(); + return die.GetOffset() < die_offset; } //---------------------------------------------------------------------- -// GetDIEPtr() +// GetDIE() // -// Get the DIE (Debug Information Entry) with the specified offset. +// Get the DIE (Debug Information Entry) with the specified offset by +// first checking if the DIE is contained within this compile unit and +// grabbing the DIE from this compile unit. Otherwise we grab the DIE +// from the DWARF file. //---------------------------------------------------------------------- -DWARFDebugInfoEntry* -DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset) +DWARFDIE +DWARFCompileUnit::GetDIE (dw_offset_t die_offset) { if (die_offset != DW_INVALID_OFFSET) { - ExtractDIEsIfNeeded (false); - DWARFDebugInfoEntry compare_die; - compare_die.SetOffset(die_offset); - DWARFDebugInfoEntry::iterator end = m_die_array.end(); - DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); - if (pos != end) - { - if (die_offset == (*pos).GetOffset()) - return &(*pos); - } - } - return NULL; // Not found in any compile units -} + if (m_dwo_symbol_file) + return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset); -//---------------------------------------------------------------------- -// GetDIEPtrContainingOffset() -// -// Get the DIE (Debug Information Entry) that contains the specified -// .debug_info offset. -//---------------------------------------------------------------------- -const DWARFDebugInfoEntry* -DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset) -{ - if (die_offset != DW_INVALID_OFFSET) - { - ExtractDIEsIfNeeded (false); - DWARFDebugInfoEntry compare_die; - compare_die.SetOffset(die_offset); - DWARFDebugInfoEntry::iterator end = m_die_array.end(); - DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); - if (pos != end) + if (ContainsDIEOffset(die_offset)) { - if (die_offset >= (*pos).GetOffset()) + ExtractDIEsIfNeeded (false); + DWARFDebugInfoEntry::iterator end = m_die_array.end(); + DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset); + if (pos != end) { - DWARFDebugInfoEntry::iterator next = pos + 1; - if (next != end) - { - if (die_offset < (*next).GetOffset()) - return &(*pos); - } + if (die_offset == (*pos).GetOffset()) + return DWARFDIE(this, &(*pos)); } } + else + { + // Don't specify the compile unit offset as we don't know it because the DIE belongs to + // a different compile unit in the same symbol file. + return m_dwarf2Data->DebugInfo()->GetDIE (DIERef(die_offset)); + } } - return NULL; // Not found in any compile units + return DWARFDIE(); // Not found } - - size_t DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const { @@ -615,7 +680,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die for (pos = m_die_array.begin(); pos != end; ++pos) { if (pos->Tag() == tag) - dies.Append (&(*pos)); + dies.Append (DWARFDIE(this, &(*pos))); } // Return the number of DIEs added to the collection @@ -646,8 +711,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die void -DWARFCompileUnit::Index (const uint32_t cu_idx, - NameToDIE& func_basenames, +DWARFCompileUnit::Index (NameToDIE& func_basenames, NameToDIE& func_fullnames, NameToDIE& func_methods, NameToDIE& func_selectors, @@ -656,10 +720,6 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, NameToDIE& types, NameToDIE& namespaces) { - const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); - - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); - Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS)); if (log) @@ -670,9 +730,57 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, } const LanguageType cu_language = GetLanguageType(); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); + + IndexPrivate(this, + cu_language, + fixed_form_sizes, + GetOffset(), + func_basenames, + func_fullnames, + func_methods, + func_selectors, + objc_class_selectors, + globals, + types, + namespaces); + + SymbolFileDWARFDwo* dwo_symbol_file = GetDwoSymbolFile(); + if (dwo_symbol_file) + { + IndexPrivate(dwo_symbol_file->GetCompileUnit(), + cu_language, + fixed_form_sizes, + GetOffset(), + func_basenames, + func_fullnames, + func_methods, + func_selectors, + objc_class_selectors, + globals, + types, + namespaces); + } +} + +void +DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, + const LanguageType cu_language, + const DWARFFormValue::FixedFormSizes& fixed_form_sizes, + const dw_offset_t cu_offset, + NameToDIE& func_basenames, + NameToDIE& func_fullnames, + NameToDIE& func_methods, + NameToDIE& func_selectors, + NameToDIE& objc_class_selectors, + NameToDIE& globals, + NameToDIE& types, + NameToDIE& namespaces) +{ DWARFDebugInfoEntry::const_iterator pos; - DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); - DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); + DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin(); + DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end(); for (pos = begin; pos != end; ++pos) { const DWARFDebugInfoEntry &die = *pos; @@ -701,17 +809,17 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, continue; } - DWARFDebugInfoEntry::Attributes attributes; + DWARFAttributes attributes; const char *name = NULL; const char *mangled_cstr = NULL; bool is_declaration = false; //bool is_artificial = false; bool has_address = false; - bool has_location = false; + bool has_location_or_const_value = false; bool is_global_or_static_variable = false; - dw_offset_t specification_die_offset = DW_INVALID_OFFSET; - const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); + DWARFFormValue specification_die_form; + const size_t num_attributes = die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes); if (num_attributes > 0) { for (uint32_t i=0; i<num_attributes; ++i) @@ -721,24 +829,24 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, switch (attr) { case DW_AT_name: - if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) - name = form_value.AsCString(debug_str); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + name = form_value.AsCString(); break; case DW_AT_declaration: - if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) + if (attributes.ExtractFormValueAtIndex(i, form_value)) is_declaration = form_value.Unsigned() != 0; break; // case DW_AT_artificial: -// if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) +// if (attributes.ExtractFormValueAtIndex(i, form_value)) // is_artificial = form_value.Unsigned() != 0; // break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: - if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) - mangled_cstr = form_value.AsCString(debug_str); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + mangled_cstr = form_value.AsCString(); break; case DW_AT_low_pc: @@ -752,7 +860,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, break; case DW_AT_location: - has_location = true; + case DW_AT_const_value: + has_location_or_const_value = true; if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry* parent_die = die.GetParent(); @@ -800,8 +909,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, break; case DW_AT_specification: - if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) - specification_die_offset = form_value.Reference(); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + specification_die_form = form_value; break; } } @@ -814,24 +923,22 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, { if (name) { - // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the - // simple inlined check outside the call. - ObjCLanguageRuntime::MethodName objc_method(name, true); + ObjCLanguage::MethodName objc_method(name, true); if (objc_method.IsValid(true)) { ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory()); ConstString objc_selector_name (objc_method.GetSelector()); ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true)); ConstString objc_class_name_no_category (objc_method.GetClassName()); - func_fullnames.Insert (ConstString(name), die.GetOffset()); + func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); if (objc_class_name_with_category) - objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset()); + objc_class_selectors.Insert(objc_class_name_with_category, DIERef(cu_offset, die.GetOffset())); if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category) - objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); + objc_class_selectors.Insert(objc_class_name_no_category, DIERef(cu_offset, die.GetOffset())); if (objc_selector_name) - func_selectors.Insert (objc_selector_name, die.GetOffset()); + func_selectors.Insert (objc_selector_name, DIERef(cu_offset, die.GetOffset())); if (objc_fullname_no_category_name) - func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); + func_fullnames.Insert (objc_fullname_no_category_name, DIERef(cu_offset, die.GetOffset())); } // If we have a mangled name, then the DW_AT_name attribute // is usually the method name without the class or any parameters @@ -846,32 +953,23 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, } else { - if (specification_die_offset != DW_INVALID_OFFSET) + if (specification_die_form.IsValid()) { - const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); - if (specification_die) - { - parent = specification_die->GetParent(); - if (parent) - { - parent_tag = parent->Tag(); - - if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) - is_method = true; - } - } + DWARFDIE specification_die = dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE (DIERef(specification_die_form)); + if (specification_die.GetParent().IsStructOrClass()) + is_method = true; } } } if (is_method) - func_methods.Insert (ConstString(name), die.GetOffset()); + func_methods.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); else - func_basenames.Insert (ConstString(name), die.GetOffset()); + func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) - func_fullnames.Insert (ConstString(name), die.GetOffset()); + func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); } if (mangled_cstr) { @@ -882,10 +980,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); - func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); + func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset())); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) - func_fullnames.Insert (demangled, die.GetOffset()); + func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset())); } } } @@ -895,7 +993,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, if (has_address) { if (name) - func_basenames.Insert (ConstString(name), die.GetOffset()); + func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); if (mangled_cstr) { // Make sure our mangled name isn't the same string table entry @@ -905,14 +1003,14 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); - func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); + func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset())); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) - func_fullnames.Insert (demangled, die.GetOffset()); + func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset())); } } else - func_fullnames.Insert (ConstString(name), die.GetOffset()); + func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); } break; @@ -928,19 +1026,19 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, case DW_TAG_unspecified_type: if (name && is_declaration == false) { - types.Insert (ConstString(name), die.GetOffset()); + types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); } break; case DW_TAG_namespace: if (name) - namespaces.Insert (ConstString(name), die.GetOffset()); + namespaces.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); break; case DW_TAG_variable: - if (name && has_location && is_global_or_static_variable) + if (name && has_location_or_const_value && is_global_or_static_variable) { - globals.Insert (ConstString(name), die.GetOffset()); + globals.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); // Be sure to include variables by their mangled and demangled // names if they have any since a variable can have a basename // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled @@ -953,10 +1051,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); - globals.Insert (mangled.GetMangledName(), die.GetOffset()); + globals.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset())); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) - globals.Insert (demangled, die.GetOffset()); + globals.Insert (demangled, DIERef(cu_offset, die.GetOffset())); } } break; @@ -1004,7 +1102,7 @@ DWARFCompileUnit::ParseProducerInfo () m_producer_version_minor = UINT32_MAX; m_producer_version_update = UINT32_MAX; - const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); + const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); if (die) { @@ -1095,10 +1193,9 @@ DWARFCompileUnit::GetLanguageType() if (m_language_type != eLanguageTypeUnknown) return m_language_type; - const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); + const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); if (die) - m_language_type = LanguageTypeFromDWARF( - die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0)); + m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0)); return m_language_type; } @@ -1108,3 +1205,57 @@ DWARFCompileUnit::IsDWARF64() const return m_is_dwarf64; } +bool +DWARFCompileUnit::GetIsOptimized () +{ + if (m_is_optimized == eLazyBoolCalculate) + { + const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); + if (die) + { + m_is_optimized = eLazyBoolNo; + if (die->GetAttributeValueAsUnsigned (m_dwarf2Data, this, DW_AT_APPLE_optimized, 0) == 1) + { + m_is_optimized = eLazyBoolYes; + } + } + } + if (m_is_optimized == eLazyBoolYes) + { + return true; + } + else + { + return false; + } +} + +DWARFFormValue::FixedFormSizes +DWARFCompileUnit::GetFixedFormSizes () +{ + return DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), IsDWARF64()); +} + +TypeSystem * +DWARFCompileUnit::GetTypeSystem () +{ + if (m_dwarf2Data) + return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType()); + else + return nullptr; +} + +void +DWARFCompileUnit::SetUserData(void *d) +{ + m_user_data = d; + if (m_dwo_symbol_file) + m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); +} + +void +DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset) +{ + m_addr_base = addr_base; + m_base_obj_offset = base_obj_offset; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 93c8df822dcc..0fcaaca09ed8 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -12,9 +12,11 @@ #include "lldb/lldb-enumerations.h" #include "DWARFDebugInfoEntry.h" -#include "SymbolFileDWARF.h" +#include "DWARFDIE.h" class NameToDIE; +class SymbolFileDWARF; +class SymbolFileDWARFDwo; class DWARFCompileUnit { @@ -29,19 +31,17 @@ public: }; DWARFCompileUnit(SymbolFileDWARF* dwarf2Data); + ~DWARFCompileUnit(); bool Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr); size_t ExtractDIEsIfNeeded (bool cu_die_only); - bool LookupAddress( - const dw_addr_t address, - DWARFDebugInfoEntry** function_die, - DWARFDebugInfoEntry** block_die); - + DWARFDIE LookupAddress(const dw_addr_t address); size_t AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT32_MAX) const; void Clear(); bool Verify(lldb_private::Stream *s) const; void Dump(lldb_private::Stream *s) const; dw_offset_t GetOffset() const { return m_offset; } + lldb::user_id_t GetID () const; uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ } bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); } dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } @@ -53,32 +53,35 @@ public: dw_offset_t GetAbbrevOffset() const; uint8_t GetAddressByteSize() const { return m_addr_size; } dw_addr_t GetBaseAddress() const { return m_base_addr; } + dw_addr_t GetAddrBase() const { return m_addr_base; } + void SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset); void ClearDIEs(bool keep_compile_unit_die); void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, DWARFDebugAranges* debug_aranges); + + lldb_private::TypeSystem * + GetTypeSystem(); + + DWARFFormValue::FixedFormSizes + GetFixedFormSizes (); + void SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } - const DWARFDebugInfoEntry* + DWARFDIE GetCompileUnitDIEOnly() { - ExtractDIEsIfNeeded (true); - if (m_die_array.empty()) - return NULL; - return &m_die_array[0]; + return DWARFDIE(this, GetCompileUnitDIEPtrOnly()); } - const DWARFDebugInfoEntry* - DIE() + DWARFDIE + DIE () { - ExtractDIEsIfNeeded (false); - if (m_die_array.empty()) - return NULL; - return &m_die_array[0]; + return DWARFDIE(this, DIEPtr()); } void @@ -97,6 +100,9 @@ public: m_die_array.reserve(GetDebugInfoSize() / 24); m_die_array.push_back(die); } + + void + AddCompileUnitDIE (DWARFDebugInfoEntry& die); bool HasDIEsParsed () const @@ -104,17 +110,8 @@ public: return m_die_array.size() > 1; } - DWARFDebugInfoEntry* - GetDIEAtIndexUnchecked (uint32_t idx) - { - return &m_die_array[idx]; - } - - DWARFDebugInfoEntry* - GetDIEPtr (dw_offset_t die_offset); - - const DWARFDebugInfoEntry* - GetDIEPtrContainingOffset (dw_offset_t die_offset); + DWARFDIE + GetDIE (dw_offset_t die_offset); static uint8_t GetAddressByteSize(const DWARFCompileUnit* cu); @@ -135,10 +132,7 @@ public: } void - SetUserData(void *d) - { - m_user_data = d; - } + SetUserData(void *d); bool Supports_DW_AT_APPLE_objc_complete_type (); @@ -149,15 +143,8 @@ public: bool Supports_unnamed_objc_bitfields (); -// void -// AddGlobalDIEByIndex (uint32_t die_idx); -// -// void -// AddGlobal (const DWARFDebugInfoEntry* die); -// void - Index (const uint32_t cu_idx, - NameToDIE& func_basenames, + Index (NameToDIE& func_basenames, NameToDIE& func_fullnames, NameToDIE& func_methods, NameToDIE& func_selectors, @@ -196,8 +183,24 @@ public: bool IsDWARF64() const; + bool + GetIsOptimized (); + + SymbolFileDWARFDwo* + GetDwoSymbolFile() const + { + return m_dwo_symbol_file.get(); + } + + dw_offset_t + GetBaseObjOffset() const + { + return m_base_obj_offset; + } + protected: SymbolFileDWARF* m_dwarf2Data; + std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file; const DWARFAbbreviationDeclarationSet *m_abbrevs; void * m_user_data; DWARFDebugInfoEntry::collection m_die_array; // The compile unit debug information entry item @@ -213,10 +216,49 @@ protected: uint32_t m_producer_version_update; lldb::LanguageType m_language_type; bool m_is_dwarf64; - + lldb_private::LazyBool m_is_optimized; + dw_addr_t m_addr_base; // Value of DW_AT_addr_base + dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the offset of + // the base compile unit in the main object file + void ParseProducerInfo (); + + static void + IndexPrivate (DWARFCompileUnit* dwarf_cu, + const lldb::LanguageType cu_language, + const DWARFFormValue::FixedFormSizes& fixed_form_sizes, + const dw_offset_t cu_offset, + NameToDIE& func_basenames, + NameToDIE& func_fullnames, + NameToDIE& func_methods, + NameToDIE& func_selectors, + NameToDIE& objc_class_selectors, + NameToDIE& globals, + NameToDIE& types, + NameToDIE& namespaces); + private: + + const DWARFDebugInfoEntry* + GetCompileUnitDIEPtrOnly() + { + ExtractDIEsIfNeeded (true); + if (m_die_array.empty()) + return NULL; + return &m_die_array[0]; + } + + const DWARFDebugInfoEntry* + DIEPtr() + { + ExtractDIEsIfNeeded (false); + if (m_die_array.empty()) + return NULL; + return &m_die_array[0]; + } + + DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit); }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp new file mode 100644 index 000000000000..0564de9e5dd1 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -0,0 +1,543 @@ +//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDIE.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugAbbrev.h" +#include "DWARFDebugAranges.h" +#include "DWARFDebugInfo.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDebugRanges.h" +#include "DWARFDeclContext.h" +#include "DWARFDIECollection.h" +#include "DWARFFormValue.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeSystem.h" + +using namespace lldb_private; + +DIERef +DWARFDIE::GetDIERef() const +{ + if (!IsValid()) + return DIERef(); + + dw_offset_t cu_offset = m_cu->GetOffset(); + if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) + cu_offset = m_cu->GetBaseObjOffset(); + return DIERef(cu_offset, m_die->GetOffset()); +} + +dw_tag_t +DWARFDIE::Tag() const +{ + if (m_die) + return m_die->Tag(); + else + return 0; +} + +const char * +DWARFDIE::GetTagAsCString () const +{ + return lldb_private::DW_TAG_value_to_name (Tag()); +} + +DWARFDIE +DWARFDIE::GetParent () const +{ + if (IsValid()) + return DWARFDIE(m_cu, m_die->GetParent()); + else + return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetFirstChild () const +{ + if (IsValid()) + return DWARFDIE(m_cu, m_die->GetFirstChild()); + else + return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetSibling () const +{ + if (IsValid()) + return DWARFDIE(m_cu, m_die->GetSibling()); + else + return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetReferencedDIE (const dw_attr_t attr) const +{ + const dw_offset_t die_offset = GetAttributeValueAsReference (attr, DW_INVALID_OFFSET); + if (die_offset != DW_INVALID_OFFSET) + return GetDIE(die_offset); + else + return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetDIE (dw_offset_t die_offset) const +{ + if (IsValid()) + return m_cu->GetDIE(die_offset); + else + return DWARFDIE(); +} + +const char * +DWARFDIE::GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const +{ + if (IsValid()) + return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, fail_value); + else + return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const +{ + if (IsValid()) + return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, fail_value); + else + return fail_value; +} + +int64_t +DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const +{ + if (IsValid()) + return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, fail_value); + else + return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const +{ + if (IsValid()) + return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, fail_value); + else + return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const +{ + if (IsValid()) + return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, fail_value); + else + return fail_value; +} + + +DWARFDIE +DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const +{ + if (IsValid()) + { + SymbolFileDWARF *dwarf= GetDWARF(); + DWARFCompileUnit *cu = GetCU(); + DWARFDebugInfoEntry* function_die = nullptr; + DWARFDebugInfoEntry* block_die = nullptr; + if (m_die->LookupAddress (file_addr, + dwarf, + cu, + &function_die, + &block_die)) + { + if (block_die && block_die != function_die) + { + if (cu->ContainsDIEOffset(block_die->GetOffset())) + return DWARFDIE(cu, block_die); + else + return DWARFDIE(dwarf->DebugInfo()->GetCompileUnitContainingDIE(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die); + } + } + } + return DWARFDIE(); +} + +lldb::user_id_t +DWARFDIE::GetID () const +{ + const dw_offset_t die_offset = GetOffset(); + if (die_offset != DW_INVALID_OFFSET) + { + lldb::user_id_t id = 0; + SymbolFileDWARF *dwarf = GetDWARF(); + if (dwarf) + id = dwarf->MakeUserID(die_offset); + else + id = die_offset; + + if (m_cu) + { + lldb::user_id_t cu_id = m_cu->GetID()&0xffffffff00000000ull; + assert ((id&0xffffffff00000000ull) == 0 || + (cu_id&0xffffffff00000000ll) == 0 || + (id&0xffffffff00000000ull) == (cu_id&0xffffffff00000000ll)); + id |= cu_id; + } + return id; + } + return LLDB_INVALID_UID; +} + +const char * +DWARFDIE::GetName () const +{ + if (IsValid()) + return m_die->GetName (GetDWARF(), m_cu); + else + return nullptr; +} + +const char * +DWARFDIE::GetMangledName () const +{ + if (IsValid()) + return m_die->GetMangledName (GetDWARF(), m_cu); + else + return nullptr; +} + +const char * +DWARFDIE::GetPubname () const +{ + if (IsValid()) + return m_die->GetPubname (GetDWARF(), m_cu); + else + return nullptr; +} + +const char * +DWARFDIE::GetQualifiedName (std::string &storage) const +{ + if (IsValid()) + return m_die->GetQualifiedName (GetDWARF(), m_cu, storage); + else + return nullptr; +} + +lldb::LanguageType +DWARFDIE::GetLanguage () const +{ + if (IsValid()) + return m_cu->GetLanguageType(); + else + return lldb::eLanguageTypeUnknown; +} + + +lldb::ModuleSP +DWARFDIE::GetModule () const +{ + SymbolFileDWARF *dwarf = GetDWARF(); + if (dwarf) + return dwarf->GetObjectFile()->GetModule(); + else + return lldb::ModuleSP(); +} + +lldb_private::CompileUnit * +DWARFDIE::GetLLDBCompileUnit () const +{ + if (IsValid()) + return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU()); + else + return nullptr; +} + +lldb_private::Type * +DWARFDIE::ResolveType () const +{ + if (IsValid()) + return GetDWARF()->ResolveType(*this, true); + else + return nullptr; +} + +lldb_private::Type * +DWARFDIE::ResolveTypeUID (lldb::user_id_t uid) const +{ + SymbolFileDWARF *dwarf = GetDWARF(); + if (dwarf) + return dwarf->ResolveTypeUID(uid); + else + return nullptr; +} + +void +DWARFDIE::GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const +{ + if (IsValid()) + { + DWARFDIE parent_decl_ctx_die = m_die->GetParentDeclContextDIE (GetDWARF(), GetCU()); + if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) + { + decl_context_dies.Append(parent_decl_ctx_die); + parent_decl_ctx_die.GetDeclContextDIEs (decl_context_dies); + } + } +} + +void +DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const +{ + if (IsValid()) + { + m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx); + } + else + { + dwarf_decl_ctx.Clear(); + } +} + +void +DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const +{ + const dw_tag_t tag = Tag(); + if (tag == DW_TAG_compile_unit) + return; + DWARFDIE parent = GetParent(); + if (parent) + parent.GetDWOContext(context); + switch (tag) + { + case DW_TAG_module: + context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + break; + case DW_TAG_namespace: + context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName()))); + break; + case DW_TAG_structure_type: + context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName()))); + break; + case DW_TAG_union_type: + context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + break; + case DW_TAG_class_type: + context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + break; + case DW_TAG_enumeration_type: + context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName()))); + break; + case DW_TAG_subprogram: + context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname()))); + break; + case DW_TAG_variable: + context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname()))); + break; + case DW_TAG_typedef: + context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + break; + default: + break; + } +} + + + +DWARFDIE +DWARFDIE::GetParentDeclContextDIE () const +{ + if (IsValid()) + return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu); + else + return DWARFDIE(); +} + + +dw_offset_t +DWARFDIE::GetOffset () const +{ + if (IsValid()) + return m_die->GetOffset(); + else + return DW_INVALID_OFFSET; +} + +dw_offset_t +DWARFDIE::GetCompileUnitRelativeOffset () const +{ + if (IsValid()) + return m_die->GetOffset() - m_cu->GetOffset(); + else + return DW_INVALID_OFFSET; +} + +SymbolFileDWARF * +DWARFDIE::GetDWARF () const +{ + if (m_cu) + return m_cu->GetSymbolFileDWARF(); + else + return nullptr; +} + +lldb_private::TypeSystem * +DWARFDIE::GetTypeSystem () const +{ + if (m_cu) + return m_cu->GetTypeSystem(); + else + return nullptr; +} + +DWARFASTParser * +DWARFDIE::GetDWARFParser () const +{ + lldb_private::TypeSystem *type_system = GetTypeSystem (); + if (type_system) + return type_system->GetDWARFParser(); + else + return nullptr; +} + +bool +DWARFDIE::IsStructOrClass () const +{ + const dw_tag_t tag = Tag(); + return tag == DW_TAG_class_type || tag == DW_TAG_structure_type; +} + + +DWARFDIE +DWARFDIE::GetContainingDWOModuleDIE () const +{ + if (IsValid()) + { + DWARFDIE top_module_die; + // Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so + for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent()) + { + const dw_tag_t tag = parent.Tag(); + if (tag == DW_TAG_module) + top_module_die = parent; + else if (tag == DW_TAG_compile_unit) + break; + } + + return top_module_die; + } + return DWARFDIE(); +} + +lldb::ModuleSP +DWARFDIE::GetContainingDWOModule () const +{ + if (IsValid()) + { + DWARFDIE dwo_module_die = GetContainingDWOModuleDIE(); + + if (dwo_module_die) + { + const char *module_name = dwo_module_die.GetName(); + if (module_name) + return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name)); + } + } + return lldb::ModuleSP(); +} + +bool +DWARFDIE::HasChildren () const +{ + if (m_die) + return m_die->HasChildren(); + else + return false; +} + +bool +DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type () const +{ + if (IsValid()) + return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); + else + return false; +} + +size_t +DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const +{ + if (IsValid()) + { + return m_die->GetAttributes (m_cu, + m_cu->GetFixedFormSizes(), + attributes, + depth); + } + if (depth == 0) + attributes.Clear(); + return 0; +} + + +bool +DWARFDIE::GetDIENamesAndRanges (const char * &name, + const char * &mangled, + DWARFRangeList& ranges, + int& decl_file, + int& decl_line, + int& decl_column, + int& call_file, + int& call_line, + int& call_column, + lldb_private::DWARFExpression *frame_base) const +{ + if (IsValid()) + { + return m_die->GetDIENamesAndRanges (GetDWARF(), + GetCU(), + name, + mangled, + ranges, + decl_file, + decl_line, + decl_column, + call_file, + call_line, + call_column, + frame_base); + } + else + return false; +} + +void +DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const +{ + if (s && IsValid()) + m_die->Dump (GetDWARF(), GetCU(), *s, recurse_depth); +} + + +bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs) +{ + return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU(); +} + +bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs) +{ + return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); +} + + diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h new file mode 100644 index 000000000000..db37a45ad01a --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -0,0 +1,281 @@ +//===-- DWARFDIE.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFDIE_h_ +#define SymbolFileDWARF_DWARFDIE_h_ + +#include "lldb/lldb-types.h" +#include "lldb/Core/dwarf.h" + +struct DIERef; +class DWARFASTParser; +class DWARFAttributes; +class DWARFCompileUnit; +class DWARFDebugInfoEntry; +class DWARFDeclContext; +class DWARFDIECollection; +class SymbolFileDWARF; + +class DWARFDIE +{ +public: + DWARFDIE () : + m_cu (nullptr), + m_die (nullptr) + { + } + + DWARFDIE (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) : + m_cu (cu), + m_die (die) + { + } + + DWARFDIE (const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) : + m_cu (const_cast<DWARFCompileUnit *>(cu)), + m_die (die) + { + } + + DWARFDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) : + m_cu (cu), + m_die (const_cast<DWARFDebugInfoEntry *>(die)) + { + } + + DWARFDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) : + m_cu (const_cast<DWARFCompileUnit *>(cu)), + m_die (const_cast<DWARFDebugInfoEntry *>(die)) + { + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + operator bool () const + { + return IsValid(); + } + + bool + IsValid() const + { + return m_cu && m_die; + } + + bool + IsStructOrClass () const; + + bool + HasChildren () const; + + bool + Supports_DW_AT_APPLE_objc_complete_type () const; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + SymbolFileDWARF * + GetDWARF () const; + + DWARFCompileUnit * + GetCU() const + { + return m_cu; + } + + DWARFDebugInfoEntry * + GetDIE() const + { + return m_die; + } + + DIERef + GetDIERef() const; + + lldb_private::TypeSystem * + GetTypeSystem () const; + + DWARFASTParser * + GetDWARFParser () const; + + void + Set (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) + { + if (cu && die) + { + m_cu = cu; + m_die = die; + } + else + { + Clear(); + } + } + + void + Clear () + { + m_cu = nullptr; + m_die = nullptr; + } + + lldb::ModuleSP + GetContainingDWOModule () const; + + DWARFDIE + GetContainingDWOModuleDIE () const; + + //---------------------------------------------------------------------- + // Accessing information about a DIE + //---------------------------------------------------------------------- + dw_tag_t + Tag() const; + + const char * + GetTagAsCString () const; + + dw_offset_t + GetOffset () const; + + dw_offset_t + GetCompileUnitRelativeOffset () const; + + //---------------------------------------------------------------------- + // Get the LLDB user ID for this DIE. This is often just the DIE offset, + // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if + // we are doing Darwin DWARF in .o file, or DWARF stand alone debug + // info. + //---------------------------------------------------------------------- + lldb::user_id_t + GetID() const; + + const char * + GetName () const; + + const char * + GetMangledName () const; + + const char * + GetPubname () const; + + const char * + GetQualifiedName (std::string &storage) const; + + lldb::LanguageType + GetLanguage () const; + + lldb::ModuleSP + GetModule () const; + + lldb_private::CompileUnit * + GetLLDBCompileUnit () const; + + lldb_private::Type * + ResolveType () const; + + // Resolve a type by UID using this DIE's DWARF file + lldb_private::Type * + ResolveTypeUID (lldb::user_id_t uid) const; + + //---------------------------------------------------------------------- + // Functions for obtaining DIE relations and references + //---------------------------------------------------------------------- + + DWARFDIE + GetParent () const; + + DWARFDIE + GetFirstChild () const; + + DWARFDIE + GetSibling () const; + + DWARFDIE + GetReferencedDIE (const dw_attr_t attr) const; + + //---------------------------------------------------------------------- + // Get a another DIE from the same DWARF file as this DIE. This will + // check the current DIE's compile unit first to see if "die_offset" is + // in the same compile unit, and fall back to checking the DWARF file. + //---------------------------------------------------------------------- + DWARFDIE + GetDIE (dw_offset_t die_offset) const; + + DWARFDIE + LookupDeepestBlock (lldb::addr_t file_addr) const; + + DWARFDIE + GetParentDeclContextDIE () const; + + //---------------------------------------------------------------------- + // DeclContext related functions + //---------------------------------------------------------------------- + void + GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const; + + void + GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const; + + void + GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const; + + //---------------------------------------------------------------------- + // Getting attribute values from the DIE. + // + // GetAttributeValueAsXXX() functions should only be used if you are + // looking for one or two attributes on a DIE. If you are trying to + // parse all attributes, use GetAttributes (...) instead + //---------------------------------------------------------------------- + const char * + GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const; + + uint64_t + GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const; + + int64_t + GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const; + + uint64_t + GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const; + + uint64_t + GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const; + + size_t + GetAttributes (DWARFAttributes &attributes, uint32_t depth = 0) const; + + bool + GetDIENamesAndRanges (const char * &name, + const char * &mangled, + DWARFRangeList& ranges, + int& decl_file, + int& decl_line, + int& decl_column, + int& call_file, + int& call_line, + int& call_column, + lldb_private::DWARFExpression *frame_base) const; + + //---------------------------------------------------------------------- + // Pretty printing + //---------------------------------------------------------------------- + + void + Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const; + +protected: + DWARFCompileUnit *m_cu; + DWARFDebugInfoEntry *m_die; +}; + +bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs); +bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs); + +#endif // SymbolFileDWARF_DWARFDIE_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp index 1beb75d33642..9e021c7185bd 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp @@ -13,13 +13,11 @@ #include "lldb/Core/Stream.h" -#include "DWARFDebugInfoEntry.h" - using namespace lldb_private; using namespace std; bool -DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die) +DWARFDIECollection::Insert(const DWARFDIE &die) { iterator end_pos = m_dies.end(); iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die); @@ -30,17 +28,17 @@ DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die) } void -DWARFDIECollection::Append (const DWARFDebugInfoEntry *die) +DWARFDIECollection::Append (const DWARFDIE &die) { m_dies.push_back (die); } -const DWARFDebugInfoEntry * -DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const +DWARFDIE +DWARFDIECollection::GetDIEAtIndex(uint32_t idx) const { if (idx < m_dies.size()) return m_dies[idx]; - return NULL; + return DWARFDIE(); } @@ -55,8 +53,6 @@ DWARFDIECollection::Dump(Stream *s, const char* title) const { if (title && title[0] != '\0') s->Printf( "%s\n", title); - const_iterator end_pos = m_dies.end(); - const_iterator pos; - for (pos = m_dies.begin(); pos != end_pos; ++pos) - s->Printf( "0x%8.8x\n", (*pos)->GetOffset()); + for (const auto &die : m_dies) + s->Printf( "0x%8.8x\n", die.GetOffset()); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h index 173d0a5604d0..e39e1aa4ccda 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h @@ -10,7 +10,7 @@ #ifndef SymbolFileDWARF_DWARFDIECollection_h_ #define SymbolFileDWARF_DWARFDIECollection_h_ -#include "SymbolFileDWARF.h" +#include "DWARFDIE.h" #include <vector> class DWARFDIECollection @@ -25,22 +25,22 @@ public: } void - Append (const DWARFDebugInfoEntry *die); + Append (const DWARFDIE &die); void Dump(lldb_private::Stream *s, const char* title) const; - const DWARFDebugInfoEntry* - GetDIEPtrAtIndex(uint32_t idx) const; + DWARFDIE + GetDIEAtIndex (uint32_t idx) const; bool - Insert(const DWARFDebugInfoEntry *die); + Insert(const DWARFDIE &die); size_t Size() const; protected: - typedef std::vector<const DWARFDebugInfoEntry *> collection; + typedef std::vector<DWARFDIE> collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h index ba2e8ad08acc..0281b5ad5c89 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -19,10 +19,10 @@ namespace lldb_private { class DWARFDataExtractor : public lldb_private::DataExtractor { public: - DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { }; + DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { } DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) : - DataExtractor(data, offset, length), m_is_dwarf64(false) { }; + DataExtractor(data, offset, length), m_is_dwarf64(false) { } uint64_t GetDWARFInitialLength(lldb::offset_t *offset_ptr) const; @@ -43,4 +43,3 @@ protected: } #endif // liblldb_DWARFDataExtractor_h_ - diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 393434800c01..a1b00d1892e9 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -103,57 +103,6 @@ DWARFDebugInfo::GetCompileUnitAranges () return *m_cu_aranges_ap.get(); } - -//---------------------------------------------------------------------- -// LookupAddress -//---------------------------------------------------------------------- -bool -DWARFDebugInfo::LookupAddress -( - const dw_addr_t address, - const dw_offset_t hint_die_offset, - DWARFCompileUnitSP& cu_sp, - DWARFDebugInfoEntry** function_die, - DWARFDebugInfoEntry** block_die -) -{ - - if (hint_die_offset != DW_INVALID_OFFSET) - cu_sp = GetCompileUnit(hint_die_offset); - else - { - DWARFDebugAranges &cu_aranges = GetCompileUnitAranges (); - const dw_offset_t cu_offset = cu_aranges.FindAddress (address); - cu_sp = GetCompileUnit(cu_offset); - } - - if (cu_sp.get()) - { - if (cu_sp->LookupAddress(address, function_die, block_die)) - return true; - cu_sp.reset(); - } - else - { - // The hint_die_offset may have been a pointer to the actual item that - // we are looking for - DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp); - if (die_ptr) - { - if (cu_sp.get()) - { - if (function_die || block_die) - return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die); - - // We only wanted the compile unit that contained this address - return true; - } - } - } - return false; -} - - void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { @@ -213,19 +162,13 @@ DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const return false; } -static int -CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem) +bool +DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp) { - const dw_offset_t key_cu_offset = *(dw_offset_t*) key; - const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset(); - if (key_cu_offset < cu_offset) - return -1; - if (key_cu_offset > cu_offset) - return 1; - return 0; + return offset < cu_sp->GetOffset(); } -DWARFCompileUnitSP +DWARFCompileUnit * DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) { DWARFCompileUnitSP cu_sp; @@ -234,41 +177,80 @@ DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) { ParseCompileUnitHeadersIfNeeded(); - DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset); - if (match) + // Watch out for single compile unit executable as they are pretty common + const size_t num_cus = m_compile_units.size(); + if (num_cus == 1) { - cu_sp = *match; - cu_idx = match - &m_compile_units[0]; + if (m_compile_units[0]->GetOffset() == cu_offset) + { + cu_sp = m_compile_units[0]; + cu_idx = 0; + } + } + else if (num_cus) + { + CompileUnitColl::const_iterator end_pos = m_compile_units.end(); + CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); + CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset); + if (pos != begin_pos) + { + --pos; + if ((*pos)->GetOffset() == cu_offset) + { + cu_sp = *pos; + cu_idx = std::distance(begin_pos, pos); + } + } } } if (idx_ptr) *idx_ptr = cu_idx; - return cu_sp; + return cu_sp.get(); } -DWARFCompileUnitSP -DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) +DWARFCompileUnit * +DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref) { + dw_offset_t search_offset = die_ref.die_offset; + bool is_cu_offset = false; + if (m_dwarf2Data->GetID() == 0 && die_ref.cu_offset != DW_INVALID_OFFSET) + { + is_cu_offset = true; + search_offset = die_ref.cu_offset; + } + DWARFCompileUnitSP cu_sp; - if (die_offset != DW_INVALID_OFFSET) + if (search_offset != DW_INVALID_OFFSET) { ParseCompileUnitHeadersIfNeeded(); - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator pos; - - for (pos = m_compile_units.begin(); pos != end_pos; ++pos) + // Watch out for single compile unit executable as they are pretty common + const size_t num_cus = m_compile_units.size(); + if (num_cus == 1) { - dw_offset_t cu_start_offset = (*pos)->GetOffset(); - dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset(); - if (cu_start_offset <= die_offset && die_offset < cu_end_offset) + if ((is_cu_offset && m_compile_units[0]->GetOffset() == search_offset) || + (!is_cu_offset && m_compile_units[0]->ContainsDIEOffset(search_offset))) { - cu_sp = *pos; - break; + cu_sp = m_compile_units[0]; + } + } + else if (num_cus) + { + CompileUnitColl::const_iterator end_pos = m_compile_units.end(); + CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); + CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, search_offset, OffsetLessThanCompileUnitOffset); + if (pos != begin_pos) + { + --pos; + if ((is_cu_offset && (*pos)->GetOffset() == search_offset) || + (!is_cu_offset && (*pos)->ContainsDIEOffset(search_offset))) + { + cu_sp = *pos; + } } } } - return cu_sp; + return cu_sp.get(); } //---------------------------------------------------------------------- @@ -276,73 +258,15 @@ DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) // // Get the DIE (Debug Information Entry) with the specified offset. //---------------------------------------------------------------------- -DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) -{ - DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); - if (cu_sp_ptr) - *cu_sp_ptr = cu_sp; - if (cu_sp.get()) - return cu_sp->GetDIEPtr(die_offset); - return NULL; // Not found in any compile units -} - -DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle) -{ - assert (cu_handle); - DWARFDebugInfoEntry* die = NULL; - if (*cu_handle) - die = (*cu_handle)->GetDIEPtr(die_offset); - - if (die == NULL) - { - DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset)); - if (cu_sp.get()) - { - *cu_handle = cu_sp.get(); - die = cu_sp->GetDIEPtr(die_offset); - } - } - if (die == NULL) - *cu_handle = NULL; - return die; -} - - -const DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) -{ - DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); - if (cu_sp_ptr) - *cu_sp_ptr = cu_sp; - if (cu_sp.get()) - return cu_sp->GetDIEPtrContainingOffset(die_offset); - - return NULL; // Not found in any compile units - -} - -//---------------------------------------------------------------------- -// AddCompileUnit -//---------------------------------------------------------------------- -void -DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu) +DWARFDIE +DWARFDebugInfo::GetDIE(const DIERef& die_ref) { - m_compile_units.push_back(cu); + DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_ref); + if (cu) + return cu->GetDIE (die_ref.die_offset); + return DWARFDIE(); // Not found } -/* -void -DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die) -{ - m_die_array.push_back(die); -} -*/ - - - - //---------------------------------------------------------------------- // Parse // @@ -372,7 +296,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user depth = 0; // Call the callback function with no DIE pointer for the compile unit // and get the offset that we are to continue to parse from - offset = callback(dwarf2Data, cu, NULL, offset, depth, userData); + offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData); // Make sure we are within our compile unit if (offset < next_cu_offset) @@ -383,7 +307,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) { // Call the callback function with DIE pointer that falls within the compile unit - offset = callback(dwarf2Data, cu, &die, offset, depth, userData); + offset = callback(dwarf2Data, cu.get(), &die, offset, depth, userData); if (die.IsNULL()) { @@ -450,7 +374,7 @@ typedef struct DumpInfo static dw_offset_t DumpCallback ( SymbolFileDWARF* dwarf2Data, - DWARFCompileUnitSP& cu_sp, + DWARFCompileUnit* cu, DWARFDebugInfoEntry* die, const dw_offset_t next_offset, const uint32_t curr_depth, @@ -458,9 +382,6 @@ static dw_offset_t DumpCallback ) { DumpInfo* dumpInfo = (DumpInfo*)userData; - - const DWARFCompileUnit* cu = cu_sp.get(); - Stream *s = dumpInfo->strm; bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); @@ -676,12 +597,12 @@ DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recur ParseCompileUnitHeadersIfNeeded(); for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) { - const DWARFCompileUnitSP& cu_sp = *pos; - DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo); + DWARFCompileUnit *cu = pos->get(); + DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo); - const DWARFDebugInfoEntry* die = cu_sp->DIE(); + const DWARFDIE die = cu->DIE(); if (die) - die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth); + die.Dump(s, recurse_depth); } } @@ -707,7 +628,7 @@ typedef struct FindCallbackStringInfoTag static dw_offset_t FindCallbackString ( SymbolFileDWARF* dwarf2Data, - DWARFCompileUnitSP& cu_sp, + DWARFCompileUnit* cu, DWARFDebugInfoEntry* die, const dw_offset_t next_offset, const uint32_t curr_depth, @@ -715,7 +636,6 @@ static dw_offset_t FindCallbackString ) { FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData; - const DWARFCompileUnit* cu = cu_sp.get(); if (die) { diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index 50a7ae76921f..ea2e204db702 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -16,19 +16,18 @@ #include "lldb/lldb-private.h" #include "lldb/lldb-private.h" #include "SymbolFileDWARF.h" +#include "DWARFDIE.h" typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap; typedef CStringToDIEMap::iterator CStringToDIEMapIter; typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter; -typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; - class DWARFDebugInfo { public: typedef dw_offset_t (*Callback)( SymbolFileDWARF* dwarf2Data, - DWARFCompileUnitSP& cu_shared_ptr, + DWARFCompileUnit* cu, DWARFDebugInfoEntry* die, const dw_offset_t next_offset, const uint32_t depth, @@ -37,24 +36,13 @@ public: DWARFDebugInfo(); void SetDwarfData(SymbolFileDWARF* dwarf2Data); - bool LookupAddress( - const dw_addr_t address, - const dw_offset_t cu_offset, // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually - DWARFCompileUnitSP& cu_shared_ptr, - DWARFDebugInfoEntry** function_die, - DWARFDebugInfoEntry** block_die); - - void AddCompileUnit(DWARFCompileUnitSP& cu); size_t GetNumCompileUnits(); bool ContainsCompileUnit (const DWARFCompileUnit *cu) const; - DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx); - DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); - DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset); + DWARFCompileUnit* GetCompileUnitAtIndex (uint32_t idx); + DWARFCompileUnit* GetCompileUnit (dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); + DWARFCompileUnit* GetCompileUnitContainingDIE (const DIERef& die_ref); - DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr); - DWARFDebugInfoEntry* GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle); - - const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr); + DWARFDIE GetDIE (const DIERef& die_ref); void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth); static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData); @@ -74,8 +62,17 @@ public: GetCompileUnitAranges (); protected: - SymbolFileDWARF* m_dwarf2Data; + typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; + + static bool + OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp); + typedef std::vector<DWARFCompileUnitSP> CompileUnitColl; + + //---------------------------------------------------------------------- + // Member variables + //---------------------------------------------------------------------- + SymbolFileDWARF* m_dwarf2Data; CompileUnitColl m_compile_units; std::unique_ptr<DWARFDebugAranges> m_cu_aranges_ap; // A quick address to compile unit table diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 0ad1f1a3a95a..b9d825489aef 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -19,107 +19,26 @@ #include "lldb/Symbol/ObjectFile.h" #include "DWARFCompileUnit.h" -#include "SymbolFileDWARF.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDIECollection.h" #include "DWARFFormValue.h" -#include "DWARFLocationDescription.h" -#include "DWARFLocationList.h" #include "DWARFDebugRanges.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDwo.h" using namespace lldb_private; using namespace std; extern int g_verbose; - - -DWARFDebugInfoEntry::Attributes::Attributes() : - m_infos() -{ -} - -DWARFDebugInfoEntry::Attributes::~Attributes() -{ -} - - -uint32_t -DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const -{ - collection::const_iterator end = m_infos.end(); - collection::const_iterator beg = m_infos.begin(); - collection::const_iterator pos; - for (pos = beg; pos != end; ++pos) - { - if (pos->attr == attr) - return std::distance(beg, pos); - } - return UINT32_MAX; -} - -void -DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form) -{ - Info info = { cu, attr_die_offset, attr, form }; - m_infos.push_back(info); -} - -bool -DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const -{ - return FindAttributeIndex(attr) != UINT32_MAX; -} - -bool -DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr) -{ - uint32_t attr_index = FindAttributeIndex(attr); - if (attr_index != UINT32_MAX) - { - m_infos.erase(m_infos.begin() + attr_index); - return true; - } - return false; -} - -bool -DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const -{ - form_value.SetCompileUnit(CompileUnitAtIndex(i)); - form_value.SetForm(FormAtIndex(i)); - lldb::offset_t offset = DIEOffsetAtIndex(i); - return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset); -} - -uint64_t -DWARFDebugInfoEntry::Attributes::FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const -{ - const uint32_t attr_idx = FindAttributeIndex (attr); - if (attr_idx != UINT32_MAX) - return FormValueAsUnsignedAtIndex (dwarf2Data, attr_idx, fail_value); - return fail_value; -} - -uint64_t -DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const -{ - DWARFFormValue form_value; - if (ExtractFormValueAtIndex(dwarf2Data, i, form_value)) - return form_value.Reference(); - return fail_value; -} - - - bool DWARFDebugInfoEntry::FastExtract ( const DWARFDataExtractor& debug_info_data, const DWARFCompileUnit* cu, - const uint8_t *fixed_form_sizes, + const DWARFFormValue::FixedFormSizes& fixed_form_sizes, lldb::offset_t *offset_ptr ) { @@ -158,7 +77,7 @@ DWARFDebugInfoEntry::FastExtract { form = abbrevDecl->GetFormByIndexUnchecked(i); - const uint8_t fixed_skip_size = fixed_form_sizes [form]; + const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); if (fixed_skip_size) offset += fixed_skip_size; else @@ -226,9 +145,11 @@ DWARFDebugInfoEntry::FastExtract break; // signed or unsigned LEB 128 values - case DW_FORM_sdata : - case DW_FORM_udata : - case DW_FORM_ref_udata : + case DW_FORM_sdata : + case DW_FORM_udata : + case DW_FORM_ref_udata : + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index : debug_info_data.Skip_LEB128 (&offset); break; @@ -306,7 +227,7 @@ DWARFDebugInfoEntry::Extract bool isCompileUnitTag = m_tag == DW_TAG_compile_unit; if (cu && isCompileUnitTag) - ((DWARFCompileUnit*)cu)->SetBaseAddress(0); + const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0); // Skip all data in the .debug_info for the attributes const uint32_t numAttributes = abbrevDecl->NumAttributes(); @@ -323,7 +244,7 @@ DWARFDebugInfoEntry::Extract if (form_value.ExtractValue(debug_info_data, &offset)) { if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) - ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned()); + const_cast<DWARFCompileUnit*>(cu)->SetBaseAddress(form_value.Address()); } } else @@ -389,9 +310,11 @@ DWARFDebugInfoEntry::Extract break; // signed or unsigned LEB 128 values - case DW_FORM_sdata : - case DW_FORM_udata : - case DW_FORM_ref_udata : + case DW_FORM_sdata : + case DW_FORM_udata : + case DW_FORM_ref_udata : + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index : debug_info_data.Skip_LEB128(&offset); break; @@ -456,276 +379,6 @@ DWARFDebugInfoEntry::DumpAncestry } //---------------------------------------------------------------------- -// Compare two DIE by comparing all their attributes values, and -// following all DW_FORM_ref attributes and comparing their contents as -// well (except for DW_AT_sibling attributes. -// -// DWARFDebugInfoEntry::CompareState compare_state; -// int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true); -//---------------------------------------------------------------------- -//int -//DWARFDebugInfoEntry::Compare -//( -// SymbolFileDWARF* dwarf2Data, -// dw_offset_t a_die_offset, -// dw_offset_t b_die_offset, -// CompareState &compare_state, -// bool compare_siblings, -// bool compare_children -//) -//{ -// if (a_die_offset == b_die_offset) -// return 0; -// -// DWARFCompileUnitSP a_cu_sp; -// DWARFCompileUnitSP b_cu_sp; -// const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp); -// const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp); -// -// return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children); -//} -// -//int -//DWARFDebugInfoEntry::Compare -//( -// SymbolFileDWARF* dwarf2Data, -// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, -// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, -// CompareState &compare_state, -// bool compare_siblings, -// bool compare_children -//) -//{ -// if (a_die == b_die) -// return 0; -// -// if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset())) -// { -// // We are already comparing both of these types, so let -// // compares complete for the real result -// return 0; -// } -// -// //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset()); -// -// // Do we have two valid DIEs? -// if (a_die && b_die) -// { -// // Both DIE are valid -// int result = 0; -// -// const dw_tag_t a_tag = a_die->Tag(); -// const dw_tag_t b_tag = b_die->Tag(); -// if (a_tag == 0 && b_tag == 0) -// return 0; -// -// //printf(" comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag)); -// -// if (a_tag < b_tag) -// return -1; -// else if (a_tag > b_tag) -// return 1; -// -// DWARFDebugInfoEntry::Attributes a_attrs; -// DWARFDebugInfoEntry::Attributes b_attrs; -// size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs); -// size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs); -// if (a_attr_count != b_attr_count) -// { -// a_attrs.RemoveAttribute(DW_AT_sibling); -// b_attrs.RemoveAttribute(DW_AT_sibling); -// } -// -// a_attr_count = a_attrs.Size(); -// b_attr_count = b_attrs.Size(); -// -// DWARFFormValue a_form_value; -// DWARFFormValue b_form_value; -// -// if (a_attr_count != b_attr_count) -// { -// uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration); -// uint32_t a_name_index = UINT32_MAX; -// uint32_t b_name_index = UINT32_MAX; -// if (is_decl_index != UINT32_MAX) -// { -// if (a_attr_count == 2) -// { -// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); -// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); -// } -// } -// else -// { -// is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration); -// if (is_decl_index != UINT32_MAX && a_attr_count == 2) -// { -// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); -// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); -// } -// } -// if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX) -// { -// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) && -// b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value)) -// { -// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data()); -// if (result == 0) -// { -// a_attr_count = b_attr_count = 0; -// compare_children = false; -// } -// } -// } -// } -// -// if (a_attr_count < b_attr_count) -// return -1; -// if (a_attr_count > b_attr_count) -// return 1; -// -// -// // The number of attributes are the same... -// if (a_attr_count > 0) -// { -// const DWARFDataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data(); -// -// uint32_t i; -// for (i=0; i<a_attr_count; ++i) -// { -// const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i); -// const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i); -// //printf(" comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n", -// // a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr), -// // b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr)); -// -// if (a_attr < b_attr) -// return -1; -// else if (a_attr > b_attr) -// return 1; -// -// switch (a_attr) -// { -// // Since we call a form of GetAttributes which inlines the -// // attributes from DW_AT_abstract_origin and DW_AT_specification -// // we don't care if their values mismatch... -// case DW_AT_abstract_origin: -// case DW_AT_specification: -// case DW_AT_sibling: -// case DW_AT_containing_type: -// //printf(" action = IGNORE\n"); -// result = 0; -// break; // ignore -// -// default: -// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) && -// b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value)) -// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr); -// break; -// } -// -// //printf("\t result = %i\n", result); -// -// if (result != 0) -// { -// // Attributes weren't equal, lets see if we care? -// switch (a_attr) -// { -// case DW_AT_decl_file: -// // TODO: add the ability to compare files in two different compile units -// if (a_cu == b_cu) -// { -// //printf(" action = RETURN RESULT\n"); -// return result; // Only return the compare results when the compile units are the same and the decl_file attributes can be compared -// } -// else -// { -// result = 0; -// //printf(" action = IGNORE\n"); -// } -// break; -// -// default: -// switch (a_attrs.FormAtIndex(i)) -// { -// case DW_FORM_ref1: -// case DW_FORM_ref2: -// case DW_FORM_ref4: -// case DW_FORM_ref8: -// case DW_FORM_ref_udata: -// case DW_FORM_ref_addr: -// //printf(" action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu)); -// // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets... -// result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true); -// if (result != 0) -// return result; -// break; -// -// default: -// // We do care that they were different, return this result... -// //printf(" action = RETURN RESULT\n"); -// return result; -// } -// } -// } -// } -// } -// //printf(" SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag)); -// -// if (compare_children) -// { -// bool a_has_children = a_die->HasChildren(); -// bool b_has_children = b_die->HasChildren(); -// if (a_has_children == b_has_children) -// { -// // Both either have kids or don't -// if (a_has_children) -// result = Compare( dwarf2Data, -// a_cu, a_die->GetFirstChild(), -// b_cu, b_die->GetFirstChild(), -// compare_state, true, compare_children); -// else -// result = 0; -// } -// else if (!a_has_children) -// result = -1; // A doesn't have kids, but B does -// else -// result = 1; // A has kids, but B doesn't -// } -// -// if (compare_siblings) -// { -// result = Compare( dwarf2Data, -// a_cu, a_die->GetSibling(), -// b_cu, b_die->GetSibling(), -// compare_state, true, compare_children); -// } -// -// return result; -// } -// -// if (a_die == NULL) -// return -1; // a_die is NULL, yet b_die is non-NULL -// else -// return 1; // a_die is non-NULL, yet b_die is NULL -// -//} -// -// -//int -//DWARFDebugInfoEntry::Compare -//( -// SymbolFileDWARF* dwarf2Data, -// const DWARFCompileUnit* cu_a, -// const DWARFDebugInfoEntry* die_a, -// const DWARFCompileUnit* cu_a, -// const DWARFDebugInfoEntry* die_b, -// CompareState &compare_state -//) -//{ -//} - -//---------------------------------------------------------------------- // GetDIENamesAndRanges // // Gets the valid address ranges for a given DIE by looking for a @@ -739,7 +392,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges const DWARFCompileUnit* cu, const char * &name, const char * &mangled, - DWARFDebugRanges::RangeList& ranges, + DWARFRangeList& ranges, int& decl_file, int& decl_line, int& decl_column, @@ -749,12 +402,27 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges DWARFExpression *frame_base ) const { - if (dwarf2Data == NULL) + if (dwarf2Data == nullptr) return false; + SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); + if (dwo_symbol_file) + return GetDIENamesAndRanges(dwo_symbol_file, + dwo_symbol_file->GetCompileUnit(), + name, + mangled, + ranges, + decl_file, + decl_line, + decl_column, + call_file, + call_line, + call_column, + frame_base); + dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - std::vector<dw_offset_t> die_offsets; + std::vector<DIERef> die_refs; bool set_frame_base_loclist_addr = false; lldb::offset_t offset; @@ -784,7 +452,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges switch (attr) { case DW_AT_low_pc: - lo_pc = form_value.Unsigned(); + lo_pc = form_value.Address(); if (do_offset) hi_pc += lo_pc; @@ -792,13 +460,18 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges break; case DW_AT_entry_pc: - lo_pc = form_value.Unsigned(); + lo_pc = form_value.Address(); break; case DW_AT_high_pc: - hi_pc = form_value.Unsigned(); - if (form_value.Form() != DW_FORM_addr) + if (form_value.Form() == DW_FORM_addr || + form_value.Form() == DW_FORM_GNU_addr_index) { + hi_pc = form_value.Address(); + } + else + { + hi_pc = form_value.Unsigned(); if (lo_pc == LLDB_INVALID_ADDRESS) do_offset = hi_pc != LLDB_INVALID_ADDRESS; else @@ -819,21 +492,21 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges case DW_AT_name: if (name == NULL) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); + name = form_value.AsCString(); break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: if (mangled == NULL) - mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data()); + mangled = form_value.AsCString(); break; case DW_AT_abstract_origin: - die_offsets.push_back(form_value.Reference()); + die_refs.emplace_back(form_value); break; case DW_AT_specification: - die_offsets.push_back(form_value.Reference()); + die_refs.emplace_back(form_value); break; case DW_AT_decl_file: @@ -880,7 +553,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges const DWARFDataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data(); const dw_offset_t debug_loc_offset = form_value.Unsigned(); - size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset); + size_t loc_list_length = DWARFExpression::LocationListSize(cu, debug_loc_data, debug_loc_offset); if (loc_list_length > 0) { frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); @@ -910,9 +583,9 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges if (lo_pc != LLDB_INVALID_ADDRESS) { if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) - ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc)); + ranges.Append(DWARFRangeList::Entry (lo_pc, hi_pc - lo_pc)); else - ranges.Append(DWARFDebugRanges::Range (lo_pc, 0)); + ranges.Append(DWARFRangeList::Entry (lo_pc, 0)); } } @@ -925,18 +598,13 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges if (ranges.IsEmpty() || name == NULL || mangled == NULL) { - std::vector<dw_offset_t>::const_iterator pos; - std::vector<dw_offset_t>::const_iterator end = die_offsets.end(); - for (pos = die_offsets.begin(); pos != end; ++pos) + for (const DIERef& die_ref : die_refs) { - DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = NULL; - dw_offset_t die_offset = *pos; - if (die_offset != DW_INVALID_OFFSET) + if (die_ref.die_offset != DW_INVALID_OFFSET) { - die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr); + DWARFDIE die = dwarf2Data->DebugInfo()->GetDIE(die_ref); if (die) - die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column); + die.GetDIE()->GetDIENamesAndRanges(die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column); } } } @@ -1023,10 +691,10 @@ DWARFDebugInfoEntry::DumpLocation Stream &s ) const { - const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly(); + const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly(); const char *cu_name = NULL; - if (cu_die != NULL) - cu_name = cu_die->GetName (dwarf2Data, cu); + if (cu_die) + cu_name = cu_die.GetName (); const char *obj_file_name = NULL; ObjectFile *obj_file = dwarf2Data->GetObjectFile(); if (obj_file) @@ -1062,7 +730,6 @@ DWARFDebugInfoEntry::DumpAttribute bool verbose = s.GetVerbose(); bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm); - const DWARFDataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL; if (verbose) s.Offset (*offset_ptr); else @@ -1094,7 +761,7 @@ DWARFDebugInfoEntry::DumpAttribute // Always dump form value if verbose is enabled if (verbose) { - form_value.Dump(s, debug_str_data); + form_value.Dump(s); } @@ -1127,12 +794,16 @@ DWARFDebugInfoEntry::DumpAttribute if (blockData) { if (!verbose) - form_value.Dump(s, debug_str_data); + form_value.Dump(s); // Location description is inlined in data in the form value DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned()); if ( verbose ) s.PutCString(" ( "); - print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false); + DWARFExpression::PrintDWARFExpression(s, + locationData, + DWARFCompileUnit::GetAddressByteSize(cu), + 4, + false); if ( verbose ) s.PutCString(" )"); } else @@ -1144,13 +815,16 @@ DWARFDebugInfoEntry::DumpAttribute if (dwarf2Data) { if ( !verbose ) - form_value.Dump(s, debug_str_data); - DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset); + form_value.Dump(s); + DWARFExpression::PrintDWARFLocationList(s, + cu, + dwarf2Data->get_debug_loc_data(), + debug_loc_offset); } else { if ( !verbose ) - form_value.Dump(s, NULL); + form_value.Dump(s); } } } @@ -1160,7 +834,7 @@ DWARFDebugInfoEntry::DumpAttribute case DW_AT_specification: { uint64_t abstract_die_offset = form_value.Reference(); - form_value.Dump(s, debug_str_data); + form_value.Dump(s); // *ostrm_ptr << HEX32 << abstract_die_offset << " ( "; if ( verbose ) s.PutCString(" ( "); GetName(dwarf2Data, cu, abstract_die_offset, s); @@ -1172,7 +846,7 @@ DWARFDebugInfoEntry::DumpAttribute { uint64_t type_die_offset = form_value.Reference(); if (!verbose) - form_value.Dump(s, debug_str_data); + form_value.Dump(s); s.PutCString(" ( "); AppendTypeName(dwarf2Data, cu, type_die_offset, s); s.PutCString(" )"); @@ -1182,7 +856,7 @@ DWARFDebugInfoEntry::DumpAttribute case DW_AT_ranges: { if ( !verbose ) - form_value.Dump(s, debug_str_data); + form_value.Dump(s); lldb::offset_t ranges_offset = form_value.Unsigned(); dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; if (dwarf2Data) @@ -1192,7 +866,7 @@ DWARFDebugInfoEntry::DumpAttribute default: if ( !verbose ) - form_value.Dump(s, debug_str_data); + form_value.Dump(s); break; } @@ -1206,24 +880,37 @@ DWARFDebugInfoEntry::DumpAttribute // take precedence (this can happen for declaration attributes). //---------------------------------------------------------------------- size_t -DWARFDebugInfoEntry::GetAttributes -( - SymbolFileDWARF* dwarf2Data, - const DWARFCompileUnit* cu, - const uint8_t *fixed_form_sizes, - DWARFDebugInfoEntry::Attributes& attributes, - uint32_t curr_depth -) const +DWARFDebugInfoEntry::GetAttributes (const DWARFCompileUnit* cu, + DWARFFormValue::FixedFormSizes fixed_form_sizes, + DWARFAttributes& attributes, + uint32_t curr_depth) const { - lldb::offset_t offset; - const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); + SymbolFileDWARF* dwarf2Data = nullptr; + const DWARFAbbreviationDeclaration* abbrevDecl = nullptr; + lldb::offset_t offset = 0; + if (cu) + { + if (m_tag != DW_TAG_compile_unit) + { + SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); + if (dwo_symbol_file) + return GetAttributes(dwo_symbol_file->GetCompileUnit(), + fixed_form_sizes, + attributes, + curr_depth); + } + + dwarf2Data = cu->GetSymbolFileDWARF(); + abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); + } if (abbrevDecl) { const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); - if (fixed_form_sizes == NULL) - fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64()); + if (fixed_form_sizes.Empty()) + fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize( + cu->GetAddressByteSize(), cu->IsDWARF64()); const uint32_t num_attributes = abbrevDecl->NumAttributes(); uint32_t i; @@ -1258,26 +945,15 @@ DWARFDebugInfoEntry::GetAttributes DWARFFormValue form_value (cu, form); if (form_value.ExtractValue(debug_info_data, &offset)) { - const DWARFDebugInfoEntry* die = NULL; dw_offset_t die_offset = form_value.Reference(); - if (cu->ContainsDIEOffset(die_offset)) - { - die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset); - if (die) - die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1); - } - else - { - DWARFCompileUnitSP cu_sp_ptr; - die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr); - if (die) - die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1); - } + DWARFDIE spec_die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(die_offset); + if (spec_die) + spec_die.GetAttributes(attributes, curr_depth + 1); } } else { - const uint8_t fixed_skip_size = fixed_form_sizes [form]; + const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); if (fixed_skip_size) offset += fixed_skip_size; else @@ -1308,9 +984,19 @@ DWARFDebugInfoEntry::GetAttributeValue const DWARFCompileUnit* cu, const dw_attr_t attr, DWARFFormValue& form_value, - dw_offset_t* end_attr_offset_ptr + dw_offset_t* end_attr_offset_ptr, + bool check_specification_or_abstract_origin ) const { + SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); + if (dwo_symbol_file && m_tag != DW_TAG_compile_unit) + return GetAttributeValue(dwo_symbol_file, + dwo_symbol_file->GetCompileUnit(), + attr, + form_value, + end_attr_offset_ptr, + check_specification_or_abstract_origin); + lldb::offset_t offset; const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); @@ -1338,7 +1024,58 @@ DWARFDebugInfoEntry::GetAttributeValue } } - return 0; + if (check_specification_or_abstract_origin) + { + if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) + { + DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference()); + if (die) + { + dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(), + die.GetCU(), + attr, + form_value, + end_attr_offset_ptr, + false); + if (die_offset) + return die_offset; + } + } + + if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) + { + DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference()); + if (die) + { + dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(), + die.GetCU(), + attr, + form_value, + end_attr_offset_ptr, + false); + if (die_offset) + return die_offset; + } + } + } + + if (!dwo_symbol_file) + return 0; + + DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit(); + if (!dwo_cu) + return 0; + + DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); + if (!dwo_cu_die.IsValid()) + return 0; + + return dwo_cu_die.GetDIE()->GetAttributeValue(dwo_symbol_file, + dwo_cu, + attr, + form_value, + end_attr_offset_ptr, + check_specification_or_abstract_origin); } //---------------------------------------------------------------------- @@ -1355,11 +1092,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsString SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - const char* fail_value) const + const char* fail_value, + bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) - return form_value.AsCString(&dwarf2Data->get_debug_str_data()); + if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) + return form_value.AsCString(); return fail_value; } @@ -1374,11 +1112,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsUnsigned SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - uint64_t fail_value + uint64_t fail_value, + bool check_specification_or_abstract_origin ) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) + if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Unsigned(); return fail_value; } @@ -1394,11 +1133,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsSigned SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - int64_t fail_value + int64_t fail_value, + bool check_specification_or_abstract_origin ) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) + if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Signed(); return fail_value; } @@ -1415,15 +1155,32 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - uint64_t fail_value + uint64_t fail_value, + bool check_specification_or_abstract_origin ) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) + if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Reference(); return fail_value; } +uint64_t +DWARFDebugInfoEntry::GetAttributeValueAsAddress +( + SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit* cu, + const dw_attr_t attr, + uint64_t fail_value, + bool check_specification_or_abstract_origin +) const +{ + DWARFFormValue form_value; + if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) + return form_value.Address(); + return fail_value; +} + //---------------------------------------------------------------------- // GetAttributeHighPC // @@ -1438,17 +1195,19 @@ DWARFDebugInfoEntry::GetAttributeHighPC SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, dw_addr_t lo_pc, - uint64_t fail_value + uint64_t fail_value, + bool check_specification_or_abstract_origin ) const { DWARFFormValue form_value; - - if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value)) + if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin)) { - dw_addr_t hi_pc = form_value.Unsigned(); - if (form_value.Form() != DW_FORM_addr) - hi_pc += lo_pc; // DWARF4 can specify the hi_pc as an <offset-from-lowpc> - return hi_pc; + dw_form_t form = form_value.Form(); + if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index) + return form_value.Address(); + + // DWARF4 can specify the hi_pc as an <offset-from-lowpc> + return lo_pc + form_value.Unsigned(); } return fail_value; } @@ -1468,13 +1227,14 @@ DWARFDebugInfoEntry::GetAttributeAddressRange const DWARFCompileUnit* cu, dw_addr_t& lo_pc, dw_addr_t& hi_pc, - uint64_t fail_value + uint64_t fail_value, + bool check_specification_or_abstract_origin ) const { - lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, fail_value); + lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin); if (lo_pc != fail_value) { - hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value); + hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, check_specification_or_abstract_origin); if (hi_pc != fail_value) return true; } @@ -1484,89 +1244,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange } size_t -DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data, - const DWARFCompileUnit* cu, - DWARFDebugRanges::RangeList &ranges, - bool check_hi_lo_pc) const +DWARFDebugInfoEntry::GetAttributeAddressRanges (SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit* cu, + DWARFRangeList &ranges, + bool check_hi_lo_pc, + bool check_specification_or_abstract_origin) const { ranges.Clear(); - dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); - if (ranges_offset != DW_INVALID_OFFSET) + dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, + cu, + DW_AT_ranges, + DW_INVALID_OFFSET, + check_specification_or_abstract_origin); + if (debug_ranges_offset != DW_INVALID_OFFSET) { - dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); - if (debug_ranges_offset != DW_INVALID_OFFSET) - { - DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); - - debug_ranges->FindRanges(debug_ranges_offset, ranges); - ranges.Slide (cu->GetBaseAddress()); - } + DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); + + debug_ranges->FindRanges(debug_ranges_offset, ranges); + ranges.Slide (cu->GetBaseAddress()); } else if (check_hi_lo_pc) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) + if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, check_specification_or_abstract_origin)) { if (lo_pc < hi_pc) - ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc)); + ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); } } return ranges.GetSize(); } //---------------------------------------------------------------------- -// GetAttributeValueAsLocation -// -// Get the value of an attribute as reference and fix up and compile -// unit relative offsets as needed. -//---------------------------------------------------------------------- -dw_offset_t -DWARFDebugInfoEntry::GetAttributeValueAsLocation -( - SymbolFileDWARF* dwarf2Data, - const DWARFCompileUnit* cu, - const dw_attr_t attr, - DWARFDataExtractor& location_data, - uint32_t &block_size -) const -{ - block_size = 0; - DWARFFormValue form_value; - - // Empty out data in case we don't find anything - location_data.Clear(); - dw_offset_t end_addr_offset = DW_INVALID_OFFSET; - const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset); - if (attr_offset) - { - const uint8_t* blockData = form_value.BlockData(); - if (blockData) - { - // We have an inlined location list in the .debug_info section - const DWARFDataExtractor& debug_info = dwarf2Data->get_debug_info_data(); - dw_offset_t block_offset = blockData - debug_info.GetDataStart(); - block_size = (end_addr_offset - attr_offset) - form_value.Unsigned(); - location_data.SetData(debug_info, block_offset, block_size); - } - else - { - // We have a location list offset as the value that is - // the offset into the .debug_loc section that describes - // the value over it's lifetime - lldb::offset_t debug_loc_offset = form_value.Unsigned(); - if (dwarf2Data) - { - assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize()); - return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data); - } - } - } - return attr_offset; -} - -//---------------------------------------------------------------------- // GetName // // Get value of the DW_AT_name attribute and return it if one exists, @@ -1579,27 +1290,9 @@ DWARFDebugInfoEntry::GetName const DWARFCompileUnit* cu ) const { - DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) - return form_value.AsCString(&dwarf2Data->get_debug_str_data()); - else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) - { - DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); - if (die) - return die->GetName(dwarf2Data, cu_sp_ptr.get()); - } - else if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) - { - DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); - if (die) - return die->GetName(dwarf2Data, cu_sp_ptr.get()); - } - return nullptr; + return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); } - //---------------------------------------------------------------------- // GetMangledName // @@ -1614,20 +1307,20 @@ DWARFDebugInfoEntry::GetMangledName bool substitute_name_allowed ) const { - const char* name = NULL; - DWARFFormValue form_value; + const char* name = nullptr; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true); + if (name) + return name; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true); + if (name) + return name; - if (substitute_name_allowed && name == NULL) - { - if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); - } + if (!substitute_name_allowed) + return nullptr; + + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); return name; } @@ -1645,27 +1338,19 @@ DWARFDebugInfoEntry::GetPubname const DWARFCompileUnit* cu ) const { - const char* name = NULL; + const char* name = nullptr; if (!dwarf2Data) return name; - - DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); - else if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); - else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) - name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); - else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) - { - // The specification DIE may be in another compile unit so we need - // to get a die and its compile unit. - DWARFCompileUnitSP cu_sp_ptr; - const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); - if (die) - return die->GetPubname(dwarf2Data, cu_sp_ptr.get()); - } + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true); + if (name) + return name; + + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true); + if (name) + return name; + + name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); return name; } @@ -1705,15 +1390,11 @@ DWARFDebugInfoEntry::GetName } else { - DWARFFormValue form_value; - if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) + const char* name = die.GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); + if (name) { - const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); - if (name) - { - s.PutCString(name); - return true; - } + s.PutCString(name); + return true; } } } @@ -1755,8 +1436,6 @@ DWARFDebugInfoEntry::AppendTypeName else { const char* name = die.GetPubname(dwarf2Data, cu); - // if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) - // name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); if (name) s.PutCString(name); else @@ -1909,16 +1588,12 @@ DWARFDebugInfoEntry::BuildFunctionAddressRangeTable } void -DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data, - DWARFCompileUnit* cu, +DWARFDebugInfoEntry::GetDeclContextDIEs (DWARFCompileUnit* cu, DWARFDIECollection &decl_context_dies) const { - const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); - if (parent_decl_ctx_die && parent_decl_ctx_die != this) - { - decl_context_dies.Append(parent_decl_ctx_die); - parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies); - } + + DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this)); + die.GetDeclContextDIEs(decl_context_dies); } void @@ -1930,11 +1605,11 @@ DWARFDebugInfoEntry::GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data, if (tag != DW_TAG_compile_unit) { dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu)); - const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); - if (parent_decl_ctx_die && parent_decl_ctx_die != this) + DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); + if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) { - if (parent_decl_ctx_die->Tag() != DW_TAG_compile_unit) - parent_decl_ctx_die->GetDWARFDeclContext (dwarf2Data, cu, dwarf_decl_ctx); + if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit) + parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext (parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), dwarf_decl_ctx); } } } @@ -1951,30 +1626,30 @@ DWARFDebugInfoEntry::MatchesDWARFDeclContext (SymbolFileDWARF* dwarf2Data, return this_dwarf_decl_ctx == dwarf_decl_ctx; } -const DWARFDebugInfoEntry * +DWARFDIE DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu) const { - DWARFDebugInfoEntry::Attributes attributes; - GetAttributes(dwarf2Data, cu, NULL, attributes); + DWARFAttributes attributes; + GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); return GetParentDeclContextDIE (dwarf2Data, cu, attributes); } -const DWARFDebugInfoEntry * +DWARFDIE DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, - const DWARFDebugInfoEntry::Attributes& attributes) const + const DWARFAttributes& attributes) const { - const DWARFDebugInfoEntry * die = this; - - while (die != NULL) + DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this)); + + while (die) { // If this is the original DIE that we are searching for a declaration // for, then don't look in the cache as we don't want our own decl // context to be our decl context... - if (die != this) + if (die.GetDIE() != this) { - switch (die->Tag()) + switch (die.Tag()) { case DW_TAG_compile_unit: case DW_TAG_namespace: @@ -1990,33 +1665,33 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, dw_offset_t die_offset; - die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_specification, DW_INVALID_OFFSET); + die_offset = attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET); if (die_offset != DW_INVALID_OFFSET) { - const DWARFDebugInfoEntry *spec_die = cu->GetDIEPtr (die_offset); + DWARFDIE spec_die = cu->GetDIE (die_offset); if (spec_die) - { - const DWARFDebugInfoEntry *spec_die_decl_ctx_die = spec_die->GetParentDeclContextDIE (dwarf2Data, cu); - if (spec_die_decl_ctx_die) - return spec_die_decl_ctx_die; - } + { + DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); + if (decl_ctx_die) + return decl_ctx_die; + } } - die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_abstract_origin, DW_INVALID_OFFSET); + die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, DW_INVALID_OFFSET); if (die_offset != DW_INVALID_OFFSET) { - const DWARFDebugInfoEntry *abs_die = cu->GetDIEPtr (die_offset); + DWARFDIE abs_die = cu->GetDIE (die_offset); if (abs_die) { - const DWARFDebugInfoEntry *abs_die_decl_ctx_die = abs_die->GetParentDeclContextDIE (dwarf2Data, cu); - if (abs_die_decl_ctx_die) - return abs_die_decl_ctx_die; + DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); + if (decl_ctx_die) + return decl_ctx_die; } } - die = die->GetParent(); + die = die.GetParent(); } - return NULL; + return DWARFDIE(); } @@ -2025,15 +1700,15 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, std::string &storage) const { - DWARFDebugInfoEntry::Attributes attributes; - GetAttributes(dwarf2Data, cu, NULL, attributes); + DWARFAttributes attributes; + GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); return GetQualifiedName (dwarf2Data, cu, attributes, storage); } const char* DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, - const DWARFDebugInfoEntry::Attributes& attributes, + const DWARFAttributes& attributes, std::string &storage) const { @@ -2041,47 +1716,47 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data, if (name) { - const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); + DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); storage.clear(); // TODO: change this to get the correct decl context parent.... while (parent_decl_ctx_die) { - const dw_tag_t parent_tag = parent_decl_ctx_die->Tag(); + const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); switch (parent_tag) { case DW_TAG_namespace: - { - const char *namespace_name = parent_decl_ctx_die->GetName (dwarf2Data, cu); - if (namespace_name) - { - storage.insert (0, "::"); - storage.insert (0, namespace_name); - } - else - { - storage.insert (0, "(anonymous namespace)::"); - } - parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu); - } + { + const char *namespace_name = parent_decl_ctx_die.GetName (); + if (namespace_name) + { + storage.insert (0, "::"); + storage.insert (0, namespace_name); + } + else + { + storage.insert (0, "(anonymous namespace)::"); + } + parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); + } break; case DW_TAG_class_type: case DW_TAG_structure_type: case DW_TAG_union_type: - { - const char *class_union_struct_name = parent_decl_ctx_die->GetName (dwarf2Data, cu); - - if (class_union_struct_name) - { - storage.insert (0, "::"); - storage.insert (0, class_union_struct_name); - } - parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu); - } + { + const char *class_union_struct_name = parent_decl_ctx_die.GetName (); + + if (class_union_struct_name) + { + storage.insert (0, "::"); + storage.insert (0, class_union_struct_name); + } + parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); + } break; default: - parent_decl_ctx_die = NULL; + parent_decl_ctx_die.Clear(); break; } } @@ -2179,7 +1854,7 @@ DWARFDebugInfoEntry::LookupAddress if (match_addr_range) { - dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); + dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (lo_pc != LLDB_INVALID_ADDRESS) { dw_addr_t hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS); @@ -2229,7 +1904,7 @@ DWARFDebugInfoEntry::LookupAddress dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); if (debug_ranges_offset != DW_INVALID_OFFSET) { - DWARFDebugRanges::RangeList ranges; + DWARFRangeList ranges; DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); debug_ranges->FindRanges(debug_ranges_offset, ranges); // All DW_AT_ranges are relative to the base address of the diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 3949ad339dd8..02bbff8defc0 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -57,56 +57,6 @@ public: typedef offset_collection::iterator offset_collection_iterator; typedef offset_collection::const_iterator offset_collection_const_iterator; - class Attributes - { - public: - Attributes(); - ~Attributes(); - - void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form); - const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; } - dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; } - dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; } - dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; } - bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const; - uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const; - uint64_t FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const; - uint32_t FindAttributeIndex(dw_attr_t attr) const; - bool ContainsAttribute(dw_attr_t attr) const; - bool RemoveAttribute(dw_attr_t attr); - void Clear() { m_infos.clear(); } - size_t Size() const { return m_infos.size(); } - - protected: - struct Info - { - const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values - dw_offset_t die_offset; - dw_attr_t attr; - dw_form_t form; - }; - - typedef llvm::SmallVector<Info, 8> collection; - collection m_infos; - }; - - struct CompareState - { - CompareState() : - die_offset_pairs() - { - assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t)); - } - - bool AddTypePair(dw_offset_t a, dw_offset_t b) - { - uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b; - // Return true if this type was inserted, false otherwise - return die_offset_pairs.insert(a_b_offsets).second; - } - std::set< uint64_t > die_offset_pairs; - }; - DWARFDebugInfoEntry(): m_offset (DW_INVALID_OFFSET), m_parent_idx (0), @@ -144,7 +94,7 @@ public: bool FastExtract( const lldb_private::DWARFDataExtractor& debug_info_data, const DWARFCompileUnit* cu, - const uint8_t *fixed_form_sizes, + const DWARFFormValue::FixedFormSizes& fixed_form_sizes, lldb::offset_t* offset_ptr); bool Extract( @@ -160,68 +110,67 @@ public: DWARFDebugInfoEntry** block_die); size_t GetAttributes( - SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, - const uint8_t *fixed_form_sizes, - DWARFDebugInfoEntry::Attributes& attrs, + DWARFFormValue::FixedFormSizes fixed_form_sizes, + DWARFAttributes& attrs, uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!! - dw_offset_t GetAttributeValue( - SymbolFileDWARF* dwarf2Data, - const DWARFCompileUnit* cu, - const dw_attr_t attr, - DWARFFormValue& formValue, - dw_offset_t* end_attr_offset_ptr = NULL) const; - const char* GetAttributeValueAsString( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - const char* fail_value) const; + const char* fail_value, + bool check_specification_or_abstract_origin = false) const; uint64_t GetAttributeValueAsUnsigned( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - uint64_t fail_value) const; + uint64_t fail_value, + bool check_specification_or_abstract_origin = false) const; uint64_t GetAttributeValueAsReference( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - uint64_t fail_value) const; + uint64_t fail_value, + bool check_specification_or_abstract_origin = false) const; int64_t GetAttributeValueAsSigned( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, const dw_attr_t attr, - int64_t fail_value) const; + int64_t fail_value, + bool check_specification_or_abstract_origin = false) const; + + uint64_t GetAttributeValueAsAddress( + SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit* cu, + const dw_attr_t attr, + uint64_t fail_value, + bool check_specification_or_abstract_origin = false) const; dw_addr_t GetAttributeHighPC( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, dw_addr_t lo_pc, - uint64_t fail_value) const; + uint64_t fail_value, + bool check_specification_or_abstract_origin = false) const; bool GetAttributeAddressRange( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, dw_addr_t& lo_pc, dw_addr_t& hi_pc, - uint64_t fail_value) const; + uint64_t fail_value, + bool check_specification_or_abstract_origin = false) const; size_t GetAttributeAddressRanges ( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, - DWARFDebugRanges::RangeList &ranges, - bool check_hi_lo_pc) const; - - dw_offset_t GetAttributeValueAsLocation( - SymbolFileDWARF* dwarf2Data, - const DWARFCompileUnit* cu, - const dw_attr_t attr, - lldb_private::DWARFDataExtractor& data, - uint32_t &block_size) const; + DWARFRangeList &ranges, + bool check_hi_lo_pc, + bool check_specification_or_abstract_origin = false) const; const char* GetName( SymbolFileDWARF* dwarf2Data, @@ -256,25 +205,9 @@ public: const char * GetQualifiedName ( SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, - const DWARFDebugInfoEntry::Attributes& attributes, + const DWARFAttributes& attributes, std::string &storage) const; -// static int Compare( -// SymbolFileDWARF* dwarf2Data, -// dw_offset_t a_die_offset, -// dw_offset_t b_die_offset, -// CompareState &compare_state, -// bool compare_siblings, -// bool compare_children); -// -// static int Compare( -// SymbolFileDWARF* dwarf2Data, -// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, -// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, -// CompareState &compare_state, -// bool compare_siblings, -// bool compare_children); - static bool OffsetLessThan ( const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b); @@ -311,7 +244,7 @@ public: const DWARFCompileUnit* cu, const char * &name, const char * &mangled, - DWARFDebugRanges::RangeList& rangeList, + DWARFRangeList& rangeList, int& decl_file, int& decl_line, int& decl_column, @@ -376,8 +309,7 @@ public: const DWARFDebugInfoEntry* GetFirstChild() const { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; } - void GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data, - DWARFCompileUnit* cu, + void GetDeclContextDIEs (DWARFCompileUnit* cu, DWARFDIECollection &decl_context_dies) const; void GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data, @@ -389,11 +321,11 @@ public: DWARFCompileUnit* cu, const DWARFDeclContext &dwarf_decl_ctx) const; - const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, + DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu) const; - const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, + DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, DWARFCompileUnit* cu, - const DWARFDebugInfoEntry::Attributes& attributes) const; + const DWARFAttributes& attributes) const; void SetParent (DWARFDebugInfoEntry* parent) @@ -450,6 +382,13 @@ public: DWARFDebugInfoEntry::collection &die_collection); protected: + dw_offset_t GetAttributeValue(SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit* cu, + const dw_attr_t attr, + DWARFFormValue& formValue, + dw_offset_t* end_attr_offset_ptr = nullptr, + bool check_specification_or_abstract_origin = false) const; + dw_offset_t m_offset; // Offset within the .debug_info of the start of this entry uint32_t m_parent_idx; // How many to subtract from "this" to get the parent. If zero this die has no parent uint32_t m_sibling_idx:31, // How many to add to "this" to get the sibling. @@ -457,7 +396,6 @@ protected: uint32_t m_abbr_idx:DIE_ABBR_IDX_BITSIZE, m_has_children:1, // Set to 1 if this DIE has children m_tag:16; // A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table - }; #endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index 48e11bd80089..84c2142e8419 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -249,7 +249,7 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_l fileEntry.length = debug_line_data.GetULEB128(&offset); log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )", op_offset, - fileEntry.name.c_str(), + fileEntry.name, fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length); @@ -486,65 +486,25 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp, FileSpecList &support_files) { lldb::offset_t offset = stmt_list; - // Skip the total length - (void)debug_line_data.GetDWARFInitialLength(&offset); - uint32_t version = debug_line_data.GetU16(&offset); - if (version < 2 || version > 4) - return false; - const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset; - // Skip instruction length, default is stmt, line base, line range - offset += 4; - // For DWARF4, skip maximum operations per instruction - if (version >= 4) - offset += 1; - // Skip opcode base, and all opcode lengths - const uint8_t opcode_base = debug_line_data.GetU8(&offset); - offset += opcode_base - 1; - std::vector<FileSpec> include_directories{{}}; // Directory at index zero doesn't exist - while (offset < end_prologue_offset) + Prologue prologue; + if (!ParsePrologue(debug_line_data, &offset, &prologue)) { - FileSpec dir{debug_line_data.GetCStr(&offset), false}; - if (dir) - include_directories.emplace_back(std::move(dir)); - else - break; + Host::SystemLog (Host::eSystemLogError, "error: parsing line table prologue at 0x%8.8x (parsing ended around 0x%8.8" PRIx64 "\n", stmt_list, offset); + return false; } - while (offset < end_prologue_offset) - { - FileSpec file_spec{debug_line_data.GetCStr(&offset), false}; - if (file_spec) - { - uint32_t dir_idx = debug_line_data.GetULEB128(&offset); - debug_line_data.Skip_LEB128(&offset); // Skip mod_time - debug_line_data.Skip_LEB128(&offset); // Skip length - if (file_spec.IsRelative()) - { - if (0 < dir_idx && dir_idx < include_directories.size()) - { - const FileSpec &dir = include_directories[dir_idx]; - file_spec.PrependPathComponent(dir); - } - if (file_spec.IsRelative()) - file_spec.PrependPathComponent(cu_comp_dir); - } - std::string remapped_file; - if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file)) - file_spec.SetFile(remapped_file, false); - support_files.Append(file_spec); - } - } + FileSpec file_spec; + std::string remapped_file; - if (offset != end_prologue_offset) + for (uint32_t file_idx = 1; prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) { - Host::SystemLog (Host::eSystemLogError, - "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended at 0x%8.8" PRIx64 "\n", - stmt_list, - end_prologue_offset, - offset); + if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file)) + file_spec.SetFile(remapped_file, false); + support_files.Append(file_spec); + } - return end_prologue_offset; + return true; } //---------------------------------------------------------------------- @@ -900,7 +860,7 @@ DWARFDebugLine::Prologue::Dump(Log *log) { for (i=0; i<include_directories.size(); ++i) { - log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str()); + log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i]); } } @@ -916,7 +876,7 @@ DWARFDebugLine::Prologue::Dump(Log *log) fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length, - fileEntry.name.c_str()); + fileEntry.name); } } } @@ -959,17 +919,28 @@ DWARFDebugLine::Prologue::Dump(Log *log) //} -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const +bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir, FileSpec &file) const { uint32_t idx = file_idx - 1; // File indexes are 1 based... if (idx < file_names.size()) { - path = file_names[idx].name; - uint32_t dir_idx = file_names[idx].dir_idx - 1; - if (dir_idx < include_directories.size()) - directory = include_directories[dir_idx]; - else - directory.clear(); + file.SetFile(file_names[idx].name, false); + if (file.IsRelative()) + { + if (file_names[idx].dir_idx > 0) + { + const uint32_t dir_idx = file_names[idx].dir_idx - 1; + if (dir_idx < include_directories.size()) + { + file.PrependPathComponent(include_directories[dir_idx]); + if (!file.IsRelative()) + return true; + } + } + + if (comp_dir && comp_dir[0]) + file.PrependPathComponent(comp_dir); + } return true; } return false; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h index 7da0e76a22be..9f2219b01812 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h @@ -20,7 +20,6 @@ #include "DWARFDefines.h" class SymbolFileDWARF; -class DWARFDebugInfoEntry; //---------------------------------------------------------------------- // DWARFDebugLine @@ -34,14 +33,14 @@ public: struct FileNameEntry { FileNameEntry() : - name(), + name(nullptr), dir_idx(0), mod_time(0), length(0) { } - std::string name; + const char* name; dw_sleb128_t dir_idx; dw_sleb128_t mod_time; dw_sleb128_t length; @@ -81,7 +80,7 @@ public: uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below. uint8_t opcode_base; // The number assigned to the first special opcode. std::vector<uint8_t> standard_opcode_lengths; - std::vector<std::string> include_directories; + std::vector<const char *> include_directories; std::vector<FileNameEntry> file_names; int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; } @@ -96,7 +95,7 @@ public: include_directories.clear(); file_names.clear(); } - bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const; + bool GetFile(uint32_t file_idx, const char *comp_dir, lldb_private::FileSpec &file) const; }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp new file mode 100644 index 000000000000..75c812e6e79d --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -0,0 +1,128 @@ +//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugMacro.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Symbol/DebugMacros.h" + +#include "DWARFDataExtractor.h" + +using namespace lldb_private; + +DWARFDebugMacroHeader +DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) +{ + DWARFDebugMacroHeader header; + + // Skip over the version field in header. + header.m_version = debug_macro_data.GetU16(offset); + + uint8_t flags = debug_macro_data.GetU8(offset); + header.m_offset_is_64_bit = flags & OFFSET_SIZE_MASK ? true : false; + + if (flags & DEBUG_LINE_OFFSET_MASK) + { + if (header.m_offset_is_64_bit) + header.m_debug_line_offset = debug_macro_data.GetU64(offset); + else + header.m_debug_line_offset = debug_macro_data.GetU32(offset); + } + + // Skip over the operands table if it is present. + if (flags & OPCODE_OPERANDS_TABLE_MASK) + SkipOperandTable(debug_macro_data, offset); + + return header; +} + +void +DWARFDebugMacroHeader::SkipOperandTable(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) +{ + uint8_t entry_count = debug_macro_data.GetU8(offset); + for (uint8_t i = 0; i < entry_count; i++) + { + // Skip over the opcode number. + debug_macro_data.GetU8(offset); + + uint64_t operand_count = debug_macro_data.GetULEB128(offset); + + for (uint64_t j = 0; j < operand_count; j++) + { + // Skip over the operand form + debug_macro_data.GetU8(offset); + } + } +} + +void +DWARFDebugMacroEntry::ReadMacroEntries(const DWARFDataExtractor &debug_macro_data, + const DWARFDataExtractor &debug_str_data, + const bool offset_is_64_bit, + lldb::offset_t *offset, + SymbolFileDWARF *sym_file_dwarf, + DebugMacrosSP &debug_macros_sp) +{ + llvm::dwarf::MacroEntryType type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset)); + while (type != 0) + { + lldb::offset_t new_offset = 0, str_offset = 0; + uint32_t line = 0; + const char *macro_str = nullptr; + uint32_t debug_line_file_idx = 0; + + switch (type) + { + case DW_MACRO_define: + case DW_MACRO_undef: + line = debug_macro_data.GetULEB128(offset); + macro_str = debug_macro_data.GetCStr(offset); + if (type == DW_MACRO_define) + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str)); + break; + case DW_MACRO_define_indirect: + case DW_MACRO_undef_indirect: + line = debug_macro_data.GetULEB128(offset); + if (offset_is_64_bit) + str_offset = debug_macro_data.GetU64(offset); + else + str_offset = debug_macro_data.GetU32(offset); + macro_str = debug_str_data.GetCStr(&str_offset); + if (type == DW_MACRO_define_indirect) + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str)); + break; + case DW_MACRO_start_file: + line = debug_macro_data.GetULEB128(offset); + debug_line_file_idx = debug_macro_data.GetULEB128(offset); + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx)); + break; + case DW_MACRO_end_file: + // This operation has no operands. + debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry()); + break; + case DW_MACRO_transparent_include: + if (offset_is_64_bit) + new_offset = debug_macro_data.GetU64(offset); + else + new_offset = debug_macro_data.GetU32(offset); + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::CreateIndirectEntry(sym_file_dwarf->ParseDebugMacros(&new_offset))); + break; + default: + // TODO: Add support for other standard operations. + // TODO: Provide mechanism to hook handling of non-standard/extension operands. + return; + } + type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset)); + } +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h new file mode 100644 index 000000000000..c60b9749b005 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -0,0 +1,68 @@ +//===-- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFDebugMacro_h_ +#define SymbolFileDWARF_DWARFDebugMacro_h_ + +#include <map> + +#include "lldb/lldb-types.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Symbol/DebugMacros.h" + +namespace lldb_private +{ + +class DWARFDataExtractor; + +} // namespace lldb_private + +class SymbolFileDWARF; + +class DWARFDebugMacroHeader +{ +public: + enum HeaderFlagMask + { + OFFSET_SIZE_MASK = 0x1, + DEBUG_LINE_OFFSET_MASK = 0x2, + OPCODE_OPERANDS_TABLE_MASK = 0x4 + }; + + static DWARFDebugMacroHeader + ParseHeader(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); + + bool + OffsetIs64Bit() const + { + return m_offset_is_64_bit; + } + +private: + static void + SkipOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); + + uint16_t m_version; + bool m_offset_is_64_bit; + uint64_t m_debug_line_offset; +}; + +class DWARFDebugMacroEntry +{ +public: + static void + ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, + const lldb_private::DWARFDataExtractor &debug_str_data, + const bool offset_is_64_bit, + lldb::offset_t *sect_offset, + SymbolFileDWARF *sym_file_dwarf, + lldb_private::DebugMacrosSP &debug_macros_sp); +}; + +#endif // SymbolFileDWARF_DWARFDebugMacro_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp index 8469b78d0dd5..547bd0cd1a5a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp @@ -77,9 +77,6 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); if (debug_info) { - - const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data(); - uint32_t cu_idx = 0; const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) @@ -87,7 +84,9 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64()); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), + cu->IsDWARF64()); bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; @@ -101,17 +100,17 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) size_t die_idx; for (die_idx = 0; die_idx < die_count; ++die_idx) { - const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); - DWARFDebugInfoEntry::Attributes attributes; + DWARFDIE die = dies.GetDIEAtIndex(die_idx); + DWARFAttributes attributes; const char *name = NULL; const char *mangled = NULL; bool add_die = false; - const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); + const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes); if (num_attributes > 0) { uint32_t i; - dw_tag_t tag = die->Tag(); + dw_tag_t tag = die.Tag(); for (i=0; i<num_attributes; ++i) { @@ -120,14 +119,14 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) switch (attr) { case DW_AT_name: - if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) - name = form_value.AsCString(debug_str); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + name = form_value.AsCString(); break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: - if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) - mangled = form_value.AsCString(debug_str); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + mangled = form_value.AsCString(); break; case DW_AT_low_pc: @@ -140,10 +139,10 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) case DW_AT_location: if (tag == DW_TAG_variable) { - const DWARFDebugInfoEntry* parent_die = die->GetParent(); - while ( parent_die != NULL ) + DWARFDIE parent_die = die.GetParent(); + while ( parent_die ) { - switch (parent_die->Tag()) + switch (parent_die.Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: @@ -153,31 +152,16 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) // if the location describes a hard coded address, but we don't want the performance // penalty of that right now. add_die = false; -// if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) -// { -// // If we have valid block data, then we have location expression bytes -// // that are fixed (not a location list). -// const uint8_t *block_data = form_value.BlockData(); -// if (block_data) -// { -// uint32_t block_length = form_value.Unsigned(); -// if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) -// { -// if (block_data[0] == DW_OP_addr) -// add_die = true; -// } -// } -// } - parent_die = NULL; // Terminate the while loop. + parent_die.Clear(); // Terminate the while loop. break; case DW_TAG_compile_unit: add_die = true; - parent_die = NULL; // Terminate the while loop. + parent_die.Clear(); // Terminate the while loop. break; default: - parent_die = parent_die->GetParent(); // Keep going in the while loop. + parent_die = parent_die.GetParent(); // Keep going in the while loop. break; } } @@ -189,7 +173,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) if (add_die && (name || mangled)) { - pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name); + pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name); } } @@ -231,13 +215,11 @@ DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data) size_t die_idx; for (die_idx = 0; die_idx < die_count; ++die_idx) { - const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); - const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL); + DWARFDIE die = dies.GetDIEAtIndex (die_idx); + const char *name = die.GetName(); if (name) - { - pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name); - } + pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name); } if (pubnames_set.NumDescriptors() > 0) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 0953554ffd7d..fc2831f22438 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -27,7 +27,7 @@ DWARFDebugRanges::~DWARFDebugRanges() void DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data) { - RangeList range_list; + DWARFRangeList range_list; lldb::offset_t offset = 0; dw_offset_t debug_ranges_offset = offset; while (Extract(dwarf2Data, &offset, range_list)) @@ -38,52 +38,8 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data) } } -//void -//DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset) -//{ -// if (!ranges.empty()) -// { -// Range::iterator pos = ranges.begin(); -// Range::iterator end_pos = ranges.end(); -// for (pos = ranges.begin(); pos != end_pos; ++pos) -// { -// // assert for unsigned overflows -// assert (~pos->begin_offset >= offset); -// assert (~pos->end_offset >= offset); -// pos->begin_offset += offset; -// pos->end_offset += offset; -// } -// } -//} -// -//void -//DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset) -//{ -// if (!ranges.empty()) -// { -// Range::iterator pos = ranges.begin(); -// Range::iterator end_pos = ranges.end(); -// for (pos = ranges.begin(); pos != end_pos; ++pos) -// { -// assert (pos->begin_offset >= offset); -// assert (pos->end_offset >= offset); -// pos->begin_offset -= offset; -// pos->end_offset -= offset; -// } -// } -//} -// -// -//const DWARFDebugRanges::Range* -//DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const -//{ -// if (i < ranges.size()) -// return &ranges[i]; -// return NULL; -//} - bool -DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list) +DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, DWARFRangeList &range_list) { range_list.Clear(); @@ -118,13 +74,13 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt break; default: - assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size."); + assert(!"DWARFRangeList::Extract() unsupported address size."); break; } // Filter out empty ranges if (begin < end) - range_list.Append(Range(begin, end - begin)); + range_list.Append(DWARFRangeList::Entry(begin, end - begin)); } // Make sure we consumed at least something @@ -178,7 +134,7 @@ DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, l } bool -DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const +DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const { range_map_const_iterator pos = m_range_map.find(debug_ranges_offset); if (pos != m_range_map.end()) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index 50af91d41009..3ff4ea3502c9 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -11,34 +11,30 @@ #define SymbolFileDWARF_DWARFDebugRanges_h_ #include "SymbolFileDWARF.h" +#include "DWARFDIE.h" #include <map> -#include <vector> - -#include "lldb/Core/RangeMap.h" class DWARFDebugRanges { public: - typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> RangeList; - typedef RangeList::Entry Range; DWARFDebugRanges(); ~DWARFDebugRanges(); void Extract(SymbolFileDWARF* dwarf2Data); static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr); - bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const; + bool FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const; protected: bool Extract (SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, - RangeList &range_list); + DWARFRangeList &range_list); - typedef std::map<dw_offset_t, RangeList> range_map; - typedef range_map::iterator range_map_iterator; - typedef range_map::const_iterator range_map_const_iterator; + typedef std::map<dw_offset_t, DWARFRangeList> range_map; + typedef range_map::iterator range_map_iterator; + typedef range_map::const_iterator range_map_const_iterator; range_map m_range_map; }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 3a99d2b33878..4c29447b47bb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -108,6 +108,13 @@ public: return lldb_private::ConstString (GetQualifiedName ()); } + void + Clear() + { + m_entries.clear(); + m_qualified_name.clear(); + } + protected: typedef std::vector<Entry> collection; collection m_entries; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index c733832e4f4d..a0ed9731a565 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -136,21 +136,21 @@ g_form_sizes_addr8_dwarf64[] = 8, // 0x20 DW_FORM_ref_sig8 }; -const uint8_t * +DWARFFormValue::FixedFormSizes DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64) { if (!is_dwarf64) { switch (addr_size) { - case 4: return g_form_sizes_addr4; - case 8: return g_form_sizes_addr8; + case 4: return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4)); + case 8: return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8)); } } else { if (addr_size == 8) - return g_form_sizes_addr8_dwarf64; + return FixedFormSizes(g_form_sizes_addr8_dwarf64, sizeof(g_form_sizes_addr8_dwarf64)); // is_dwarf64 && addr_size == 4 : no provider does this. } - return NULL; + return FixedFormSizes(); } DWARFFormValue::DWARFFormValue() : @@ -187,11 +187,7 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break; case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break; case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break; - case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); - // Set the string value to also be the data for inlined cstr form values only - // so we can tell the difference between DW_FORM_string and DW_FORM_strp form - // values; - m_value.data = (const uint8_t*)m_value.value.cstr; break; + case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); break; case DW_FORM_exprloc: case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break; case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break; @@ -219,10 +215,12 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off indirect = true; break; - case DW_FORM_sec_offset: assert(m_cu); - m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break; - case DW_FORM_flag_present: m_value.value.uval = 1; break; - case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break; + case DW_FORM_sec_offset: assert(m_cu); + m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break; + case DW_FORM_flag_present: m_value.value.uval = 1; break; + case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break; + case DW_FORM_GNU_str_index: m_value.value.uval = data.GetULEB128(offset_ptr); break; + case DW_FORM_GNU_addr_index: m_value.value.uval = data.GetULEB128(offset_ptr); break; default: return false; break; @@ -322,6 +320,8 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index: debug_info_data.Skip_LEB128(offset_ptr); return true; @@ -342,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d void -DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const +DWARFFormValue::Dump(Stream &s) const { uint64_t uvalue = Unsigned(); bool cu_relative_offset = false; @@ -353,13 +353,13 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const { case DW_FORM_addr: s.Address(uvalue, sizeof (uint64_t)); break; case DW_FORM_flag: - case DW_FORM_data1: s.PutHex8(uvalue); break; + case DW_FORM_data1: s.PutHex8(uvalue); break; case DW_FORM_data2: s.PutHex16(uvalue); break; case DW_FORM_sec_offset: case DW_FORM_data4: s.PutHex32(uvalue); break; case DW_FORM_ref_sig8: case DW_FORM_data8: s.PutHex64(uvalue); break; - case DW_FORM_string: s.QuotedCString(AsCString(NULL)); break; + case DW_FORM_string: s.QuotedCString(AsCString()); break; case DW_FORM_exprloc: case DW_FORM_block: case DW_FORM_block1: @@ -395,18 +395,18 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const case DW_FORM_sdata: s.PutSLEB128(uvalue); break; case DW_FORM_udata: s.PutULEB128(uvalue); break; case DW_FORM_strp: - if (debug_str_data) { - if (verbose) - s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); - - const char* dbg_str = AsCString(debug_str_data); + const char* dbg_str = AsCString(); if (dbg_str) + { + if (verbose) + s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); s.QuotedCString(dbg_str); - } - else - { - s.PutHex32(uvalue); + } + else + { + s.PutHex32(uvalue); + } } break; @@ -444,13 +444,52 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const } const char* -DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const +DWARFFormValue::AsCString() const { - if (IsInlinedCStr()) + SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF(); + + if (m_form == DW_FORM_string) + { return m_value.value.cstr; - else if (debug_str_data_ptr) - return debug_str_data_ptr->PeekCStr(m_value.value.uval); - return NULL; + } + else if (m_form == DW_FORM_strp) + { + if (!symbol_file) + return nullptr; + + return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval); + } + else if (m_form == DW_FORM_GNU_str_index) + { + if (!symbol_file) + return nullptr; + + uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4; + lldb::offset_t offset = m_value.value.uval * index_size; + dw_offset_t str_offset = symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, index_size); + return symbol_file->get_debug_str_data().PeekCStr(str_offset); + } + return nullptr; +} + +dw_addr_t +DWARFFormValue::Address() const +{ + SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF(); + + if (m_form == DW_FORM_addr) + return Unsigned(); + + assert(m_cu); + assert(m_form == DW_FORM_GNU_addr_index); + + if (!symbol_file) + return 0; + + uint32_t index_size = m_cu->GetAddressByteSize(); + dw_offset_t addr_base = m_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + m_value.value.uval * index_size; + return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size); } uint64_t @@ -500,9 +539,7 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const const uint8_t* DWARFFormValue::BlockData() const { - if (!IsInlinedCStr()) - return m_value.data; - return NULL; + return m_value.data; } @@ -537,7 +574,8 @@ DWARFFormValue::IsDataForm(const dw_form_t form) } int -DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr) +DWARFFormValue::Compare (const DWARFFormValue& a_value, + const DWARFFormValue& b_value) { dw_form_t a_form = a_value.Form(); dw_form_t b_form = b_value.Form(); @@ -558,6 +596,7 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_ case DW_FORM_sec_offset: case DW_FORM_flag_present: case DW_FORM_ref_sig8: + case DW_FORM_GNU_addr_index: { uint64_t a = a_value.Unsigned(); uint64_t b = b_value.Unsigned(); @@ -581,9 +620,10 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_ case DW_FORM_string: case DW_FORM_strp: + case DW_FORM_GNU_str_index: { - const char *a_string = a_value.AsCString(debug_str_data_ptr); - const char *b_string = b_value.AsCString(debug_str_data_ptr); + const char *a_string = a_value.AsCString(); + const char *b_string = b_value.AsCString(); if (a_string == b_string) return 0; else if (a_string && b_string) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 392df26a088e..b10f4d3a0ac9 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -35,6 +35,34 @@ public: } value; const uint8_t* data; } ValueType; + + class FixedFormSizes + { + public: + FixedFormSizes() : + m_fix_sizes(nullptr), m_size(0) + {} + + FixedFormSizes(const uint8_t* fix_sizes, size_t size) : + m_fix_sizes(fix_sizes), m_size(size) + {} + + uint8_t + GetSize(uint32_t index) const + { + return index < m_size ? m_fix_sizes[index] : 0; + } + + bool + Empty() const + { + return m_size == 0; + } + + private: + const uint8_t* m_fix_sizes; + size_t m_size; + }; enum { @@ -52,10 +80,9 @@ public: dw_form_t Form() const { return m_form; } void SetForm(dw_form_t form) { m_form = form; } const ValueType& Value() const { return m_value; } - void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const; + void Dump(lldb_private::Stream &s) const; bool ExtractValue(const lldb_private::DWARFDataExtractor& data, lldb::offset_t* offset_ptr); - bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; } const uint8_t* BlockData() const; uint64_t Reference() const; uint64_t Reference (dw_offset_t offset) const; @@ -64,13 +91,16 @@ public: void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; } int64_t Signed() const { return m_value.value.sval; } void SetSigned(int64_t sval) { m_value.value.sval = sval; } - const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const; + const char* AsCString() const; + dw_addr_t Address() const; + bool IsValid() const { return m_form != 0; } bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const; static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu); static bool IsBlockForm(const dw_form_t form); static bool IsDataForm(const dw_form_t form); - static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); - static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr); + static FixedFormSizes GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); + static int Compare (const DWARFFormValue& a, + const DWARFFormValue& b); protected: const DWARFCompileUnit* m_cu; // Compile unit for this form dw_form_t m_form; // Form for this value diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp deleted file mode 100644 index d79ae79822b0..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFLocationDescription.h" -#include "DWARFDefines.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/Stream.h" - - -using namespace lldb_private; - -static int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size); - -int -print_dwarf_expression (Stream &s, - const DWARFDataExtractor& data, - int address_size, - int dwarf_ref_size, - bool location_expression) -{ - int op_count = 0; - lldb::offset_t offset = 0; - while (data.ValidOffset(offset)) - { - if (location_expression && op_count > 0) - { - // err (baton, "Dwarf location expressions may only have one operand!"); - return 1; - } - if (op_count > 0) - { - s.PutCString(", "); - } - if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1) - return 1; - op_count++; - } - - return 0; -} - -static int -print_dwarf_exp_op (Stream &s, - const DWARFDataExtractor& data, - lldb::offset_t *offset_ptr, - int address_size, - int dwarf_ref_size) -{ - uint8_t opcode = data.GetU8(offset_ptr); - DRC_class opcode_class; - uint64_t uint; - int64_t sint; - - int size; - - opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); - - s.Printf("%s ", DW_OP_value_to_name (opcode)); - - /* Does this take zero parameters? If so we can shortcut this function. */ - if (opcode_class == DRC_ZEROOPERANDS) - return 0; - - if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) - { - uint = data.GetULEB128(offset_ptr); - sint = data.GetSLEB128(offset_ptr); - s.Printf("%" PRIu64 " %" PRIi64, uint, sint); - return 0; - } - if (opcode_class != DRC_ONEOPERAND) - { - s.Printf("UNKNOWN OP %u", opcode); - return 1; - } - - switch (opcode) - { - case DW_OP_addr: size = address_size; break; - case DW_OP_const1u: size = 1; break; - case DW_OP_const1s: size = -1; break; - case DW_OP_const2u: size = 2; break; - case DW_OP_const2s: size = -2; break; - case DW_OP_const4u: size = 4; break; - case DW_OP_const4s: size = -4; break; - case DW_OP_const8u: size = 8; break; - case DW_OP_const8s: size = -8; break; - case DW_OP_constu: size = 128; break; - case DW_OP_consts: size = -128; break; - case DW_OP_fbreg: size = -128; break; - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - size = -128; break; - case DW_OP_pick: - size = 1; break; - case DW_OP_deref_size: - size = 1; break; - case DW_OP_xderef_size: - size = 1; break; - case DW_OP_plus_uconst: - size = 128; break; - case DW_OP_skip: - size = -2; break; - case DW_OP_bra: - size = -2; break; - case DW_OP_call2: - size = 2; break; - case DW_OP_call4: - size = 4; break; - case DW_OP_call_ref: - size = dwarf_ref_size; break; - case DW_OP_piece: - size = 128; break; - case DW_OP_regx: - size = 128; break; - default: - s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); - return 1; - } - - switch (size) - { - case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break; - case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break; - case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break; - case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break; - case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break; - } - - return 0; -} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h deleted file mode 100644 index 69cc0c15969c..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- DWARFLocationDescription.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFLocationDescription_h_ -#define SymbolFileDWARF_DWARFLocationDescription_h_ - -#include "SymbolFileDWARF.h" - -int -print_dwarf_expression (lldb_private::Stream &s, - const lldb_private::DWARFDataExtractor& data, - int address_size, - int dwarf_ref_size, - bool location_expression); - - - -#endif // SymbolFileDWARF_DWARFLocationDescription_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp deleted file mode 100644 index 26768f060ef1..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFLocationList.h" - -#include "lldb/Core/Stream.h" - -#include "DWARFCompileUnit.h" -#include "DWARFDebugInfo.h" -#include "DWARFLocationDescription.h" - -using namespace lldb_private; - -dw_offset_t -DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset) -{ - uint64_t start_addr, end_addr; - uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); - s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu)); - dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; - while (debug_loc_data.ValidOffset(offset)) - { - start_addr = debug_loc_data.GetMaxU64(&offset,addr_size); - end_addr = debug_loc_data.GetMaxU64(&offset,addr_size); - - if (start_addr == 0 && end_addr == 0) - break; - - s.PutCString("\n "); - s.Indent(); - if (cu) - s.AddressRange (start_addr + base_addr, - end_addr + base_addr, - cu->GetAddressByteSize(), - NULL, - ": "); - uint32_t loc_length = debug_loc_data.GetU16(&offset); - - DWARFDataExtractor locationData(debug_loc_data, offset, loc_length); - // if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( "; - print_dwarf_expression (s, locationData, addr_size, 4, false); - offset += loc_length; - } - - return offset; -} - -bool -DWARFLocationList::Extract(const DWARFDataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DWARFDataExtractor& location_list_data) -{ - // Initialize with no data just in case we don't find anything - location_list_data.Clear(); - - size_t loc_list_length = Size(debug_loc_data, *offset_ptr); - if (loc_list_length > 0) - { - location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length); - *offset_ptr += loc_list_length; - return true; - } - - return false; -} - -size_t -DWARFLocationList::Size(const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset) -{ - const dw_offset_t debug_loc_offset = offset; - - while (debug_loc_data.ValidOffset(offset)) - { - dw_addr_t start_addr = debug_loc_data.GetAddress(&offset); - dw_addr_t end_addr = debug_loc_data.GetAddress(&offset); - - if (start_addr == 0 && end_addr == 0) - break; - - uint16_t loc_length = debug_loc_data.GetU16(&offset); - offset += loc_length; - } - - if (offset > debug_loc_offset) - return offset - debug_loc_offset; - return 0; -} - - - diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h deleted file mode 100644 index 6dcc0d74e441..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h +++ /dev/null @@ -1,34 +0,0 @@ -//===-- DWARFLocationList.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFLocationList_h_ -#define SymbolFileDWARF_DWARFLocationList_h_ - -#include "SymbolFileDWARF.h" - -class DWARFLocationList -{ -public: - static dw_offset_t - Dump (lldb_private::Stream &s, - const DWARFCompileUnit* cu, - const lldb_private::DWARFDataExtractor& debug_loc_data, - lldb::offset_t offset); - - static bool - Extract (const lldb_private::DWARFDataExtractor& debug_loc_data, - lldb::offset_t* offset_ptr, - lldb_private::DWARFDataExtractor& location_list_data); - - static size_t - Size (const lldb_private::DWARFDataExtractor& debug_loc_data, - lldb::offset_t offset); - -}; -#endif // SymbolFileDWARF_DWARFLocationList_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp new file mode 100644 index 000000000000..0db416054ae8 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -0,0 +1,747 @@ +//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "HashedNameToDIE.h" + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets) +{ + const size_t count = die_info_array.size(); + for (size_t i=0; i<count; ++i) + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +} + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, + const dw_tag_t tag, + DIEArray &die_offsets) +{ + if (tag == 0) + { + ExtractDIEArray (die_info_array, die_offsets); + } + else + { + const size_t count = die_info_array.size(); + for (size_t i=0; i<count; ++i) + { + const dw_tag_t die_tag = die_info_array[i].tag; + bool tag_matches = die_tag == 0 || tag == die_tag; + if (!tag_matches) + { + if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) + tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; + } + if (tag_matches) + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); + } + } +} + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, + const dw_tag_t tag, + const uint32_t qualified_name_hash, + DIEArray &die_offsets) +{ + if (tag == 0) + { + ExtractDIEArray (die_info_array, die_offsets); + } + else + { + const size_t count = die_info_array.size(); + for (size_t i=0; i<count; ++i) + { + if (qualified_name_hash != die_info_array[i].qualified_name_hash) + continue; + const dw_tag_t die_tag = die_info_array[i].tag; + bool tag_matches = die_tag == 0 || tag == die_tag; + if (!tag_matches) + { + if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) + tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; + } + if (tag_matches) + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); + } + } +} + +void +DWARFMappedHash::ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, + bool return_implementation_only_if_available, + DIEArray &die_offsets) +{ + const size_t count = die_info_array.size(); + for (size_t i=0; i<count; ++i) + { + const dw_tag_t die_tag = die_info_array[i].tag; + if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) + { + if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) + { + if (return_implementation_only_if_available) + { + // We found the one true definition for this class, so + // only return that + die_offsets.clear(); + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); + return; + } + else + { + // Put the one true definition as the first entry so it + // matches first + die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset, die_info_array[i].offset); + } + } + else + { + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); + } + } + } +} + +void +DWARFMappedHash::ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, + uint32_t type_flag_mask, + uint32_t type_flag_value, + DIEArray &die_offsets) +{ + const size_t count = die_info_array.size(); + for (size_t i=0; i<count; ++i) + { + if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) + die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); + } +} + +const char * +DWARFMappedHash::GetAtomTypeName (uint16_t atom) +{ + switch (atom) + { + case eAtomTypeNULL: return "NULL"; + case eAtomTypeDIEOffset: return "die-offset"; + case eAtomTypeCUOffset: return "cu-offset"; + case eAtomTypeTag: return "die-tag"; + case eAtomTypeNameFlags: return "name-flags"; + case eAtomTypeTypeFlags: return "type-flags"; + case eAtomTypeQualNameHash: return "qualified-name-hash"; + } + return "<invalid>"; +} + +DWARFMappedHash::DIEInfo::DIEInfo () : + cu_offset (DW_INVALID_OFFSET), + offset (DW_INVALID_OFFSET), + tag (0), + type_flags (0), + qualified_name_hash (0) +{ +} + +DWARFMappedHash::DIEInfo::DIEInfo (dw_offset_t c, + dw_offset_t o, + dw_tag_t t, + uint32_t f, + uint32_t h) : + cu_offset (c), + offset (o), + tag (t), + type_flags (f), + qualified_name_hash (h) +{ +} + +DWARFMappedHash::Prologue::Prologue (dw_offset_t _die_base_offset) : + die_base_offset (_die_base_offset), + atoms(), + atom_mask (0), + min_hash_data_byte_size(0), + hash_data_has_fixed_byte_size(true) +{ + // Define an array of DIE offsets by first defining an array, + // and then define the atom type for the array, in this case + // we have an array of DIE offsets + AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); +} + +void +DWARFMappedHash::Prologue::ClearAtoms () +{ + hash_data_has_fixed_byte_size = true; + min_hash_data_byte_size = 0; + atom_mask = 0; + atoms.clear(); +} + +bool +DWARFMappedHash::Prologue::ContainsAtom (AtomType atom_type) const +{ + return (atom_mask & (1u << atom_type)) != 0; +} + +void +DWARFMappedHash::Prologue::Clear () +{ + die_base_offset = 0; + ClearAtoms (); +} + +void +DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form) +{ + atoms.push_back ({type, form}); + atom_mask |= 1u << type; + switch (form) + { + case DW_FORM_indirect: + case DW_FORM_exprloc: + case DW_FORM_flag_present: + case DW_FORM_ref_sig8: + assert (!"Unhandled atom form"); + break; + + case DW_FORM_string: + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index: + hash_data_has_fixed_byte_size = false; + // Fall through to the cases below... + case DW_FORM_flag: + case DW_FORM_data1: + case DW_FORM_ref1: + case DW_FORM_sec_offset: + min_hash_data_byte_size += 1; + break; + + case DW_FORM_block2: + hash_data_has_fixed_byte_size = false; + // Fall through to the cases below... + case DW_FORM_data2: + case DW_FORM_ref2: + min_hash_data_byte_size += 2; + break; + + case DW_FORM_block4: + hash_data_has_fixed_byte_size = false; + // Fall through to the cases below... + case DW_FORM_data4: + case DW_FORM_ref4: + case DW_FORM_addr: + case DW_FORM_ref_addr: + case DW_FORM_strp: + min_hash_data_byte_size += 4; + break; + + case DW_FORM_data8: + case DW_FORM_ref8: + min_hash_data_byte_size += 8; + break; + + } +} + +lldb::offset_t +DWARFMappedHash::Prologue::Read (const lldb_private::DataExtractor &data, + lldb::offset_t offset) +{ + ClearAtoms (); + + die_base_offset = data.GetU32 (&offset); + + const uint32_t atom_count = data.GetU32 (&offset); + if (atom_count == 0x00060003u) + { + // Old format, deal with contents of old pre-release format + while (data.GetU32(&offset)) + /* do nothing */; + + // Hardcode to the only known value for now. + AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); + } + else + { + for (uint32_t i=0; i<atom_count; ++i) + { + AtomType type = (AtomType)data.GetU16 (&offset); + dw_form_t form = (dw_form_t)data.GetU16 (&offset); + AppendAtom (type, form); + } + } + return offset; +} + +size_t +DWARFMappedHash::Prologue::GetByteSize () const +{ + // Add an extra count to the atoms size for the zero termination Atom that gets + // written to disk + return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); +} + +size_t +DWARFMappedHash::Prologue::GetMinimumHashDataByteSize () const +{ + return min_hash_data_byte_size; +} + +bool +DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const +{ + return hash_data_has_fixed_byte_size; +} + +size_t +DWARFMappedHash::Header::GetByteSize (const HeaderData &header_data) +{ + return header_data.GetByteSize(); +} + +lldb::offset_t +DWARFMappedHash::Header::Read (lldb_private::DataExtractor &data, lldb::offset_t offset) +{ + offset = MappedHash::Header<Prologue>::Read (data, offset); + if (offset != UINT32_MAX) + { + offset = header_data.Read (data, offset); + } + return offset; +} + +bool +DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr, + DIEInfo &hash_data) const +{ + const size_t num_atoms = header_data.atoms.size(); + if (num_atoms == 0) + return false; + + for (size_t i=0; i<num_atoms; ++i) + { + DWARFFormValue form_value (NULL, header_data.atoms[i].form); + + if (!form_value.ExtractValue(data, offset_ptr)) + return false; + + switch (header_data.atoms[i].type) + { + case eAtomTypeDIEOffset: // DIE offset, check form for encoding + hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); + break; + + case eAtomTypeTag: // DW_TAG value for the DIE + hash_data.tag = (dw_tag_t)form_value.Unsigned (); + + case eAtomTypeTypeFlags: // Flags from enum TypeFlags + hash_data.type_flags = (uint32_t)form_value.Unsigned (); + break; + + case eAtomTypeQualNameHash: // Flags from enum TypeFlags + hash_data.qualified_name_hash = form_value.Unsigned (); + break; + + default: + // We can always skip atoms we don't know about + break; + } + } + return true; +} + +void +DWARFMappedHash::Header::Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const +{ + const size_t num_atoms = header_data.atoms.size(); + for (size_t i=0; i<num_atoms; ++i) + { + if (i > 0) + strm.PutCString (", "); + + DWARFFormValue form_value (NULL, header_data.atoms[i].form); + switch (header_data.atoms[i].type) + { + case eAtomTypeDIEOffset: // DIE offset, check form for encoding + strm.Printf ("{0x%8.8x}", hash_data.offset); + break; + + case eAtomTypeTag: // DW_TAG value for the DIE + { + const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); + if (tag_cstr) + strm.PutCString (tag_cstr); + else + strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); + } + break; + + case eAtomTypeTypeFlags: // Flags from enum TypeFlags + strm.Printf ("0x%2.2x", hash_data.type_flags); + if (hash_data.type_flags) + { + strm.PutCString (" ("); + if (hash_data.type_flags & eTypeFlagClassIsImplementation) + strm.PutCString (" implementation"); + strm.PutCString (" )"); + } + break; + + case eAtomTypeQualNameHash: // Flags from enum TypeFlags + strm.Printf ("0x%8.8x", hash_data.qualified_name_hash); + break; + + default: + strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); + break; + } + } +} + +DWARFMappedHash::MemoryTable::MemoryTable (lldb_private::DWARFDataExtractor &table_data, + const lldb_private::DWARFDataExtractor &string_table, + const char *name) : + MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), + m_data (table_data), + m_string_table (string_table), + m_name (name) +{ +} + +const char * +DWARFMappedHash::MemoryTable::GetStringForKeyType (KeyType key) const +{ + // The key in the DWARF table is the .debug_str offset for the string + return m_string_table.PeekCStr (key); +} + +bool +DWARFMappedHash::MemoryTable::ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const +{ + lldb::offset_t offset = hash_data_offset; + offset += 4; // Skip string table offset that contains offset of hash name in .debug_str + const uint32_t count = m_data.GetU32 (&offset); + if (count > 0) + { + hash_data.resize(count); + for (uint32_t i=0; i<count; ++i) + { + if (!m_header.Read(m_data, &offset, hash_data[i])) + return false; + } + } + else + hash_data.clear(); + return true; +} + +DWARFMappedHash::MemoryTable::Result +DWARFMappedHash::MemoryTable::GetHashDataForName (const char *name, + lldb::offset_t* hash_data_offset_ptr, + Pair &pair) const +{ + pair.key = m_data.GetU32 (hash_data_offset_ptr); + pair.value.clear(); + + // If the key is zero, this terminates our chain of HashData objects + // for this hash value. + if (pair.key == 0) + return eResultEndOfHashData; + + // There definitely should be a string for this string offset, if + // there isn't, there is something wrong, return and error + const char *strp_cstr = m_string_table.PeekCStr (pair.key); + if (strp_cstr == NULL) + { + *hash_data_offset_ptr = UINT32_MAX; + return eResultError; + } + + const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); + const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); + if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) + { + // We have at least one HashData entry, and we have enough + // data to parse at least "count" HashData entries. + + // First make sure the entire C string matches... + const bool match = strcmp (name, strp_cstr) == 0; + + if (!match && m_header.header_data.HashDataHasFixedByteSize()) + { + // If the string doesn't match and we have fixed size data, + // we can just add the total byte size of all HashData objects + // to the hash data offset and be done... + *hash_data_offset_ptr += min_total_hash_data_size; + } + else + { + // If the string does match, or we don't have fixed size data + // then we need to read the hash data as a stream. If the + // string matches we also append all HashData objects to the + // value array. + for (uint32_t i=0; i<count; ++i) + { + DIEInfo die_info; + if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) + { + // Only happened if the HashData of the string matched... + if (match) + pair.value.push_back (die_info); + } + else + { + // Something went wrong while reading the data + *hash_data_offset_ptr = UINT32_MAX; + return eResultError; + } + } + } + // Return the correct response depending on if the string matched + // or not... + if (match) + return eResultKeyMatch; // The key (cstring) matches and we have lookup results! + else + return eResultKeyMismatch; // The key doesn't match, this function will get called + // again for the next key/value or the key terminator + // which in our case is a zero .debug_str offset. + } + else + { + *hash_data_offset_ptr = UINT32_MAX; + return eResultError; + } +} + +DWARFMappedHash::MemoryTable::Result +DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression ( + const lldb_private::RegularExpression& regex, + lldb::offset_t* hash_data_offset_ptr, + Pair &pair) const +{ + pair.key = m_data.GetU32 (hash_data_offset_ptr); + // If the key is zero, this terminates our chain of HashData objects + // for this hash value. + if (pair.key == 0) + return eResultEndOfHashData; + + // There definitely should be a string for this string offset, if + // there isn't, there is something wrong, return and error + const char *strp_cstr = m_string_table.PeekCStr (pair.key); + if (strp_cstr == NULL) + return eResultError; + + const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); + const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); + if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) + { + const bool match = regex.Execute(strp_cstr); + + if (!match && m_header.header_data.HashDataHasFixedByteSize()) + { + // If the regex doesn't match and we have fixed size data, + // we can just add the total byte size of all HashData objects + // to the hash data offset and be done... + *hash_data_offset_ptr += min_total_hash_data_size; + } + else + { + // If the string does match, or we don't have fixed size data + // then we need to read the hash data as a stream. If the + // string matches we also append all HashData objects to the + // value array. + for (uint32_t i=0; i<count; ++i) + { + DIEInfo die_info; + if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) + { + // Only happened if the HashData of the string matched... + if (match) + pair.value.push_back (die_info); + } + else + { + // Something went wrong while reading the data + *hash_data_offset_ptr = UINT32_MAX; + return eResultError; + } + } + } + // Return the correct response depending on if the string matched + // or not... + if (match) + return eResultKeyMatch; // The key (cstring) matches and we have lookup results! + else + return eResultKeyMismatch; // The key doesn't match, this function will get called + // again for the next key/value or the key terminator + // which in our case is a zero .debug_str offset. + } + else + { + *hash_data_offset_ptr = UINT32_MAX; + return eResultError; + } +} + +size_t +DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex ( + const lldb_private::RegularExpression& regex, + DIEInfoArray &die_info_array) const +{ + const uint32_t hash_count = m_header.hashes_count; + Pair pair; + for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) + { + lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); + while (hash_data_offset != UINT32_MAX) + { + const lldb::offset_t prev_hash_data_offset = hash_data_offset; + Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); + if (prev_hash_data_offset == hash_data_offset) + break; + + // Check the result of getting our hash data + switch (hash_result) + { + case eResultKeyMatch: + case eResultKeyMismatch: + // Whether we matches or not, it doesn't matter, we + // keep looking. + break; + + case eResultEndOfHashData: + case eResultError: + hash_data_offset = UINT32_MAX; + break; + } + } + } + die_info_array.swap (pair.value); + return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_start, + const uint32_t die_offset_end, + DIEInfoArray &die_info_array) const +{ + const uint32_t hash_count = m_header.hashes_count; + for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) + { + bool done = false; + lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); + while (!done && hash_data_offset != UINT32_MAX) + { + KeyType key = m_data.GetU32 (&hash_data_offset); + // If the key is zero, this terminates our chain of HashData objects + // for this hash value. + if (key == 0) + break; + + const uint32_t count = m_data.GetU32 (&hash_data_offset); + for (uint32_t i=0; i<count; ++i) + { + DIEInfo die_info; + if (m_header.Read(m_data, &hash_data_offset, die_info)) + { + if (die_info.offset == 0) + done = true; + if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) + die_info_array.push_back(die_info); + } + } + } + } + return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets) +{ + DIEInfoArray die_info_array; + if (FindByName(name, die_info_array)) + DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); + return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByNameAndTag (const char *name, + const dw_tag_t tag, + DIEArray &die_offsets) +{ + DIEInfoArray die_info_array; + if (FindByName(name, die_info_array)) + DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); + return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash (const char *name, + const dw_tag_t tag, + const uint32_t qualified_name_hash, + DIEArray &die_offsets) +{ + DIEInfoArray die_info_array; + if (FindByName(name, die_info_array)) + DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets); + return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name, + DIEArray &die_offsets, + bool must_be_implementation) +{ + DIEInfoArray die_info_array; + if (FindByName(name, die_info_array)) + { + if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) + { + // If we have two atoms, then we have the DIE offset and + // the type flags so we can find the objective C class + // efficiently. + DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, + UINT32_MAX, + eTypeFlagClassIsImplementation, + die_offsets); + } + else + { + // We don't only want the one true definition, so try and see + // what we can find, and only return class or struct DIEs. + // If we do have the full implementation, then return it alone, + // else return all possible matches. + const bool return_implementation_only_if_available = true; + DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, + return_implementation_only_if_available, + die_offsets); + } + } + return die_offsets.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array) +{ + Pair kv_pair; + size_t old_size = die_info_array.size(); + if (Find (name, kv_pair)) + { + die_info_array.swap(kv_pair.value); + return die_info_array.size() - old_size; + } + return 0; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index f8a8cc60467d..bcde558ae449 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -12,139 +12,36 @@ #include <vector> -#include "DWARFDefines.h" -#include "DWARFFormValue.h" - #include "lldb/lldb-defines.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/MappedHash.h" +#include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "NameToDIE.h" class SymbolFileDWARF; class DWARFCompileUnit; class DWARFDebugInfoEntry; -struct DWARFMappedHash +class DWARFMappedHash { - struct DIEInfo - { - dw_offset_t offset; // The DIE offset - dw_tag_t tag; - uint32_t type_flags; // Any flags for this DIEInfo - uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name - - DIEInfo () : - offset (DW_INVALID_OFFSET), - tag (0), - type_flags (0), - qualified_name_hash (0) - { - } - - DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) : - offset(o), - tag (t), - type_flags (f), - qualified_name_hash (h) - { - } - - void - Clear() - { - offset = DW_INVALID_OFFSET; - tag = 0; - type_flags = 0; - qualified_name_hash = 0; - } - }; - - typedef std::vector<DIEInfo> DIEInfoArray; - typedef std::vector<uint32_t> DIEArray; - - static void - ExtractDIEArray (const DIEInfoArray &die_info_array, - DIEArray &die_offsets) - { - const size_t count = die_info_array.size(); - for (size_t i=0; i<count; ++i) - { - die_offsets.push_back (die_info_array[i].offset); - } - } - - static void - ExtractDIEArray (const DIEInfoArray &die_info_array, - const dw_tag_t tag, - DIEArray &die_offsets) - { - if (tag == 0) - { - ExtractDIEArray (die_info_array, die_offsets); - } - else - { - const size_t count = die_info_array.size(); - for (size_t i=0; i<count; ++i) - { - const dw_tag_t die_tag = die_info_array[i].tag; - bool tag_matches = die_tag == 0 || tag == die_tag; - if (!tag_matches) - { - if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) - tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; - } - if (tag_matches) - die_offsets.push_back (die_info_array[i].offset); - } - } - } - - static void - ExtractDIEArray (const DIEInfoArray &die_info_array, - const dw_tag_t tag, - const uint32_t qualified_name_hash, - DIEArray &die_offsets) - { - if (tag == 0) - { - ExtractDIEArray (die_info_array, die_offsets); - } - else - { - const size_t count = die_info_array.size(); - for (size_t i=0; i<count; ++i) - { - if (qualified_name_hash != die_info_array[i].qualified_name_hash) - continue; - const dw_tag_t die_tag = die_info_array[i].tag; - bool tag_matches = die_tag == 0 || tag == die_tag; - if (!tag_matches) - { - if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) - tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; - } - if (tag_matches) - die_offsets.push_back (die_info_array[i].offset); - } - } - } - - enum AtomType +public: + enum AtomType : uint16_t { - eAtomTypeNULL = 0u, - eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding - eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question - eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 - eAtomTypeNameFlags = 4u, // Flags from enum NameFlags - eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, + eAtomTypeNULL = 0u, + eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding + eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question + eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 + eAtomTypeNameFlags = 4u, // Flags from enum NameFlags + eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name (since all hash entries are basename only) // For example a type like "std::vector<int>::iterator" would have a name of "iterator" // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull // in debug info for a type when we know the fully qualified name. }; - + // Bit definitions for the eAtomTypeTypeFlags flags enum TypeFlags { @@ -152,782 +49,171 @@ struct DWARFMappedHash // @implementation for class eTypeFlagClassIsImplementation = ( 1u << 1 ) }; - - static void - ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, - bool return_implementation_only_if_available, - DIEArray &die_offsets) + struct DIEInfo { - const size_t count = die_info_array.size(); - for (size_t i=0; i<count; ++i) - { - const dw_tag_t die_tag = die_info_array[i].tag; - if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) - { - if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) - { - if (return_implementation_only_if_available) - { - // We found the one true definition for this class, so - // only return that - die_offsets.clear(); - die_offsets.push_back (die_info_array[i].offset); - return; - } - else - { - // Put the one true definition as the first entry so it - // matches first - die_offsets.insert (die_offsets.begin(), die_info_array[i].offset); - } - } - else - { - die_offsets.push_back (die_info_array[i].offset); - } - } - } - } + dw_offset_t cu_offset; + dw_offset_t offset; // The DIE offset + dw_tag_t tag; + uint32_t type_flags; // Any flags for this DIEInfo + uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name - static void - ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, - uint32_t type_flag_mask, - uint32_t type_flag_value, - DIEArray &die_offsets) - { - const size_t count = die_info_array.size(); - for (size_t i=0; i<count; ++i) - { - if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) - die_offsets.push_back (die_info_array[i].offset); - } - } + DIEInfo (); + DIEInfo (dw_offset_t c, dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); + }; struct Atom { - uint16_t type; + AtomType type; dw_form_t form; - - Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) : - type (t), - form (f) - { - } }; - + + typedef std::vector<DIEInfo> DIEInfoArray; typedef std::vector<Atom> AtomArray; - - static uint32_t - GetTypeFlags (SymbolFileDWARF *dwarf2Data, - const DWARFCompileUnit* cu, - const DWARFDebugInfoEntry* die); - - static const char * - GetAtomTypeName (uint16_t atom) - { - switch (atom) - { - case eAtomTypeNULL: return "NULL"; - case eAtomTypeDIEOffset: return "die-offset"; - case eAtomTypeCUOffset: return "cu-offset"; - case eAtomTypeTag: return "die-tag"; - case eAtomTypeNameFlags: return "name-flags"; - case eAtomTypeTypeFlags: return "type-flags"; - case eAtomTypeQualNameHash: return "qualified-name-hash"; - } - return "<invalid>"; - } - struct Prologue + class Prologue { - // DIE offset base so die offsets in hash_data can be CU relative - dw_offset_t die_base_offset; - AtomArray atoms; - uint32_t atom_mask; - size_t min_hash_data_byte_size; - bool hash_data_has_fixed_byte_size; - - Prologue (dw_offset_t _die_base_offset = 0) : - die_base_offset (_die_base_offset), - atoms(), - atom_mask (0), - min_hash_data_byte_size(0), - hash_data_has_fixed_byte_size(true) - { - // Define an array of DIE offsets by first defining an array, - // and then define the atom type for the array, in this case - // we have an array of DIE offsets - AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); - } - - virtual ~Prologue() - { - } + public: + Prologue (dw_offset_t _die_base_offset = 0); void - ClearAtoms () - { - hash_data_has_fixed_byte_size = true; - min_hash_data_byte_size = 0; - atom_mask = 0; - atoms.clear(); - } + ClearAtoms (); bool - ContainsAtom (AtomType atom_type) const - { - return (atom_mask & (1u << atom_type)) != 0; - } - - virtual void - Clear () - { - die_base_offset = 0; - ClearAtoms (); - } - + ContainsAtom (AtomType atom_type) const; + void - AppendAtom (AtomType type, dw_form_t form) - { - atoms.push_back (Atom(type, form)); - atom_mask |= 1u << type; - switch (form) - { - case DW_FORM_indirect: - case DW_FORM_exprloc: - case DW_FORM_flag_present: - case DW_FORM_ref_sig8: - assert (!"Unhandled atom form"); - break; - - case DW_FORM_string: - case DW_FORM_block: - case DW_FORM_block1: - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - hash_data_has_fixed_byte_size = false; - // Fall through to the cases below... - case DW_FORM_flag: - case DW_FORM_data1: - case DW_FORM_ref1: - case DW_FORM_sec_offset: - min_hash_data_byte_size += 1; - break; - - case DW_FORM_block2: - hash_data_has_fixed_byte_size = false; - // Fall through to the cases below... - case DW_FORM_data2: - case DW_FORM_ref2: - min_hash_data_byte_size += 2; - break; - - case DW_FORM_block4: - hash_data_has_fixed_byte_size = false; - // Fall through to the cases below... - case DW_FORM_data4: - case DW_FORM_ref4: - case DW_FORM_addr: - case DW_FORM_ref_addr: - case DW_FORM_strp: - min_hash_data_byte_size += 4; - break; - - case DW_FORM_data8: - case DW_FORM_ref8: - min_hash_data_byte_size += 8; - break; - - } - } - -// void -// Dump (std::ostream* ostrm_ptr); - + Clear (); + + void + AppendAtom (AtomType type, dw_form_t form); + lldb::offset_t - Read (const lldb_private::DataExtractor &data, - lldb::offset_t offset) - { - ClearAtoms (); - - die_base_offset = data.GetU32 (&offset); - - const uint32_t atom_count = data.GetU32 (&offset); - if (atom_count == 0x00060003u) - { - // Old format, deal with contents of old pre-release format - while (data.GetU32(&offset)) - /* do nothing */; - - // Hardcode to the only known value for now. - AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); - } - else - { - for (uint32_t i=0; i<atom_count; ++i) - { - AtomType type = (AtomType)data.GetU16 (&offset); - dw_form_t form = (dw_form_t)data.GetU16 (&offset); - AppendAtom (type, form); - } - } - return offset; - } - -// virtual void -// Write (BinaryStreamBuf &s); - + Read (const lldb_private::DataExtractor &data, lldb::offset_t offset); + size_t - GetByteSize () const - { - // Add an extra count to the atoms size for the zero termination Atom that gets - // written to disk - return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); - } - + GetByteSize () const; + size_t - GetMinimumHashDataByteSize () const - { - return min_hash_data_byte_size; - } + GetMinimumHashDataByteSize () const; bool - HashDataHasFixedByteSize() const - { - return hash_data_has_fixed_byte_size; - } + HashDataHasFixedByteSize() const; + + // DIE offset base so die offsets in hash_data can be CU relative + dw_offset_t die_base_offset; + AtomArray atoms; + uint32_t atom_mask; + size_t min_hash_data_byte_size; + bool hash_data_has_fixed_byte_size; }; - struct Header : public MappedHash::Header<Prologue> + class Header : public MappedHash::Header<Prologue> { - Header (dw_offset_t _die_base_offset = 0) - { - } - - virtual - ~Header() - { - } - - virtual size_t - GetByteSize (const HeaderData &header_data) - { - return header_data.GetByteSize(); - } - - // virtual void - // Dump (std::ostream* ostrm_ptr); - // - virtual lldb::offset_t - Read (lldb_private::DataExtractor &data, lldb::offset_t offset) - { - offset = MappedHash::Header<Prologue>::Read (data, offset); - if (offset != UINT32_MAX) - { - offset = header_data.Read (data, offset); - } - return offset; - } - + public: + size_t + GetByteSize (const HeaderData &header_data) override; + + lldb::offset_t + Read (lldb_private::DataExtractor &data, lldb::offset_t offset) override; + bool Read (const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr, - DIEInfo &hash_data) const - { - const size_t num_atoms = header_data.atoms.size(); - if (num_atoms == 0) - return false; - - for (size_t i=0; i<num_atoms; ++i) - { - DWARFFormValue form_value (NULL, header_data.atoms[i].form); - - if (!form_value.ExtractValue(data, offset_ptr)) - return false; - - switch (header_data.atoms[i].type) - { - case eAtomTypeDIEOffset: // DIE offset, check form for encoding - hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); - break; - - case eAtomTypeTag: // DW_TAG value for the DIE - hash_data.tag = (dw_tag_t)form_value.Unsigned (); - - case eAtomTypeTypeFlags: // Flags from enum TypeFlags - hash_data.type_flags = (uint32_t)form_value.Unsigned (); - break; - - case eAtomTypeQualNameHash: // Flags from enum TypeFlags - hash_data.qualified_name_hash = form_value.Unsigned (); - break; - - default: - // We can always skip atoms we don't know about - break; - } - } - return true; - } - + DIEInfo &hash_data) const; + void - Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const - { - const size_t num_atoms = header_data.atoms.size(); - for (size_t i=0; i<num_atoms; ++i) - { - if (i > 0) - strm.PutCString (", "); - - DWARFFormValue form_value (NULL, header_data.atoms[i].form); - switch (header_data.atoms[i].type) - { - case eAtomTypeDIEOffset: // DIE offset, check form for encoding - strm.Printf ("{0x%8.8x}", hash_data.offset); - break; - - case eAtomTypeTag: // DW_TAG value for the DIE - { - const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); - if (tag_cstr) - strm.PutCString (tag_cstr); - else - strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); - } - break; - - case eAtomTypeTypeFlags: // Flags from enum TypeFlags - strm.Printf ("0x%2.2x", hash_data.type_flags); - if (hash_data.type_flags) - { - strm.PutCString (" ("); - if (hash_data.type_flags & eTypeFlagClassIsImplementation) - strm.PutCString (" implementation"); - strm.PutCString (" )"); - } - break; - - case eAtomTypeQualNameHash: // Flags from enum TypeFlags - strm.Printf ("0x%8.8x", hash_data.qualified_name_hash); - break; - - default: - strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); - break; - } - } - } + Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const; }; - -// class ExportTable -// { -// public: -// ExportTable (); -// -// void -// AppendNames (DWARFDebugPubnamesSet &pubnames_set, -// StringTable &string_table); -// -// void -// AppendNamesEntry (SymbolFileDWARF *dwarf2Data, -// const DWARFCompileUnit* cu, -// const DWARFDebugInfoEntry* die, -// StringTable &string_table); -// -// void -// AppendTypesEntry (DWARFData *dwarf2Data, -// const DWARFCompileUnit* cu, -// const DWARFDebugInfoEntry* die, -// StringTable &string_table); -// -// size_t -// Save (BinaryStreamBuf &names_data, const StringTable &string_table); -// -// void -// AppendName (const char *name, -// uint32_t die_offset, -// StringTable &string_table, -// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied -// void -// AppendType (const char *name, -// uint32_t die_offset, -// StringTable &string_table); -// -// -// protected: -// struct Entry -// { -// uint32_t hash; -// uint32_t str_offset; -// uint32_t die_offset; -// }; -// -// // Map uniqued .debug_str offset to the corresponding DIE offsets -// typedef std::map<uint32_t, DIEInfoArray> NameInfo; -// // Map a name hash to one or more name infos -// typedef std::map<uint32_t, NameInfo> BucketEntry; -// -// static uint32_t -// GetByteSize (const NameInfo &name_info); -// -// typedef std::vector<BucketEntry> BucketEntryColl; -// typedef std::vector<Entry> EntryColl; -// EntryColl m_entries; -// -// }; - - + // A class for reading and using a saved hash table from a block of data // in memory class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> { public: - MemoryTable (lldb_private::DWARFDataExtractor &table_data, const lldb_private::DWARFDataExtractor &string_table, - const char *name) : - MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), - m_data (table_data), - m_string_table (string_table), - m_name (name) - { - } - - virtual - ~MemoryTable () - { - } - - virtual const char * - GetStringForKeyType (KeyType key) const - { - // The key in the DWARF table is the .debug_str offset for the string - return m_string_table.PeekCStr (key); - } + const char *name); + + const char * + GetStringForKeyType (KeyType key) const override; - virtual bool - ReadHashData (uint32_t hash_data_offset, - HashData &hash_data) const - { - lldb::offset_t offset = hash_data_offset; - offset += 4; // Skip string table offset that contains offset of hash name in .debug_str - const uint32_t count = m_data.GetU32 (&offset); - if (count > 0) - { - hash_data.resize(count); - for (uint32_t i=0; i<count; ++i) - { - if (!m_header.Read(m_data, &offset, hash_data[i])) - return false; - } - } - else - hash_data.clear(); - return true; - } - - virtual Result - GetHashDataForName (const char *name, - lldb::offset_t* hash_data_offset_ptr, - Pair &pair) const - { - pair.key = m_data.GetU32 (hash_data_offset_ptr); - pair.value.clear(); - - // If the key is zero, this terminates our chain of HashData objects - // for this hash value. - if (pair.key == 0) - return eResultEndOfHashData; - - // There definitely should be a string for this string offset, if - // there isn't, there is something wrong, return and error - const char *strp_cstr = m_string_table.PeekCStr (pair.key); - if (strp_cstr == NULL) - { - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } - - const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); - const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) - { - // We have at least one HashData entry, and we have enough - // data to parse at least "count" HashData entries. - - // First make sure the entire C string matches... - const bool match = strcmp (name, strp_cstr) == 0; - - if (!match && m_header.header_data.HashDataHasFixedByteSize()) - { - // If the string doesn't match and we have fixed size data, - // we can just add the total byte size of all HashData objects - // to the hash data offset and be done... - *hash_data_offset_ptr += min_total_hash_data_size; - } - else - { - // If the string does match, or we don't have fixed size data - // then we need to read the hash data as a stream. If the - // string matches we also append all HashData objects to the - // value array. - for (uint32_t i=0; i<count; ++i) - { - DIEInfo die_info; - if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) - { - // Only happened if the HashData of the string matched... - if (match) - pair.value.push_back (die_info); - } - else - { - // Something went wrong while reading the data - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } - } - } - // Return the correct response depending on if the string matched - // or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup results! - else - return eResultKeyMismatch; // The key doesn't match, this function will get called - // again for the next key/value or the key terminator - // which in our case is a zero .debug_str offset. - } - else - { - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } - } - - virtual Result - AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, - lldb::offset_t* hash_data_offset_ptr, - Pair &pair) const - { - pair.key = m_data.GetU32 (hash_data_offset_ptr); - // If the key is zero, this terminates our chain of HashData objects - // for this hash value. - if (pair.key == 0) - return eResultEndOfHashData; - - // There definitely should be a string for this string offset, if - // there isn't, there is something wrong, return and error - const char *strp_cstr = m_string_table.PeekCStr (pair.key); - if (strp_cstr == NULL) - return eResultError; - - const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); - const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) - { - const bool match = regex.Execute(strp_cstr); - - if (!match && m_header.header_data.HashDataHasFixedByteSize()) - { - // If the regex doesn't match and we have fixed size data, - // we can just add the total byte size of all HashData objects - // to the hash data offset and be done... - *hash_data_offset_ptr += min_total_hash_data_size; - } - else - { - // If the string does match, or we don't have fixed size data - // then we need to read the hash data as a stream. If the - // string matches we also append all HashData objects to the - // value array. - for (uint32_t i=0; i<count; ++i) - { - DIEInfo die_info; - if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) - { - // Only happened if the HashData of the string matched... - if (match) - pair.value.push_back (die_info); - } - else - { - // Something went wrong while reading the data - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } - } - } - // Return the correct response depending on if the string matched - // or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup results! - else - return eResultKeyMismatch; // The key doesn't match, this function will get called - // again for the next key/value or the key terminator - // which in our case is a zero .debug_str offset. - } - else - { - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } - } + bool + ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const override; size_t AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex, - DIEInfoArray &die_info_array) const - { - const uint32_t hash_count = m_header.hashes_count; - Pair pair; - for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) - { - lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); - while (hash_data_offset != UINT32_MAX) - { - const lldb::offset_t prev_hash_data_offset = hash_data_offset; - Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); - if (prev_hash_data_offset == hash_data_offset) - break; - - // Check the result of getting our hash data - switch (hash_result) - { - case eResultKeyMatch: - case eResultKeyMismatch: - // Whether we matches or not, it doesn't matter, we - // keep looking. - break; - - case eResultEndOfHashData: - case eResultError: - hash_data_offset = UINT32_MAX; - break; - } - } - } - die_info_array.swap (pair.value); - return die_info_array.size(); - } - + DIEInfoArray &die_info_array) const; + size_t AppendAllDIEsInRange (const uint32_t die_offset_start, const uint32_t die_offset_end, - DIEInfoArray &die_info_array) const - { - const uint32_t hash_count = m_header.hashes_count; - for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) - { - bool done = false; - lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); - while (!done && hash_data_offset != UINT32_MAX) - { - KeyType key = m_data.GetU32 (&hash_data_offset); - // If the key is zero, this terminates our chain of HashData objects - // for this hash value. - if (key == 0) - break; - - const uint32_t count = m_data.GetU32 (&hash_data_offset); - for (uint32_t i=0; i<count; ++i) - { - DIEInfo die_info; - if (m_header.Read(m_data, &hash_data_offset, die_info)) - { - if (die_info.offset == 0) - done = true; - if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) - die_info_array.push_back(die_info); - } - } - } - } - return die_info_array.size(); - } + DIEInfoArray &die_info_array) const; size_t - FindByName (const char *name, DIEArray &die_offsets) - { - DIEInfoArray die_info_array; - if (FindByName(name, die_info_array)) - DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); - return die_info_array.size(); - } + FindByName (const char *name, DIEArray &die_offsets); size_t - FindByNameAndTag (const char *name, - const dw_tag_t tag, - DIEArray &die_offsets) - { - DIEInfoArray die_info_array; - if (FindByName(name, die_info_array)) - DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); - return die_info_array.size(); - } + FindByNameAndTag (const char *name, const dw_tag_t tag, DIEArray &die_offsets); size_t FindByNameAndTagAndQualifiedNameHash (const char *name, const dw_tag_t tag, const uint32_t qualified_name_hash, - DIEArray &die_offsets) - { - DIEInfoArray die_info_array; - if (FindByName(name, die_info_array)) - DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets); - return die_info_array.size(); - } + DIEArray &die_offsets); size_t - FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation) - { - DIEInfoArray die_info_array; - if (FindByName(name, die_info_array)) - { - if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) - { - // If we have two atoms, then we have the DIE offset and - // the type flags so we can find the objective C class - // efficiently. - DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, - UINT32_MAX, - eTypeFlagClassIsImplementation, - die_offsets); - } - else - { - // We don't only want the one true definition, so try and see - // what we can find, and only return class or struct DIEs. - // If we do have the full implementation, then return it alone, - // else return all possible matches. - const bool return_implementation_only_if_available = true; - DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, - return_implementation_only_if_available, - die_offsets); - } - } - return die_offsets.size(); - } + FindCompleteObjCClassByName (const char *name, + DIEArray &die_offsets, + bool must_be_implementation); - size_t - FindByName (const char *name, DIEInfoArray &die_info_array) - { - Pair kv_pair; - size_t old_size = die_info_array.size(); - if (Find (name, kv_pair)) - { - die_info_array.swap(kv_pair.value); - return die_info_array.size() - old_size; - } - return 0; - } - protected: + Result + AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, + lldb::offset_t* hash_data_offset_ptr, + Pair &pair) const; + + size_t + FindByName (const char *name, DIEInfoArray &die_info_array); + + Result + GetHashDataForName (const char *name, + lldb::offset_t* hash_data_offset_ptr, + Pair &pair) const override; + const lldb_private::DWARFDataExtractor &m_data; const lldb_private::DWARFDataExtractor &m_string_table; std::string m_name; }; -}; + static void + ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets); + +protected: + static void + ExtractDIEArray (const DIEInfoArray &die_info_array, + const dw_tag_t tag, + DIEArray &die_offsets); + + static void + ExtractDIEArray (const DIEInfoArray &die_info_array, + const dw_tag_t tag, + const uint32_t qualified_name_hash, + DIEArray &die_offsets); + + static void + ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, + bool return_implementation_only_if_available, + DIEArray &die_offsets); + + static void + ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, + uint32_t type_flag_mask, + uint32_t type_flag_value, + DIEArray &die_offsets); + + static const char * + GetAtomTypeName (uint16_t atom); +}; #endif // SymbolFileDWARF_HashedNameToDIE_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h index 2091a8414f58..24fa7d148cd3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -1,4 +1,4 @@ -//===-- LogChannelDWARF.h --------------------------------------*- C++ -*-===// +//===-- LogChannelDWARF.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,7 +13,6 @@ // C Includes // C++ Includes // Other libraries and framework includes - // Project includes #include "lldb/Core/Log.h" @@ -34,8 +33,7 @@ class LogChannelDWARF : public lldb_private::LogChannel public: LogChannelDWARF (); - virtual - ~LogChannelDWARF (); + ~LogChannelDWARF() override; static void Initialize(); @@ -52,26 +50,26 @@ public: static lldb_private::LogChannel * CreateInstance (); - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; - virtual void - Disable (const char** categories, lldb_private::Stream *feedback_strm); + void + Disable(const char** categories, lldb_private::Stream *feedback_strm) override; void Delete (); - virtual bool - Enable (lldb::StreamSP &log_stream_sp, - uint32_t log_options, - lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc - const char **categories); // The categories to enable within this logging stream, if empty, enable default set + bool + Enable(lldb::StreamSP &log_stream_sp, + uint32_t log_options, + lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc + const char **categories) override; // The categories to enable within this logging stream, if empty, enable default set - virtual void - ListCategories (lldb_private::Stream *strm); + void + ListCategories(lldb_private::Stream *strm) override; static lldb_private::Log * GetLog (); @@ -86,4 +84,4 @@ public: LogIf (uint32_t mask, const char *format, ...); }; -#endif // SymbolFileDWARF_LogChannelDWARF_h_ +#endif // SymbolFileDWARF_LogChannelDWARF_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index c49237b8fbbc..775bb6718b8a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -18,6 +18,7 @@ #include "DWARFDebugInfo.h" #include "DWARFDebugInfoEntry.h" #include "SymbolFileDWARF.h" + using namespace lldb; using namespace lldb_private; @@ -29,9 +30,9 @@ NameToDIE::Finalize() } void -NameToDIE::Insert (const ConstString& name, uint32_t die_offset) +NameToDIE::Insert (const ConstString& name, const DIERef& die_ref) { - m_map.Append(name.GetCString(), die_offset); + m_map.Append(name.GetCString(), die_ref); } size_t @@ -47,17 +48,15 @@ NameToDIE::Find (const RegularExpression& regex, DIEArray &info_array) const } size_t -NameToDIE::FindAllEntriesForCompileUnit (uint32_t cu_offset, - uint32_t cu_end_offset, - DIEArray &info_array) const +NameToDIE::FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const { const size_t initial_size = info_array.size(); const uint32_t size = m_map.GetSize(); for (uint32_t i=0; i<size; ++i) { - const uint32_t die_offset = m_map.GetValueAtIndexUnchecked(i); - if (cu_offset < die_offset && die_offset < cu_end_offset) - info_array.push_back (die_offset); + const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i); + if (cu_offset == die_ref.cu_offset) + info_array.push_back (die_ref); } return info_array.size() - initial_size; } @@ -69,18 +68,29 @@ NameToDIE::Dump (Stream *s) for (uint32_t i=0; i<size; ++i) { const char *cstr = m_map.GetCStringAtIndex(i); - s->Printf("%p: {0x%8.8x} \"%s\"\n", (const void *)cstr, m_map.GetValueAtIndexUnchecked(i), cstr); + const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i); + s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", cstr, die_ref.cu_offset, die_ref.die_offset, cstr); } } void -NameToDIE::ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const +NameToDIE::ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const { const uint32_t size = m_map.GetSize(); for (uint32_t i=0; i<size; ++i) { - if (!callback(m_map.GetCStringAtIndexUnchecked(i), - m_map.GetValueAtIndexUnchecked (i))) + if (!callback(m_map.GetCStringAtIndexUnchecked(i), m_map.GetValueAtIndexUnchecked (i))) break; } } + +void +NameToDIE::Append (const NameToDIE& other) +{ + const uint32_t size = other.m_map.GetSize(); + for (uint32_t i = 0; i < size; ++i) + { + m_map.Append(other.m_map.GetCStringAtIndexUnchecked (i), + other.m_map.GetValueAtIndexUnchecked (i)); + } +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index f9a12736bf9e..7fc66138f51e 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -10,56 +10,53 @@ #ifndef SymbolFileDWARF_NameToDIE_h_ #define SymbolFileDWARF_NameToDIE_h_ -#include "lldb/Core/UniqueCStringMap.h" - #include <functional> +#include "lldb/Core/dwarf.h" +#include "lldb/Core/UniqueCStringMap.h" #include "lldb/lldb-defines.h" +#include "DIERef.h" class SymbolFileDWARF; -typedef std::vector<uint32_t> DIEArray; - class NameToDIE { public: - NameToDIE () : + NameToDIE () : m_map() { } - + ~NameToDIE () { } - + void Dump (lldb_private::Stream *s); void - Insert (const lldb_private::ConstString& name, uint32_t die_offset); + Insert (const lldb_private::ConstString& name, const DIERef& die_ref); + + void + Append (const NameToDIE& other); void Finalize(); size_t - Find (const lldb_private::ConstString &name, - DIEArray &info_array) const; + Find (const lldb_private::ConstString &name, DIEArray &info_array) const; size_t - Find (const lldb_private::RegularExpression& regex, - DIEArray &info_array) const; + Find (const lldb_private::RegularExpression& regex, DIEArray &info_array) const; size_t - FindAllEntriesForCompileUnit (uint32_t cu_offset, - uint32_t cu_end_offset, - DIEArray &info_array) const; + FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const; void - ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const; + ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const; protected: - lldb_private::UniqueCStringMap<uint32_t> m_map; - + lldb_private::UniqueCStringMap<DIERef> m_map; }; #endif // SymbolFileDWARF_NameToDIE_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ea8aedcc2be0..0ed4d05be5c2 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -10,20 +10,6 @@ #include "SymbolFileDWARF.h" // Other libraries and framework includes -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Sema/DeclSpec.h" - #include "llvm/Support/Casting.h" #include "lldb/Core/ArchSpec.h" @@ -39,34 +25,48 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Interpreter/OptionValueFileSpecList.h" +#include "lldb/Interpreter/OptionValueProperties.h" + #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/TypeMap.h" + +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" + +#include "lldb/Target/Language.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Utility/TaskPool.h" +#include "DWARFASTParser.h" #include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugInfoEntry.h" #include "DWARFDebugLine.h" +#include "DWARFDebugMacro.h" #include "DWARFDebugPubnames.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFDIECollection.h" #include "DWARFFormValue.h" -#include "DWARFLocationList.h" #include "LogChannelDWARF.h" +#include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDebugMap.h" #include <map> @@ -83,8 +83,6 @@ #define DEBUG_PRINTF(fmt, ...) #endif -#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1) - using namespace lldb; using namespace lldb_private; @@ -105,18 +103,58 @@ using namespace lldb_private; // return false; //} // -static AccessType -DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility) -{ - switch (dwarf_accessibility) + +namespace { + + PropertyDefinition + g_properties[] = + { + { "comp-dir-symlink-paths" , OptionValue::eTypeFileSpecList, true, 0 , nullptr, nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time." }, + { nullptr , OptionValue::eTypeInvalid , false, 0, nullptr, nullptr, nullptr } + }; + + enum + { + ePropertySymLinkPaths + }; + + + class PluginProperties : public Properties { - case DW_ACCESS_public: return eAccessPublic; - case DW_ACCESS_private: return eAccessPrivate; - case DW_ACCESS_protected: return eAccessProtected; - default: break; + public: + static ConstString + GetSettingName() + { + return SymbolFileDWARF::GetPluginNameStatic(); + } + + PluginProperties() + { + m_collection_sp.reset (new OptionValueProperties(GetSettingName())); + m_collection_sp->Initialize(g_properties); + } + + FileSpecList& + GetSymLinkPaths() + { + OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths); + assert(option_value); + return option_value->GetCurrentValue(); + } + + }; + + typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP; + + static const SymbolFileDWARFPropertiesSP& + GetGlobalPluginProperties() + { + static const auto g_settings_sp(std::make_shared<PluginProperties>()); + return g_settings_sp; } - return eAccessNone; -} + +} // anonymous namespace end + static const char* removeHostnameFromPathname(const char* path_from_dwarf) @@ -125,9 +163,15 @@ removeHostnameFromPathname(const char* path_from_dwarf) { return path_from_dwarf; } - + const char *colon_pos = strchr(path_from_dwarf, ':'); - if (!colon_pos) + if (nullptr == colon_pos) + { + return path_from_dwarf; + } + + const char *slash_pos = strchr(path_from_dwarf, '/'); + if (slash_pos && (slash_pos < colon_pos)) { return path_from_dwarf; } @@ -142,89 +186,42 @@ removeHostnameFromPathname(const char* path_from_dwarf) { return path_from_dwarf; } - + return colon_pos + 1; } -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) - -class DIEStack +static const char* +resolveCompDir(const char* path_from_dwarf) { -public: - - void Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) - { - m_dies.push_back (DIEInfo(cu, die)); - } + if (!path_from_dwarf) + return nullptr; - - void LogDIEs (Log *log, SymbolFileDWARF *dwarf) - { - StreamString log_strm; - const size_t n = m_dies.size(); - log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n); - for (size_t i=0; i<n; i++) - { - DWARFCompileUnit *cu = m_dies[i].cu; - const DWARFDebugInfoEntry *die = m_dies[i].die; - std::string qualified_name; - die->GetQualifiedName(dwarf, cu, qualified_name); - log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", - (uint64_t)i, - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - qualified_name.c_str()); - } - log->PutCString(log_strm.GetData()); - } - void Pop () - { - m_dies.pop_back(); - } - - class ScopedPopper - { - public: - ScopedPopper (DIEStack &die_stack) : - m_die_stack (die_stack), - m_valid (false) - { - } - - void - Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) - { - m_valid = true; - m_die_stack.Push (cu, die); - } - - ~ScopedPopper () - { - if (m_valid) - m_die_stack.Pop(); - } - - - - protected: - DIEStack &m_die_stack; - bool m_valid; - }; + // DWARF2/3 suggests the form hostname:pathname for compilation directory. + // Remove the host part if present. + const char* local_path = removeHostnameFromPathname(path_from_dwarf); + if (!local_path) + return nullptr; + + bool is_symlink = false; + FileSpec local_path_spec(local_path, false); + const auto& file_specs = GetGlobalPluginProperties()->GetSymLinkPaths(); + for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i) + is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), local_path_spec, true); + + if (!is_symlink) + return local_path; + + if (!local_path_spec.IsSymbolicLink()) + return local_path; + + FileSpec resolved_local_path_spec; + const auto error = FileSystem::Readlink(local_path_spec, resolved_local_path_spec); + if (error.Success()) + return resolved_local_path_spec.GetCString(); + + return nullptr; +} -protected: - struct DIEInfo { - DIEInfo (DWARFCompileUnit *c, const DWARFDebugInfoEntry *d) : - cu(c), - die(d) - { - } - DWARFCompileUnit *cu; - const DWARFDebugInfoEntry *die; - }; - typedef std::vector<DIEInfo> Stack; - Stack m_dies; -}; -#endif void SymbolFileDWARF::Initialize() @@ -232,7 +229,21 @@ SymbolFileDWARF::Initialize() LogChannelDWARF::Initialize(); PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), - CreateInstance); + CreateInstance, + DebuggerInitialize); +} + +void +SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) +{ + if (!PluginManager::GetSettingForSymbolFilePlugin(debugger, PluginProperties::GetSettingName())) + { + const bool is_global_setting = true; + PluginManager::CreateSettingForSymbolFilePlugin(debugger, + GetGlobalPluginProperties()->GetValueProperties(), + ConstString ("Properties for the dwarf symbol-file plug-in."), + is_global_setting); + } } void @@ -272,65 +283,61 @@ SymbolFileDWARF::GetTypeList () } void -SymbolFileDWARF::GetTypes (DWARFCompileUnit* cu, - const DWARFDebugInfoEntry *die, +SymbolFileDWARF::GetTypes (const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, TypeSet &type_set) { - if (cu) + if (die) { - if (die) + const dw_offset_t die_offset = die.GetOffset(); + + if (die_offset >= max_die_offset) + return; + + if (die_offset >= min_die_offset) { - const dw_offset_t die_offset = die->GetOffset(); - - if (die_offset >= max_die_offset) - return; + const dw_tag_t tag = die.Tag(); - if (die_offset >= min_die_offset) - { - const dw_tag_t tag = die->Tag(); - - bool add_type = false; + bool add_type = false; - switch (tag) - { - case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break; - case DW_TAG_unspecified_type: - case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break; - case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break; - case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break; - case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break; - case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break; - case DW_TAG_subroutine_type: - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break; - case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break; - case DW_TAG_rvalue_reference_type: - case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break; - case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break; - case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break; - } + switch (tag) + { + case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break; + case DW_TAG_unspecified_type: + case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break; + case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break; + case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break; + case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break; + case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break; + case DW_TAG_subroutine_type: + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break; + case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break; + case DW_TAG_rvalue_reference_type: + case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break; + case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break; + case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break; + } - if (add_type) + if (add_type) + { + const bool assert_not_being_parsed = true; + Type *type = ResolveTypeUID (die, assert_not_being_parsed); + if (type) { - const bool assert_not_being_parsed = true; - Type *type = ResolveTypeUID (cu, die, assert_not_being_parsed); - if (type) - { - if (type_set.find(type) == type_set.end()) - type_set.insert(type); - } + if (type_set.find(type) == type_set.end()) + type_set.insert(type); } } - - for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); - child_die != NULL; - child_die = child_die->GetSibling()) - { - GetTypes (cu, child_die, min_die_offset, max_die_offset, type_mask, type_set); - } + } + + for (DWARFDIE child_die = die.GetFirstChild(); + child_die.IsValid(); + child_die = child_die.GetSibling()) + { + GetTypes (child_die, min_die_offset, max_die_offset, type_mask, type_set); } } } @@ -353,8 +360,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope, dwarf_cu = GetDWARFCompileUnit(comp_unit); if (dwarf_cu == 0) return 0; - GetTypes (dwarf_cu, - dwarf_cu->DIE(), + GetTypes (dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextCompileUnitOffset(), type_mask, @@ -371,8 +377,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope, dwarf_cu = info->GetCompileUnitAtIndex(cu_idx); if (dwarf_cu) { - GetTypes (dwarf_cu, - dwarf_cu->DIE(), + GetTypes (dwarf_cu->DIE(), 0, UINT32_MAX, type_mask, @@ -381,76 +386,15 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope, } } } -// if (m_using_apple_tables) -// { -// DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get(); -// if (apple_types) -// { -// apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool { -// -// for (auto die_info: die_info_array) -// { -// bool add_type = TagMatchesTypeMask (type_mask, 0); -// if (!add_type) -// { -// dw_tag_t tag = die_info.tag; -// if (tag == 0) -// { -// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL); -// tag = die->Tag(); -// } -// add_type = TagMatchesTypeMask (type_mask, tag); -// } -// if (add_type) -// { -// Type *type = ResolveTypeUID(die_info.offset); -// -// if (type_set.find(type) == type_set.end()) -// type_set.insert(type); -// } -// } -// return true; // Keep iterating -// }); -// } -// } -// else -// { -// if (!m_indexed) -// Index (); -// -// m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool { -// -// bool add_type = TagMatchesTypeMask (type_mask, 0); -// -// if (!add_type) -// { -// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL); -// if (die) -// { -// const dw_tag_t tag = die->Tag(); -// add_type = TagMatchesTypeMask (type_mask, tag); -// } -// } -// -// if (add_type) -// { -// Type *type = ResolveTypeUID(die_offset); -// -// if (type_set.find(type) == type_set.end()) -// type_set.insert(type); -// } -// return true; // Keep iterating -// }); -// } - - std::set<ClangASTType> clang_type_set; + + std::set<CompilerType> compiler_type_set; size_t num_types_added = 0; for (Type *type : type_set) { - ClangASTType clang_type = type->GetClangForwardType(); - if (clang_type_set.find(clang_type) == clang_type_set.end()) + CompilerType compiler_type = type->GetForwardCompilerType (); + if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) { - clang_type_set.insert(clang_type); + compiler_type_set.insert(compiler_type); type_list.Insert (type->shared_from_this()); ++num_types_added; } @@ -463,13 +407,13 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope, // Gets the first parent that is a lexical block, function or inlined // subroutine, or compile unit. //---------------------------------------------------------------------- -static const DWARFDebugInfoEntry * -GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die) +DWARFDIE +SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { - const DWARFDebugInfoEntry *die; - for (die = child_die->GetParent(); die != NULL; die = die->GetParent()) + DWARFDIE die; + for (die = child_die.GetParent(); die; die = die.GetParent()) { - dw_tag_t tag = die->Tag(); + dw_tag_t tag = die.Tag(); switch (tag) { @@ -480,7 +424,7 @@ GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die) return die; } } - return NULL; + return DWARFDIE(); } @@ -489,13 +433,12 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) : UserID (0), // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID m_debug_map_module_wp (), m_debug_map_symfile (NULL), - m_clang_tu_decl (NULL), - m_flags(), m_data_debug_abbrev (), m_data_debug_aranges (), m_data_debug_frame (), m_data_debug_info (), m_data_debug_line (), + m_data_debug_macro (), m_data_debug_loc (), m_data_debug_ranges (), m_data_debug_str (), @@ -518,7 +461,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) : m_type_index(), m_namespace_index(), m_indexed (false), - m_is_external_ast_source (false), m_using_apple_tables (false), m_fetched_external_modules (false), m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate), @@ -529,12 +471,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) : SymbolFileDWARF::~SymbolFileDWARF() { - if (m_is_external_ast_source) - { - ModuleSP module_sp (m_obj_file->GetModule()); - if (module_sp) - module_sp->GetClangASTContext().RemoveExternalSource (); - } } static const ConstString & @@ -552,36 +488,31 @@ SymbolFileDWARF::GetUniqueDWARFASTTypeMap () return m_unique_ast_type_map; } -ClangASTContext & -SymbolFileDWARF::GetClangASTContext () +TypeSystem * +SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language) { - if (GetDebugMapSymfile ()) - return m_debug_map_symfile->GetClangASTContext (); - - ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); - if (!m_is_external_ast_source) + SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); + TypeSystem *type_system; + if (debug_map_symfile) { - m_is_external_ast_source = true; - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap ( - new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl, - SymbolFileDWARF::CompleteObjCInterfaceDecl, - SymbolFileDWARF::FindExternalVisibleDeclsByName, - SymbolFileDWARF::LayoutRecordType, - this)); - ast.SetExternalSource (ast_source_ap); + type_system = debug_map_symfile->GetTypeSystemForLanguage(language); } - return ast; + else + { + type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); + if (type_system) + type_system->SetSymbolFile(this); + } + return type_system; } void SymbolFileDWARF::InitializeObject() { - // Install our external AST source callbacks so we can complete Clang types. ModuleSP module_sp (m_obj_file->GetModule()); if (module_sp) { const SectionList *section_list = module_sp->GetSectionList(); - const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get(); // Memory map the DWARF mach-o segment so we have everything mmap'ed @@ -589,19 +520,24 @@ SymbolFileDWARF::InitializeObject() if (section) m_obj_file->MemoryMapSectionData(section, m_dwarf_data); } + get_apple_names_data(); - if (m_data_apple_names.GetByteSize() > 0) + if (m_data_apple_names.m_data.GetByteSize() > 0) { - m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names")); + m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data, + get_debug_str_data(), + ".apple_names")); if (m_apple_names_ap->IsValid()) m_using_apple_tables = true; else m_apple_names_ap.reset(); } get_apple_types_data(); - if (m_data_apple_types.GetByteSize() > 0) + if (m_data_apple_types.m_data.GetByteSize() > 0) { - m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types")); + m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data, + get_debug_str_data(), + ".apple_types")); if (m_apple_types_ap->IsValid()) m_using_apple_tables = true; else @@ -609,9 +545,11 @@ SymbolFileDWARF::InitializeObject() } get_apple_namespaces_data(); - if (m_data_apple_namespaces.GetByteSize() > 0) + if (m_data_apple_namespaces.m_data.GetByteSize() > 0) { - m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces")); + m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data, + get_debug_str_data(), + ".apple_namespaces")); if (m_apple_namespaces_ap->IsValid()) m_using_apple_tables = true; else @@ -619,9 +557,11 @@ SymbolFileDWARF::InitializeObject() } get_apple_objc_data(); - if (m_data_apple_objc.GetByteSize() > 0) + if (m_data_apple_objc.m_data.GetByteSize() > 0) { - m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc")); + m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data, + get_debug_str_data(), + ".apple_objc")); if (m_apple_objc_ap->IsValid()) m_using_apple_tables = true; else @@ -663,46 +603,10 @@ SymbolFileDWARF::CalculateAbilities () section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get(); if (section) debug_abbrev_file_size = section->GetFileSize(); - else - m_flags.Set (flagsGotDebugAbbrevData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get(); - if (!section) - m_flags.Set (flagsGotDebugArangesData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get(); - if (!section) - m_flags.Set (flagsGotDebugFrameData); section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get(); if (section) debug_line_file_size = section->GetFileSize(); - else - m_flags.Set (flagsGotDebugLineData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get(); - if (!section) - m_flags.Set (flagsGotDebugLocData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get(); - if (!section) - m_flags.Set (flagsGotDebugMacInfoData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get(); - if (!section) - m_flags.Set (flagsGotDebugPubNamesData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get(); - if (!section) - m_flags.Set (flagsGotDebugPubTypesData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get(); - if (!section) - m_flags.Set (flagsGotDebugRangesData); - - section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get(); - if (!section) - m_flags.Set (flagsGotDebugStrData); } else { @@ -737,104 +641,128 @@ SymbolFileDWARF::CalculateAbilities () } const DWARFDataExtractor& -SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data) +SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment) { - if (m_flags.IsClear (got_flag)) + std::call_once(data_segment.m_flag, + &SymbolFileDWARF::LoadSectionData, + this, + sect_type, + std::ref(data_segment.m_data)); + return data_segment.m_data; +} + +void +SymbolFileDWARF::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data) +{ + ModuleSP module_sp (m_obj_file->GetModule()); + const SectionList *section_list = module_sp->GetSectionList(); + if (section_list) { - ModuleSP module_sp (m_obj_file->GetModule()); - m_flags.Set (got_flag); - const SectionList *section_list = module_sp->GetSectionList(); - if (section_list) + SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); + if (section_sp) { - SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); - if (section_sp) + // See if we memory mapped the DWARF segment? + if (m_dwarf_data.GetByteSize()) { - // See if we memory mapped the DWARF segment? - if (m_dwarf_data.GetByteSize()) - { - data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize()); - } - else - { - if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0) - data.Clear(); - } + data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize()); + } + else + { + if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0) + data.Clear(); } } } - return data; } const DWARFDataExtractor& SymbolFileDWARF::get_debug_abbrev_data() { - return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev); + return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_addr_data() +{ + return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_aranges_data() { - return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges); + return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_frame_data() { - return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame); + return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_info_data() { - return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info); + return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_line_data() { - return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line); + return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_macro_data() +{ + return GetCachedSectionData (eSectionTypeDWARFDebugMacro, m_data_debug_macro); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_loc_data() { - return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc); + return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_ranges_data() { - return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges); + return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges); } const DWARFDataExtractor& SymbolFileDWARF::get_debug_str_data() { - return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str); + return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_str_offsets_data() +{ + return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets); } const DWARFDataExtractor& SymbolFileDWARF::get_apple_names_data() { - return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names); + return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names); } const DWARFDataExtractor& SymbolFileDWARF::get_apple_types_data() { - return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types); + return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types); } const DWARFDataExtractor& SymbolFileDWARF::get_apple_namespaces_data() { - return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces); + return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces); } const DWARFDataExtractor& SymbolFileDWARF::get_apple_objc_data() { - return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc); + return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc); } @@ -889,6 +817,9 @@ SymbolFileDWARF::DebugInfo() const DWARFCompileUnit* SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { + if (!comp_unit) + return nullptr; + DWARFDebugInfo* info = DebugInfo(); if (info) { @@ -900,7 +831,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) // TODO: modify to support LTO .o files where each .o file might // have multiple DW_TAG_compile_unit tags. - DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get(); + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0); if (dwarf_cu && dwarf_cu->GetUserData() == NULL) dwarf_cu->SetUserData(comp_unit); return dwarf_cu; @@ -910,7 +841,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) // Just a normal DWARF file whose user ID for the compile unit is // the DWARF offset itself - DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()); if (dwarf_cu && dwarf_cu->GetUserData() == NULL) dwarf_cu->SetUserData(comp_unit); return dwarf_cu; @@ -958,7 +889,11 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) } else { - if (GetDebugMapSymfile ()) + if (dwarf_cu->GetSymbolFileDWARF() != this) + { + return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx); + } + else if (GetDebugMapSymfile ()) { // Let the debug map create the compile unit cu_sp = m_debug_map_symfile->GetCompileUnit(this); @@ -969,20 +904,18 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) ModuleSP module_sp (m_obj_file->GetModule()); if (module_sp) { - const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly (); + const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly (); if (cu_die) { - FileSpec cu_file_spec{cu_die->GetName(this, dwarf_cu), false}; + FileSpec cu_file_spec{cu_die.GetName(), false}; if (cu_file_spec) { // If we have a full path to the compile unit, we don't need to resolve // the file. This can be expensive e.g. when the source files are NFS mounted. if (cu_file_spec.IsRelative()) { - // DWARF2/3 suggests the form hostname:pathname for compilation directory. - // Remove the host part if present. - const char *cu_comp_dir{cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, nullptr)}; - cu_file_spec.PrependPathComponent(removeHostnameFromPathname(cu_comp_dir)); + const char *cu_comp_dir{cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)}; + cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir)); } std::string remapped_file; @@ -990,13 +923,15 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) cu_file_spec.SetFile(remapped_file, false); } - LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0)); + LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); + bool is_optimized = dwarf_cu->GetIsOptimized (); cu_sp.reset(new CompileUnit (module_sp, dwarf_cu, cu_file_spec, - MakeUserID(dwarf_cu->GetOffset()), - cu_language)); + dwarf_cu->GetID(), + cu_language, + is_optimized)); if (cu_sp) { // If we just created a compile unit with an invalid file spec, try and get the @@ -1053,137 +988,20 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) } Function * -SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die) +SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFDIE &die) { - DWARFDebugRanges::RangeList func_ranges; - const char *name = NULL; - const char *mangled = NULL; - int decl_file = 0; - int decl_line = 0; - int decl_column = 0; - int call_file = 0; - int call_line = 0; - int call_column = 0; - DWARFExpression frame_base; - - assert (die->Tag() == DW_TAG_subprogram); - - if (die->Tag() != DW_TAG_subprogram) - return NULL; - - if (die->GetDIENamesAndRanges (this, - dwarf_cu, - name, - mangled, - func_ranges, - decl_file, - decl_line, - decl_column, - call_file, - call_line, - call_column, - &frame_base)) + if (die.IsValid()) { - // Union of all ranges in the function DIE (if the function is discontiguous) - AddressRange func_range; - lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0); - lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0); - if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) - { - ModuleSP module_sp (m_obj_file->GetModule()); - func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList()); - if (func_range.GetBaseAddress().IsValid()) - func_range.SetByteSize(highest_func_addr - lowest_func_addr); - } + TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - if (func_range.GetBaseAddress().IsValid()) + if (type_system) { - Mangled func_name; - if (mangled) - func_name.SetValue(ConstString(mangled), true); - else if (die->GetParent()->Tag() == DW_TAG_compile_unit && - LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()) && - name && strcmp(name, "main") != 0) - { - // If the mangled name is not present in the DWARF, generate the demangled name - // using the decl context. We skip if the function is "main" as its name is - // never mangled. - bool is_static = false; - bool is_variadic = false; - unsigned type_quals = 0; - std::vector<ClangASTType> param_types; - std::vector<clang::ParmVarDecl*> param_decls; - const DWARFDebugInfoEntry *decl_ctx_die = NULL; - DWARFDeclContext decl_ctx; - StreamString sstr; - - die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx); - sstr << decl_ctx.GetQualifiedName(); - - clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(dwarf_cu, - die, - &decl_ctx_die); - ParseChildParameters(sc, - containing_decl_ctx, - dwarf_cu, - die, - true, - is_static, - is_variadic, - param_types, - param_decls, - type_quals); - sstr << "("; - for (size_t i = 0; i < param_types.size(); i++) - { - if (i > 0) - sstr << ", "; - sstr << param_types[i].GetTypeName(); - } - if (is_variadic) - sstr << ", ..."; - sstr << ")"; - if (type_quals & clang::Qualifiers::Const) - sstr << " const"; - - func_name.SetValue(ConstString(sstr.GetData()), false); - } - else - func_name.SetValue(ConstString(name), false); - - FunctionSP func_sp; - std::unique_ptr<Declaration> decl_ap; - if (decl_file != 0 || decl_line != 0 || decl_column != 0) - decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), - decl_line, - decl_column)); - - // Supply the type _only_ if it has already been parsed - Type *func_type = m_die_to_type.lookup (die); - - assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); - - if (FixupAddress (func_range.GetBaseAddress())) - { - const user_id_t func_user_id = MakeUserID(die->GetOffset()); - func_sp.reset(new Function (sc.comp_unit, - MakeUserID(func_user_id), // UserID is the DIE offset - MakeUserID(func_user_id), - func_name, - func_type, - func_range)); // first address range - - if (func_sp.get() != NULL) - { - if (frame_base.IsValid()) - func_sp->GetFrameBaseExpression() = frame_base; - sc.comp_unit->AddFunction(func_sp); - return func_sp.get(); - } - } + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->ParseFunctionFromDWARF(sc, die); } } - return NULL; + return nullptr; } bool @@ -1203,12 +1021,9 @@ SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc) assert (sc.comp_unit); DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (dwarf_cu) - { - const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly(); - if (die) - return DWARFCompileUnit::LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0)); - } - return eLanguageTypeUnknown; + return dwarf_cu->GetLanguageType(); + else + return eLanguageTypeUnknown; } size_t @@ -1224,10 +1039,10 @@ SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) size_t func_idx; for (func_idx = 0; func_idx < num_functions; ++func_idx) { - const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx); - if (sc.comp_unit->FindFunctionByUID (MakeUserID(die->GetOffset())).get() == NULL) + DWARFDIE die = function_dies.GetDIEAtIndex(func_idx); + if (sc.comp_unit->FindFunctionByUID (die.GetID()).get() == NULL) { - if (ParseCompileUnitFunction(sc, dwarf_cu, die)) + if (ParseCompileUnitFunction(sc, die)) ++functions_added; } } @@ -1243,17 +1058,13 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (dwarf_cu) { - const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly(); + const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly(); if (cu_die) { - const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL); - - // DWARF2/3 suggests the form hostname:pathname for compilation directory. - // Remove the host part if present. - cu_comp_dir = removeHostnameFromPathname(cu_comp_dir); + const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)); - dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET); + const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET); // All file indexes in DWARF are one based and a file of index zero is // supposed to be the compile unit itself. @@ -1275,9 +1086,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage())) { UpdateExternalModuleListIfNeeded(); - for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules) + for (const auto &pair : m_external_type_modules) { - imported_modules.push_back(external_type_module.second.m_name); + imported_modules.push_back(pair.first); } } } @@ -1288,6 +1099,7 @@ struct ParseDWARFLineTableCallbackInfo { LineTable* line_table; std::unique_ptr<LineSequence> sequence_ap; + lldb::addr_t addr_mask; }; //---------------------------------------------------------------------- @@ -1317,7 +1129,7 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta assert(info->sequence_ap.get()); } line_table->AppendLineEntryToSequence (info->sequence_ap.get(), - state.address, + state.address & info->addr_mask, state.line, state.column, state.file, @@ -1346,10 +1158,10 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (dwarf_cu) { - const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); + const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); if (dwarf_cu_die) { - const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET); + const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET); if (cu_line_offset != DW_INVALID_OFFSET) { std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit)); @@ -1357,6 +1169,28 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) { ParseDWARFLineTableCallbackInfo info; info.line_table = line_table_ap.get(); + + /* + * MIPS: + * The SymbolContext may not have a valid target, thus we may not be able + * to call Address::GetOpcodeLoadAddress() which would clear the bit #0 + * for MIPS. Use ArchSpec to clear the bit #0. + */ + ArchSpec arch; + GetObjectFile()->GetArchitecture(arch); + switch (arch.GetMachine()) + { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + info.addr_mask = ~((lldb::addr_t)1); + break; + default: + info.addr_mask = ~((lldb::addr_t)0); + break; + } + lldb::offset_t offset = cu_line_offset; DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info); if (m_debug_map_symfile) @@ -1379,21 +1213,63 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) return false; } +lldb_private::DebugMacrosSP +SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) +{ + auto iter = m_debug_macros_map.find(*offset); + if (iter != m_debug_macros_map.end()) + return iter->second; + + const DWARFDataExtractor &debug_macro_data = get_debug_macro_data(); + if (debug_macro_data.GetByteSize() == 0) + return DebugMacrosSP(); + + lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros()); + m_debug_macros_map[*offset] = debug_macros_sp; + + const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset); + DWARFDebugMacroEntry::ReadMacroEntries( + debug_macro_data, get_debug_str_data(), header.OffsetIs64Bit(), offset, this, debug_macros_sp); + + return debug_macros_sp; +} + +bool +SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc) +{ + assert (sc.comp_unit); + + DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + if (dwarf_cu == nullptr) + return false; + + const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); + if (!dwarf_cu_die) + return false; + + lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + return false; + + sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); + + return true; +} + size_t -SymbolFileDWARF::ParseFunctionBlocks -( - const SymbolContext& sc, - Block *parent_block, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - addr_t subprogram_low_pc, - uint32_t depth -) +SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc, + Block *parent_block, + const DWARFDIE &orig_die, + addr_t subprogram_low_pc, + uint32_t depth) { size_t blocks_added = 0; - while (die != NULL) + DWARFDIE die = orig_die; + while (die) { - dw_tag_t tag = die->Tag(); + dw_tag_t tag = die.Tag(); switch (tag) { @@ -1415,11 +1291,11 @@ SymbolFileDWARF::ParseFunctionBlocks } else { - BlockSP block_sp(new Block (MakeUserID(die->GetOffset()))); + BlockSP block_sp(new Block (die.GetID())); parent_block->AddChild(block_sp); block = block_sp.get(); } - DWARFDebugRanges::RangeList ranges; + DWARFRangeList ranges; const char *name = NULL; const char *mangled_name = NULL; @@ -1429,13 +1305,11 @@ SymbolFileDWARF::ParseFunctionBlocks int call_file = 0; int call_line = 0; int call_column = 0; - if (die->GetDIENamesAndRanges (this, - dwarf_cu, - name, - mangled_name, - ranges, - decl_file, decl_line, decl_column, - call_file, call_line, call_column)) + if (die.GetDIENamesAndRanges (name, + mangled_name, + ranges, + decl_file, decl_line, decl_column, + call_file, call_line, call_column, nullptr)) { if (tag == DW_TAG_subprogram) { @@ -1461,7 +1335,7 @@ SymbolFileDWARF::ParseFunctionBlocks const size_t num_ranges = ranges.GetSize(); for (size_t i = 0; i<num_ranges; ++i) { - const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i); + const DWARFRangeList::Entry &range = ranges.GetEntryRef (i); const addr_t range_base = range.GetRangeBase(); if (range_base >= subprogram_low_pc) block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize())); @@ -1493,12 +1367,11 @@ SymbolFileDWARF::ParseFunctionBlocks ++blocks_added; - if (die->HasChildren()) + if (die.HasChildren()) { blocks_added += ParseFunctionBlocks (sc, block, - dwarf_cu, - die->GetFirstChild(), + die.GetFirstChild(), subprogram_low_pc, depth + 1); } @@ -1514,278 +1387,21 @@ SymbolFileDWARF::ParseFunctionBlocks // DW_TAG_subprogram DIE if (depth == 0) - die = NULL; + die.Clear(); else - die = die->GetSibling(); + die = die.GetSibling(); } return blocks_added; } bool -SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - ClangASTContext::TemplateParameterInfos &template_param_infos) -{ - const dw_tag_t tag = die->Tag(); - - switch (tag) - { - case DW_TAG_template_type_parameter: - case DW_TAG_template_value_parameter: - { - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes (this, - dwarf_cu, - fixed_form_sizes, - attributes); - const char *name = NULL; - Type *lldb_type = NULL; - ClangASTType clang_type; - uint64_t uval64 = 0; - bool uval64_valid = false; - if (num_attributes > 0) - { - DWARFFormValue form_value; - for (size_t i=0; i<num_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - - switch (attr) - { - case DW_AT_name: - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - name = form_value.AsCString(&get_debug_str_data()); - break; - - case DW_AT_type: - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - const dw_offset_t type_die_offset = form_value.Reference(); - lldb_type = ResolveTypeUID(type_die_offset); - if (lldb_type) - clang_type = lldb_type->GetClangForwardType(); - } - break; - - case DW_AT_const_value: - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - uval64_valid = true; - uval64 = form_value.Unsigned(); - } - break; - default: - break; - } - } - - clang::ASTContext *ast = GetClangASTContext().getASTContext(); - if (!clang_type) - clang_type = GetClangASTContext().GetBasicType(eBasicTypeVoid); - - if (clang_type) - { - bool is_signed = false; - if (name && name[0]) - template_param_infos.names.push_back(name); - else - template_param_infos.names.push_back(NULL); - - if (tag == DW_TAG_template_value_parameter && - lldb_type != NULL && - clang_type.IsIntegerType (is_signed) && - uval64_valid) - { - llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed); - template_param_infos.args.push_back (clang::TemplateArgument (*ast, - llvm::APSInt(apint), - clang_type.GetQualType())); - } - else - { - template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType())); - } - } - else - { - return false; - } - - } - } - return true; - - default: - break; - } - return false; -} - -bool -SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - ClangASTContext::TemplateParameterInfos &template_param_infos) -{ - - if (parent_die == NULL) - return false; - - Args template_parameter_names; - for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); - die != NULL; - die = die->GetSibling()) - { - const dw_tag_t tag = die->Tag(); - - switch (tag) - { - case DW_TAG_template_type_parameter: - case DW_TAG_template_value_parameter: - ParseTemplateDIE (dwarf_cu, die, template_param_infos); - break; - - default: - break; - } - } - if (template_param_infos.args.empty()) - return false; - return template_param_infos.args.size() == template_param_infos.names.size(); -} - -clang::ClassTemplateDecl * -SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *parent_name, - int tag_decl_kind, - const ClangASTContext::TemplateParameterInfos &template_param_infos) -{ - if (template_param_infos.IsValid()) - { - std::string template_basename(parent_name); - template_basename.erase (template_basename.find('<')); - ClangASTContext &ast = GetClangASTContext(); - - return ast.CreateClassTemplateDecl (decl_ctx, - access_type, - template_basename.c_str(), - tag_decl_kind, - template_param_infos); - } - return NULL; -} - -class SymbolFileDWARF::DelayedAddObjCClassProperty -{ -public: - DelayedAddObjCClassProperty - ( - const ClangASTType &class_opaque_type, - const char *property_name, - const ClangASTType &property_opaque_type, // The property type is only required if you don't have an ivar decl - clang::ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - const ClangASTMetadata *metadata - ) : - m_class_opaque_type (class_opaque_type), - m_property_name (property_name), - m_property_opaque_type (property_opaque_type), - m_ivar_decl (ivar_decl), - m_property_setter_name (property_setter_name), - m_property_getter_name (property_getter_name), - m_property_attributes (property_attributes) - { - if (metadata != NULL) - { - m_metadata_ap.reset(new ClangASTMetadata()); - *m_metadata_ap = *metadata; - } - } - - DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs) - { - *this = rhs; - } - - DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs) - { - m_class_opaque_type = rhs.m_class_opaque_type; - m_property_name = rhs.m_property_name; - m_property_opaque_type = rhs.m_property_opaque_type; - m_ivar_decl = rhs.m_ivar_decl; - m_property_setter_name = rhs.m_property_setter_name; - m_property_getter_name = rhs.m_property_getter_name; - m_property_attributes = rhs.m_property_attributes; - - if (rhs.m_metadata_ap.get()) - { - m_metadata_ap.reset (new ClangASTMetadata()); - *m_metadata_ap = *rhs.m_metadata_ap; - } - return *this; - } - - bool - Finalize() - { - return m_class_opaque_type.AddObjCClassProperty (m_property_name, - m_property_opaque_type, - m_ivar_decl, - m_property_setter_name, - m_property_getter_name, - m_property_attributes, - m_metadata_ap.get()); - } -private: - ClangASTType m_class_opaque_type; - const char *m_property_name; - ClangASTType m_property_opaque_type; - clang::ObjCIvarDecl *m_ivar_decl; - const char *m_property_setter_name; - const char *m_property_getter_name; - uint32_t m_property_attributes; - std::unique_ptr<ClangASTMetadata> m_metadata_ap; -}; - -struct BitfieldInfo -{ - uint64_t bit_size; - uint64_t bit_offset; - - BitfieldInfo () : - bit_size (LLDB_INVALID_ADDRESS), - bit_offset (LLDB_INVALID_ADDRESS) - { - } - - void - Clear() - { - bit_size = LLDB_INVALID_ADDRESS; - bit_offset = LLDB_INVALID_ADDRESS; - } - - bool IsValid () - { - return (bit_size != LLDB_INVALID_ADDRESS) && - (bit_offset != LLDB_INVALID_ADDRESS); - } -}; - - -bool -SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die) +SymbolFileDWARF::ClassOrStructIsVirtual (const DWARFDIE &parent_die) { if (parent_die) { - for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) + for (DWARFDIE die = parent_die.GetFirstChild(); die; die = die.GetSibling()) { - dw_tag_t tag = die->Tag(); + dw_tag_t tag = die.Tag(); bool check_virtuality = false; switch (tag) { @@ -1798,7 +1414,7 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu, } if (check_virtuality) { - if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0) + if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0) return true; } } @@ -1806,602 +1422,79 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu, return false; } -size_t -SymbolFileDWARF::ParseChildMembers -( - const SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - ClangASTType &class_clang_type, - const LanguageType class_language, - std::vector<clang::CXXBaseSpecifier *>& base_classes, - std::vector<int>& member_accessibilities, - DWARFDIECollection& member_function_dies, - DelayedPropertyList& delayed_properties, - AccessType& default_accessibility, - bool &is_a_class, - LayoutInfo &layout_info -) +void +SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx) { - if (parent_die == NULL) - return 0; + TypeSystem *type_system = decl_ctx.GetTypeSystem(); + DWARFASTParser *ast_parser = type_system->GetDWARFParser(); + std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx); - size_t count = 0; - const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - uint32_t member_idx = 0; - BitfieldInfo last_field_info; - ModuleSP module = GetObjectFile()->GetModule(); + for (DWARFDIE decl_ctx_die : decl_ctx_die_list) + for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling()) + ast_parser->GetDeclForUIDFromDWARF(decl); +} - for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) +CompilerDecl +SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid) +{ + if (UserIDMatches(type_uid)) { - dw_tag_t tag = die->Tag(); - - switch (tag) + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) { - case DW_TAG_member: - case DW_TAG_APPLE_property: - { - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes (this, - dwarf_cu, - fixed_form_sizes, - attributes); - if (num_attributes > 0) - { - Declaration decl; - //DWARFExpression location; - const char *name = NULL; - const char *prop_name = NULL; - const char *prop_getter_name = NULL; - const char *prop_setter_name = NULL; - uint32_t prop_attributes = 0; - - - bool is_artificial = false; - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; - AccessType accessibility = eAccessNone; - uint32_t member_byte_offset = UINT32_MAX; - size_t byte_size = 0; - size_t bit_offset = 0; - size_t bit_size = 0; - bool is_external = false; // On DW_TAG_members, this means the member is static - uint32_t i; - for (i=0; i<num_attributes && !is_artificial; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: encoding_uid = form_value.Reference(); break; - case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break; - case DW_AT_bit_size: bit_size = form_value.Unsigned(); break; - case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; - case DW_AT_data_member_location: - if (form_value.BlockData()) - { - Value initialValue(0); - Value memberOffset(0); - const DWARFDataExtractor& debug_info_data = get_debug_info_data(); - uint32_t block_length = form_value.Unsigned(); - uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate(NULL, // ExecutionContext * - NULL, // ClangExpressionVariableList * - NULL, // ClangExpressionDeclMap * - NULL, // RegisterContext * - module, - debug_info_data, - block_offset, - block_length, - eRegisterKindDWARF, - &initialValue, - memberOffset, - NULL)) - { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); - } - } - else - { - // With DWARF 3 and later, if the value is an integer constant, - // this form value is the offset in bytes from the beginning - // of the containing entity. - member_byte_offset = form_value.Unsigned(); - } - break; - - case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break; - case DW_AT_artificial: is_artificial = form_value.Boolean(); break; - case DW_AT_APPLE_property_name: prop_name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break; - case DW_AT_external: is_external = form_value.Boolean(); break; - - default: - case DW_AT_declaration: - case DW_AT_description: - case DW_AT_mutable: - case DW_AT_visibility: - case DW_AT_sibling: - break; - } - } - } - - if (prop_name) - { - ConstString fixed_getter; - ConstString fixed_setter; - - // Check if the property getter/setter were provided as full - // names. We want basenames, so we extract them. - - if (prop_getter_name && prop_getter_name[0] == '-') - { - ObjCLanguageRuntime::MethodName prop_getter_method(prop_getter_name, true); - prop_getter_name = prop_getter_method.GetSelector().GetCString(); - } - - if (prop_setter_name && prop_setter_name[0] == '-') - { - ObjCLanguageRuntime::MethodName prop_setter_method(prop_setter_name, true); - prop_setter_name = prop_setter_method.GetSelector().GetCString(); - } - - // If the names haven't been provided, they need to be - // filled in. - - if (!prop_getter_name) - { - prop_getter_name = prop_name; - } - if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly)) - { - StreamString ss; - - ss.Printf("set%c%s:", - toupper(prop_name[0]), - &prop_name[1]); - - fixed_setter.SetCString(ss.GetData()); - prop_setter_name = fixed_setter.GetCString(); - } - } - - // Clang has a DWARF generation bug where sometimes it - // represents fields that are references with bad byte size - // and bit size/offset information such as: - // - // DW_AT_byte_size( 0x00 ) - // DW_AT_bit_size( 0x40 ) - // DW_AT_bit_offset( 0xffffffffffffffc0 ) - // - // So check the bit offset to make sure it is sane, and if - // the values are not sane, remove them. If we don't do this - // then we will end up with a crash if we try to use this - // type in an expression when clang becomes unhappy with its - // recycled debug info. - - if (bit_offset > 128) - { - bit_size = 0; - bit_offset = 0; - } - - // FIXME: Make Clang ignore Objective-C accessibility for expressions - if (class_language == eLanguageTypeObjC || - class_language == eLanguageTypeObjC_plus_plus) - accessibility = eAccessNone; - - if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name)) - { - // Not all compilers will mark the vtable pointer - // member as artificial (llvm-gcc). We can't have - // the virtual members in our classes otherwise it - // throws off all child offsets since we end up - // having and extra pointer sized member in our - // class layouts. - is_artificial = true; - } - - // Handle static members - if (is_external && member_byte_offset == UINT32_MAX) - { - Type *var_type = ResolveTypeUID(encoding_uid); - - if (var_type) - { - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - class_clang_type.AddVariableToRecordType (name, - var_type->GetClangLayoutType(), - accessibility); - } - break; - } - - if (is_artificial == false) - { - Type *member_type = ResolveTypeUID(encoding_uid); - - clang::FieldDecl *field_decl = NULL; - if (tag == DW_TAG_member) - { - if (member_type) - { - if (accessibility == eAccessNone) - accessibility = default_accessibility; - member_accessibilities.push_back(accessibility); - - uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); - if (bit_size > 0) - { - - BitfieldInfo this_field_info; - this_field_info.bit_offset = field_bit_offset; - this_field_info.bit_size = bit_size; - - ///////////////////////////////////////////////////////////// - // How to locate a field given the DWARF debug information - // - // AT_byte_size indicates the size of the word in which the - // bit offset must be interpreted. - // - // AT_data_member_location indicates the byte offset of the - // word from the base address of the structure. - // - // AT_bit_offset indicates how many bits into the word - // (according to the host endianness) the low-order bit of - // the field starts. AT_bit_offset can be negative. - // - // AT_bit_size indicates the size of the field in bits. - ///////////////////////////////////////////////////////////// - - if (byte_size == 0) - byte_size = member_type->GetByteSize(); - - if (GetObjectFile()->GetByteOrder() == eByteOrderLittle) - { - this_field_info.bit_offset += byte_size * 8; - this_field_info.bit_offset -= (bit_offset + bit_size); - } - else - { - this_field_info.bit_offset += bit_offset; - } - - // Update the field bit offset we will report for layout - field_bit_offset = this_field_info.bit_offset; - - // If the member to be emitted did not start on a character boundary and there is - // empty space between the last field and this one, then we need to emit an - // anonymous member filling up the space up to its start. There are three cases - // here: - // - // 1 If the previous member ended on a character boundary, then we can emit an - // anonymous member starting at the most recent character boundary. - // - // 2 If the previous member did not end on a character boundary and the distance - // from the end of the previous member to the current member is less than a - // word width, then we can emit an anonymous member starting right after the - // previous member and right before this member. - // - // 3 If the previous member did not end on a character boundary and the distance - // from the end of the previous member to the current member is greater than - // or equal a word width, then we act as in Case 1. - - const uint64_t character_width = 8; - const uint64_t word_width = 32; - - // Objective-C has invalid DW_AT_bit_offset values in older versions - // of clang, so we have to be careful and only insert unnamed bitfields - // if we have a new enough clang. - bool detect_unnamed_bitfields = true; - - if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus) - detect_unnamed_bitfields = dwarf_cu->Supports_unnamed_objc_bitfields (); - - if (detect_unnamed_bitfields) - { - BitfieldInfo anon_field_info; - - if ((this_field_info.bit_offset % character_width) != 0) // not char aligned - { - uint64_t last_field_end = 0; - - if (last_field_info.IsValid()) - last_field_end = last_field_info.bit_offset + last_field_info.bit_size; - - if (this_field_info.bit_offset != last_field_end) - { - if (((last_field_end % character_width) == 0) || // case 1 - (this_field_info.bit_offset - last_field_end >= word_width)) // case 3 - { - anon_field_info.bit_size = this_field_info.bit_offset % character_width; - anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size; - } - else // case 2 - { - anon_field_info.bit_size = this_field_info.bit_offset - last_field_end; - anon_field_info.bit_offset = last_field_end; - } - } - } - - if (anon_field_info.IsValid()) - { - clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL, - GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), - accessibility, - anon_field_info.bit_size); - - layout_info.field_offsets.insert( - std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); - } - } - last_field_info = this_field_info; - } - else - { - last_field_info.Clear(); - } - - ClangASTType member_clang_type = member_type->GetClangLayoutType(); - - { - // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>). - // If the current field is at the end of the structure, then there is definitely no room for extra - // elements and we override the type to array[0]. - - ClangASTType member_array_element_type; - uint64_t member_array_size; - bool member_array_is_incomplete; - - if (member_clang_type.IsArrayType(&member_array_element_type, - &member_array_size, - &member_array_is_incomplete) && - !member_array_is_incomplete) - { - uint64_t parent_byte_size = parent_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, UINT64_MAX); - - if (member_byte_offset >= parent_byte_size) - { - if (member_array_size != 1) - { - GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64, - MakeUserID(die->GetOffset()), - name, - encoding_uid, - MakeUserID(parent_die->GetOffset())); - } - - member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false); - } - } - } - - field_decl = class_clang_type.AddFieldToRecordType (name, - member_clang_type, - accessibility, - bit_size); - - GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset())); - - layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset)); - } - else - { - if (name) - GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed", - MakeUserID(die->GetOffset()), - name, - encoding_uid); - else - GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed", - MakeUserID(die->GetOffset()), - encoding_uid); - } - } - - if (prop_name != NULL && member_type) - { - clang::ObjCIvarDecl *ivar_decl = NULL; - - if (field_decl) - { - ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl); - assert (ivar_decl != NULL); - } - - ClangASTMetadata metadata; - metadata.SetUserID (MakeUserID(die->GetOffset())); - delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type, - prop_name, - member_type->GetClangLayoutType(), - ivar_decl, - prop_setter_name, - prop_getter_name, - prop_attributes, - &metadata)); - - if (ivar_decl) - GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset())); - } - } - } - ++member_idx; - } - break; - - case DW_TAG_subprogram: - // Let the type parsing code handle this one for us. - member_function_dies.Append (die); - break; - - case DW_TAG_inheritance: + DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); + if (die) { - is_a_class = true; - if (default_accessibility == eAccessNone) - default_accessibility = eAccessPrivate; - // TODO: implement DW_TAG_inheritance type parsing - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes (this, - dwarf_cu, - fixed_form_sizes, - attributes); - if (num_attributes > 0) - { - Declaration decl; - DWARFExpression location; - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; - AccessType accessibility = default_accessibility; - bool is_virtual = false; - bool is_base_of_class = true; - off_t member_byte_offset = 0; - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_type: encoding_uid = form_value.Reference(); break; - case DW_AT_data_member_location: - if (form_value.BlockData()) - { - Value initialValue(0); - Value memberOffset(0); - const DWARFDataExtractor& debug_info_data = get_debug_info_data(); - uint32_t block_length = form_value.Unsigned(); - uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate (NULL, - NULL, - NULL, - NULL, - module, - debug_info_data, - block_offset, - block_length, - eRegisterKindDWARF, - &initialValue, - memberOffset, - NULL)) - { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); - } - } - else - { - // With DWARF 3 and later, if the value is an integer constant, - // this form value is the offset in bytes from the beginning - // of the containing entity. - member_byte_offset = form_value.Unsigned(); - } - break; - - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - - case DW_AT_virtuality: - is_virtual = form_value.Boolean(); - break; - - case DW_AT_sibling: - break; - - default: - break; - } - } - } - - Type *base_class_type = ResolveTypeUID(encoding_uid); - if (base_class_type == NULL) - { - GetObjectFile()->GetModule()->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message", - die->GetOffset(), - encoding_uid, - parent_die->GetOffset()); - break; - } - - ClangASTType base_class_clang_type = base_class_type->GetClangFullType(); - assert (base_class_clang_type); - if (class_language == eLanguageTypeObjC) - { - class_clang_type.SetObjCSuperClass(base_class_clang_type); - } - else - { - base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility, - is_virtual, - is_base_of_class)); - - if (is_virtual) - { - // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't - // give us a constant offset, but gives us a DWARF expressions that requires an actual object - // in memory. the DW_AT_data_member_location for a virtual base class looks like: - // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus ) - // Given this, there is really no valid response we can give to clang for virtual base - // class offsets, and this should eventually be removed from LayoutRecordType() in the external - // AST source in clang. - } - else - { - layout_info.base_offsets.insert( - std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(), - clang::CharUnits::fromQuantity(member_byte_offset))); - } - } - } + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclForUIDFromDWARF(die); } - break; - - default: - break; } } - - return count; + return CompilerDecl(); } - -clang::DeclContext* -SymbolFileDWARF::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid) { - DWARFDebugInfo* debug_info = DebugInfo(); - if (debug_info && UserIDMatches(type_uid)) + if (UserIDMatches(type_uid)) { - DWARFCompileUnitSP cu_sp; - const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp); - if (die) - return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL); + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + { + DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); + if (die) + { + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclContextForUIDFromDWARF(die); + } + } } - return NULL; + return CompilerDeclContext(); } -clang::DeclContext* -SymbolFileDWARF::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid) { if (UserIDMatches(type_uid)) - return GetClangDeclContextForDIEOffset (sc, type_uid); - return NULL; + { + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + { + DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); + if (die) + { + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); + } + } + } + return CompilerDeclContext(); } + Type* SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid) { @@ -2410,418 +1503,143 @@ SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid) DWARFDebugInfo* debug_info = DebugInfo(); if (debug_info) { - DWARFCompileUnitSP cu_sp; - const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp); - const bool assert_not_being_parsed = true; - return ResolveTypeUID (cu_sp.get(), type_die, assert_not_being_parsed); + DWARFDIE type_die = debug_info->GetDIE (DIERef(type_uid)); + if (type_die) + { + const bool assert_not_being_parsed = true; + return ResolveTypeUID (type_die, assert_not_being_parsed); + } } } return NULL; } Type* -SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed) +SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_parsed) { - if (die != NULL) + if (die) { Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, cu)); + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); // We might be coming in in the middle of a type tree (a class // withing a class, an enum within a class), so parse any needed // parent DIEs before we get to this one... - const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die); - switch (decl_ctx_die->Tag()) + DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE (die); + if (decl_ctx_die) { - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: + if (log) { - // Get the type, which could be a forward declaration - if (log) - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, cu), - decl_ctx_die->GetOffset()); -// -// Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed); -// if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag())) -// { -// if (log) -// GetObjectFile()->GetModule()->LogMessage (log, -// "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function", -// die->GetOffset(), -// DW_TAG_value_to_name(die->Tag()), -// die->GetName(this, cu), -// decl_ctx_die->GetOffset()); -// // Ask the type to complete itself if it already hasn't since if we -// // want a function (method or static) from a class, the class must -// // create itself and add it's own methods and class functions. -// if (parent_type) -// parent_type->GetClangFullType(); -// } - } - break; + switch (decl_ctx_die.Tag()) + { + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + { + // Get the type, which could be a forward declaration + if (log) + GetObjectFile()->GetModule()->LogMessage (log, + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", + die.GetOffset(), + die.GetTagAsCString(), + die.GetName(), + decl_ctx_die.GetOffset()); + } + break; - default: - break; + default: + break; + } + } } - return ResolveType (cu, die); + return ResolveType (die); } return NULL; } // This function is used when SymbolFileDWARFDebugMap owns a bunch of // SymbolFileDWARF objects to detect if this DWARF file is the one that -// can resolve a clang_type. +// can resolve a compiler_type. bool -SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type) +SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type) { - ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); - const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); - return die != NULL; + CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); + if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType())) + { + return true; + } + TypeSystem *type_system = compiler_type.GetTypeSystem(); + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->CanCompleteType(compiler_type); + } + return false; } bool -SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) +SymbolFileDWARF::CompleteType (CompilerType &compiler_type) { + TypeSystem *type_system = compiler_type.GetTypeSystem(); + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type)) + return dwarf_ast->CompleteType(compiler_type); + } + // We have a struct/union/class/enum that needs to be fully resolved. - ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); - const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); - if (die == NULL) + CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); + auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType()); + if (die_it == GetForwardDeclClangTypeToDie().end()) { // We have already resolved this type... return true; } + + DWARFDebugInfo* debug_info = DebugInfo(); + DWARFDIE dwarf_die = debug_info->GetDIE(die_it->getSecond()); + + assert(UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile"); + // Once we start resolving this type, remove it from the forward declaration // map in case anyone child members or other types require this type to get resolved. // The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition // are done. - m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType()); - - // Disable external storage for this type so we don't get anymore - // clang::ExternalASTSource queries for this type. - clang_type.SetHasExternalStorage (false); - - DWARFDebugInfo* debug_info = DebugInfo(); + GetForwardDeclClangTypeToDie().erase (die_it); - DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIE (die->GetOffset()).get(); - Type *type = m_die_to_type.lookup (die); - - const dw_tag_t tag = die->Tag(); + Type *type = GetDIEToType().lookup (dwarf_die.GetDIE()); Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); if (log) GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", - MakeUserID(die->GetOffset()), - DW_TAG_value_to_name(tag), + dwarf_die.GetID(), + dwarf_die.GetTagAsCString(), type->GetName().AsCString()); - assert (clang_type); - DWARFDebugInfoEntry::Attributes attributes; - - switch (tag) - { - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: - { - LayoutInfo layout_info; - - { - if (die->HasChildren()) - { - LanguageType class_language = eLanguageTypeUnknown; - if (clang_type.IsObjCObjectOrInterfaceType()) - { - class_language = eLanguageTypeObjC; - // For objective C we don't start the definition when - // the class is created. - clang_type.StartTagDeclarationDefinition (); - } - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) - { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } - else if (tag == DW_TAG_union_type) - { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } - else if (tag == DW_TAG_class_type) - { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } - - SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); - std::vector<clang::CXXBaseSpecifier *> base_classes; - std::vector<int> member_accessibilities; - bool is_a_class = false; - // Parse members and base classes first - DWARFDIECollection member_function_dies; - - DelayedPropertyList delayed_properties; - ParseChildMembers (sc, - dwarf_cu, - die, - clang_type, - class_language, - base_classes, - member_accessibilities, - member_function_dies, - delayed_properties, - default_accessibility, - is_a_class, - layout_info); - - // Now parse any methods if there were any... - size_t num_functions = member_function_dies.Size(); - if (num_functions > 0) - { - for (size_t i=0; i<num_functions; ++i) - { - ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i)); - } - } - - if (class_language == eLanguageTypeObjC) - { - ConstString class_name (clang_type.GetTypeName()); - if (class_name) - { - DIEArray method_die_offsets; - if (m_using_apple_tables) - { - if (m_apple_objc_ap.get()) - m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets); - } - else - { - if (!m_indexed) - Index (); - - m_objc_class_selectors_index.Find (class_name, method_die_offsets); - } - - if (!method_die_offsets.empty()) - { - DWARFDebugInfo* debug_info = DebugInfo(); - - DWARFCompileUnit* method_cu = NULL; - const size_t num_matches = method_die_offsets.size(); - for (size_t i=0; i<num_matches; ++i) - { - const dw_offset_t die_offset = method_die_offsets[i]; - DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu); - - if (method_die) - ResolveType (method_cu, method_die); - else - { - if (m_using_apple_tables) - { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, class_name.GetCString()); - } - } - } - } - - for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end(); - pi != pe; - ++pi) - pi->Finalize(); - } - } - - // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we - // need to tell the clang type it is actually a class. - if (class_language != eLanguageTypeObjC) - { - if (is_a_class && tag_decl_kind != clang::TTK_Class) - clang_type.SetTagTypeKind (clang::TTK_Class); - } - - // Since DW_TAG_structure_type gets used for both classes - // and structures, we may need to set any DW_TAG_member - // fields to have a "private" access if none was specified. - // When we parsed the child members we tracked that actual - // accessibility value for each DW_TAG_member in the - // "member_accessibilities" array. If the value for the - // member is zero, then it was set to the "default_accessibility" - // which for structs was "public". Below we correct this - // by setting any fields to "private" that weren't correctly - // set. - if (is_a_class && !member_accessibilities.empty()) - { - // This is a class and all members that didn't have - // their access specified are private. - clang_type.SetDefaultAccessForRecordFields (eAccessPrivate, - &member_accessibilities.front(), - member_accessibilities.size()); - } - - if (!base_classes.empty()) - { - // Make sure all base classes refer to complete types and not - // forward declarations. If we don't do this, clang will crash - // with an assertion in the call to clang_type.SetBaseClassesForClassType() - bool base_class_error = false; - for (auto &base_class : base_classes) - { - clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); - if (type_source_info) - { - ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType()); - if (base_class_type.GetCompleteType() == false) - { - if (!base_class_error) - { - GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", - die->GetOffset(), - die->GetName(this, dwarf_cu), - base_class_type.GetTypeName().GetCString(), - sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); - } - // We have no choice other than to pretend that the base class - // is complete. If we don't do this, clang will crash when we - // call setBases() inside of "clang_type.SetBaseClassesForClassType()" - // below. Since we provide layout assistance, all ivars in this - // class and other classes will be fine, this is the best we can do - // short of crashing. - base_class_type.StartTagDeclarationDefinition (); - base_class_type.CompleteTagDeclarationDefinition (); - } - } - } - clang_type.SetBaseClassesForClassType (&base_classes.front(), - base_classes.size()); - - // Clang will copy each CXXBaseSpecifier in "base_classes" - // so we have to free them all. - ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(), - base_classes.size()); - } - } - } - - clang_type.BuildIndirectFields (); - clang_type.CompleteTagDeclarationDefinition (); - - if (!layout_info.field_offsets.empty() || - !layout_info.base_offsets.empty() || - !layout_info.vbase_offsets.empty() ) - { - if (type) - layout_info.bit_size = type->GetByteSize() * 8; - if (layout_info.bit_size == 0) - layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8; - - clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl(); - if (record_decl) - { - if (log) - { - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])", - static_cast<void*>(clang_type.GetOpaqueQualType()), - static_cast<void*>(record_decl), - layout_info.bit_size, - layout_info.alignment, - static_cast<uint32_t>(layout_info.field_offsets.size()), - static_cast<uint32_t>(layout_info.base_offsets.size()), - static_cast<uint32_t>(layout_info.vbase_offsets.size())); - - uint32_t idx; - { - llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos, - end = layout_info.field_offsets.end(); - for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx) - { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = " - "{ bit_offset=%u, name='%s' }", - static_cast<void *>(clang_type.GetOpaqueQualType()), idx, - static_cast<uint32_t>(pos->second), pos->first->getNameAsString().c_str()); - } - } - - { - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, - base_end = layout_info.base_offsets.end(); - for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; - ++base_pos, ++idx) - { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) base[%u] " - "= { byte_offset=%u, name='%s' }", - clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(), - base_pos->first->getNameAsString().c_str()); - } - } - { - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos, - vbase_end = layout_info.vbase_offsets.end(); - for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; - ++vbase_pos, ++idx) - { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) " - "vbase[%u] = { byte_offset=%u, name='%s' }", - static_cast<void *>(clang_type.GetOpaqueQualType()), idx, - static_cast<uint32_t>(vbase_pos->second.getQuantity()), - vbase_pos->first->getNameAsString().c_str()); - } - } - } - m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); - } - } - } - - return (bool)clang_type; - - case DW_TAG_enumeration_type: - clang_type.StartTagDeclarationDefinition (); - if (die->HasChildren()) - { - SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); - bool is_signed = false; - clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die); - } - clang_type.CompleteTagDeclarationDefinition (); - return (bool)clang_type; - - default: - assert(false && "not a forward clang type decl!"); - break; - } + assert (compiler_type); + DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type); return false; } Type* -SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed) +SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context) { - if (type_die != NULL) + if (die) { - Type *type = m_die_to_type.lookup (type_die); + Type *type = GetDIEToType().lookup (die.GetDIE()); if (type == NULL) - type = GetTypeForDIE (dwarf_cu, type_die).get(); + type = GetTypeForDIE (die, resolve_function_context).get(); if (assert_not_being_parsed) { @@ -2829,15 +1647,15 @@ SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn return type; GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s", - type_die->GetOffset(), - DW_TAG_value_to_name(type_die->Tag()), - type_die->GetName(this, dwarf_cu)); + die.GetOffset(), + die.GetTagAsCString(), + die.GetName()); } else return type; } - return NULL; + return nullptr; } CompileUnit* @@ -2853,26 +1671,60 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32 return (CompileUnit*)dwarf_cu->GetUserData(); } +size_t +SymbolFileDWARF::GetObjCMethodDIEOffsets (ConstString class_name, DIEArray &method_die_offsets) +{ + method_die_offsets.clear(); + if (m_using_apple_tables) + { + if (m_apple_objc_ap.get()) + m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets); + } + else + { + if (!m_indexed) + Index (); + + m_objc_class_selectors_index.Find (class_name, method_die_offsets); + } + return method_die_offsets.size(); +} + bool -SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc) +SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc) { sc.Clear(false); - // Check if the symbol vendor already knows about this compile unit? - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); - sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(func_die->GetOffset())).get(); - if (sc.function == NULL) - sc.function = ParseCompileUnitFunction(sc, dwarf_cu, func_die); - - if (sc.function) - { - sc.module_sp = sc.function->CalculateSymbolContextModule(); - return true; + if (die) + { + // Check if the symbol vendor already knows about this compile unit? + sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); + + sc.function = sc.comp_unit->FindFunctionByUID (die.GetID()).get(); + if (sc.function == NULL) + sc.function = ParseCompileUnitFunction(sc, die); + + if (sc.function) + { + sc.module_sp = sc.function->CalculateSymbolContextModule(); + return true; + } } return false; } +lldb::ModuleSP +SymbolFileDWARF::GetDWOModule (ConstString name) +{ + UpdateExternalModuleListIfNeeded(); + const auto &pos = m_external_type_modules.find(name); + if (pos != m_external_type_modules.end()) + return pos->second; + else + return lldb::ModuleSP(); +} + void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -2881,47 +1733,33 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded() m_fetched_external_modules = true; DWARFDebugInfo * debug_info = DebugInfo(); - debug_info->GetNumCompileUnits(); - + const uint32_t num_compile_units = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); - const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly(); - if (die && die->HasChildren() == false) + const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly(); + if (die && die.HasChildren() == false) { - const uint64_t name_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_name, UINT64_MAX); - const uint64_t dwo_path_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_GNU_dwo_name, UINT64_MAX); - - if (name_strp != UINT64_MAX) + const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr); + + if (name) { - if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end()) + ConstString const_name(name); + if (m_external_type_modules.find(const_name) == m_external_type_modules.end()) { - const char *name = get_debug_str_data().PeekCStr(name_strp); - const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp); - if (name || dwo_path) + ModuleSP module_sp; + const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); + if (dwo_path) { - ModuleSP module_sp; - if (dwo_path) - { - ModuleSpec dwo_module_spec; - dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); - dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); - //printf ("Loading dwo = '%s'\n", dwo_path); - Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL); - } - - if (dwo_path_strp != LLDB_INVALID_UID) - { - m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp }; - } - else - { - // This hack should be removed promptly once clang emits both. - m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp }; - } + ModuleSpec dwo_module_spec; + dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); + dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); + //printf ("Loading dwo = '%s'\n", dwo_path); + Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL); } + m_external_type_modules[const_name] = module_sp; } } } @@ -3025,7 +1863,7 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ else { uint32_t cu_idx = DW_INVALID_INDEX; - DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get(); + DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx); if (dwarf_cu) { sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); @@ -3036,22 +1874,16 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ bool force_check_line_table = false; if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { - DWARFDebugInfoEntry *function_die = NULL; - DWARFDebugInfoEntry *block_die = NULL; - if (resolve_scope & eSymbolContextBlock) - { - dwarf_cu->LookupAddress(file_vm_addr, &function_die, &block_die); - } - else - { - dwarf_cu->LookupAddress(file_vm_addr, &function_die, NULL); - } - - if (function_die != NULL) + DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); + DWARFDIE block_die; + if (function_die) { - sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get(); + sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get(); if (sc.function == NULL) - sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die); + sc.function = ParseCompileUnitFunction(sc, function_die); + + if (sc.function && (resolve_scope & eSymbolContextBlock)) + block_die = function_die.LookupDeepestBlock(file_vm_addr); } else { @@ -3072,10 +1904,10 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ { Block& block = sc.function->GetBlock (true); - if (block_die != NULL) - sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset())); + if (block_die) + sc.block = block.FindBlockByID (block_die.GetID()); else - sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset())); + sc.block = block.FindBlockByID (function_die.GetID()); if (sc.block) resolved |= eSymbolContextBlock; } @@ -3190,25 +2022,26 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress(); if (file_vm_addr != LLDB_INVALID_ADDRESS) { - DWARFDebugInfoEntry *function_die = NULL; - DWARFDebugInfoEntry *block_die = NULL; - dwarf_cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL); - - if (function_die != NULL) + DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); + DWARFDIE block_die; + if (function_die) { - sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get(); + sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get(); if (sc.function == NULL) - sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die); + sc.function = ParseCompileUnitFunction(sc, function_die); + + if (sc.function && (resolve_scope & eSymbolContextBlock)) + block_die = function_die.LookupDeepestBlock(file_vm_addr); } if (sc.function != NULL) { Block& block = sc.function->GetBlock (true); - if (block_die != NULL) - sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset())); - else if (function_die != NULL) - sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset())); + if (block_die) + sc.block = block.FindBlockByID (block_die.GetID()); + else if (function_die) + sc.block = block.FindBlockByID (function_die.GetID()); } } } @@ -3255,38 +2088,77 @@ SymbolFileDWARF::Index () DWARFDebugInfo* debug_info = DebugInfo(); if (debug_info) { - uint32_t cu_idx = 0; const uint32_t num_compile_units = GetNumCompileUnits(); - for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + std::vector<NameToDIE> function_basename_index(num_compile_units); + std::vector<NameToDIE> function_fullname_index(num_compile_units); + std::vector<NameToDIE> function_method_index(num_compile_units); + std::vector<NameToDIE> function_selector_index(num_compile_units); + std::vector<NameToDIE> objc_class_selectors_index(num_compile_units); + std::vector<NameToDIE> global_index(num_compile_units); + std::vector<NameToDIE> type_index(num_compile_units); + std::vector<NameToDIE> namespace_index(num_compile_units); + + auto parser_fn = [this, + debug_info, + &function_basename_index, + &function_fullname_index, + &function_method_index, + &function_selector_index, + &objc_class_selectors_index, + &global_index, + &type_index, + &namespace_index](uint32_t cu_idx) { DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); + bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1; + + dwarf_cu->Index(function_basename_index[cu_idx], + function_fullname_index[cu_idx], + function_method_index[cu_idx], + function_selector_index[cu_idx], + objc_class_selectors_index[cu_idx], + global_index[cu_idx], + type_index[cu_idx], + namespace_index[cu_idx]); - bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1; - - dwarf_cu->Index (cu_idx, - m_function_basename_index, - m_function_fullname_index, - m_function_method_index, - m_function_selector_index, - m_objc_class_selectors_index, - m_global_index, - m_type_index, - m_namespace_index); - // Keep memory down by clearing DIEs if this generate function // caused them to be parsed if (clear_dies) - dwarf_cu->ClearDIEs (true); + dwarf_cu->ClearDIEs(true); + + return cu_idx; + }; + + TaskRunner<uint32_t> task_runner; + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + task_runner.AddTask(parser_fn, cu_idx); + + while (true) + { + std::future<uint32_t> f = task_runner.WaitForNextCompletedTask(); + if (!f.valid()) + break; + uint32_t cu_idx = f.get(); + + m_function_basename_index.Append(function_basename_index[cu_idx]); + m_function_fullname_index.Append(function_fullname_index[cu_idx]); + m_function_method_index.Append(function_method_index[cu_idx]); + m_function_selector_index.Append(function_selector_index[cu_idx]); + m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]); + m_global_index.Append(global_index[cu_idx]); + m_type_index.Append(type_index[cu_idx]); + m_namespace_index.Append(namespace_index[cu_idx]); } - - m_function_basename_index.Finalize(); - m_function_fullname_index.Finalize(); - m_function_method_index.Finalize(); - m_function_selector_index.Finalize(); - m_objc_class_selectors_index.Finalize(); - m_global_index.Finalize(); - m_type_index.Finalize(); - m_namespace_index.Finalize(); + + TaskPool::RunTasks( + [&]() { m_function_basename_index.Finalize(); }, + [&]() { m_function_fullname_index.Finalize(); }, + [&]() { m_function_method_index.Finalize(); }, + [&]() { m_function_selector_index.Finalize(); }, + [&]() { m_objc_class_selectors_index.Finalize(); }, + [&]() { m_global_index.Finalize(); }, + [&]() { m_type_index.Finalize(); }, + [&]() { m_namespace_index.Finalize(); }); #if defined (ENABLE_DEBUG_PRINTF) StreamFile s(stdout, false); @@ -3299,30 +2171,26 @@ SymbolFileDWARF::Index () s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s); s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s); s.Printf("\nTypes:\n"); m_type_index.Dump (&s); - s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s); + s.Printf("\nNamespaces:\n") m_namespace_index.Dump (&s); #endif } } bool -SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *namespace_decl) +SymbolFileDWARF::DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx) { - if (namespace_decl == NULL) + if (decl_ctx == nullptr || !decl_ctx->IsValid()) { // Invalid namespace decl which means we aren't matching only things // in this symbol file, so return true to indicate it matches this // symbol file. return true; } - - clang::ASTContext *namespace_ast = namespace_decl->GetASTContext(); - - if (namespace_ast == NULL) - return true; // No AST in the "namespace_decl", return true since it - // could then match any symbol file, including this one - if (namespace_ast == GetClangASTContext().getASTContext()) - return true; // The ASTs match, return true + TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); + TypeSystem *type_system = GetTypeSystemForLanguage(decl_ctx_type_system->GetMinimumLanguage(nullptr)); + if (decl_ctx_type_system == type_system) + return true; // The type systems match, return true // The namespace AST was valid, and it does not match... Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -3333,66 +2201,19 @@ SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *n return false; } -bool -SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl, - DWARFCompileUnit* cu, - const DWARFDebugInfoEntry* die) -{ - // No namespace specified, so the answer is - if (namespace_decl == NULL) - return true; - - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); - - const DWARFDebugInfoEntry *decl_ctx_die = NULL; - clang::DeclContext *die_clang_decl_ctx = GetClangDeclContextContainingDIE (cu, die, &decl_ctx_die); - if (decl_ctx_die) - { - clang::NamespaceDecl *clang_namespace_decl = namespace_decl->GetNamespaceDecl(); - - if (clang_namespace_decl) - { - if (decl_ctx_die->Tag() != DW_TAG_namespace) - { - if (log) - GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent is not a namespace"); - return false; - } - - if (clang_namespace_decl == die_clang_decl_ctx) - return true; - else - return false; - } - else - { - // We have a namespace_decl that was not NULL but it contained - // a NULL "clang::NamespaceDecl", so this means the global namespace - // So as long the contained decl context DIE isn't a namespace - // we should be ok. - if (decl_ctx_die->Tag() != DW_TAG_namespace) - return true; - } - } - - if (log) - GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent doesn't exist"); - - return false; -} uint32_t -SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) +SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables) { Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)", + "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables)", name.GetCString(), - static_cast<const void*>(namespace_decl), + static_cast<const void*>(parent_decl_ctx), append, max_matches); - if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return 0; DWARFDebugInfo* info = DebugInfo(); @@ -3417,7 +2238,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat llvm::StringRef basename; llvm::StringRef context; - if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename)) + if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, basename)) basename = name_cstr; m_apple_names_ap->FindByName (basename.data(), die_offsets); @@ -3440,17 +2261,15 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat assert (sc.module_sp); DWARFDebugInfo* debug_info = DebugInfo(); - DWARFCompileUnit* dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; bool done = false; for (size_t i=0; i<num_die_matches && !done; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); if (die) { - switch (die->Tag()) + switch (die.Tag()) { default: case DW_TAG_subprogram: @@ -3461,12 +2280,20 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat case DW_TAG_variable: { - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); + sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); - if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) - continue; + if (parent_decl_ctx) + { + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) + { + CompilerDeclContext actual_parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); + if (!actual_parent_decl_ctx || actual_parent_decl_ctx != *parent_decl_ctx) + continue; + } + } - ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables); + ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); if (variables.GetSize() - original_size >= max_matches) done = true; @@ -3479,7 +2306,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, name.GetCString()); + die_ref.die_offset, name.GetCString()); } } } @@ -3490,9 +2317,9 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u", + "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u", name.GetCString(), - static_cast<const void*>(namespace_decl), + static_cast<const void*>(parent_decl_ctx), append, max_matches, num_matches); } @@ -3525,7 +2352,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append const uint32_t original_size = variables.GetSize(); DIEArray die_offsets; - + if (m_using_apple_tables) { if (m_apple_names_ap.get()) @@ -3548,22 +2375,20 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append sc.module_sp = m_obj_file->GetModule(); assert (sc.module_sp); - DWARFCompileUnit* dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; const size_t num_matches = die_offsets.size(); if (num_matches) { DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); if (die) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); + sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); - ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables); + ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); if (variables.GetSize() - original_size >= max_matches) break; @@ -3573,7 +2398,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n", - die_offset, regex.GetText()); + die_ref.die_offset, regex.GetText()); } } } @@ -3585,53 +2410,59 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append bool -SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset, - DWARFCompileUnit *&dwarf_cu, +SymbolFileDWARF::ResolveFunction (const DIERef& die_ref, bool include_inlines, SymbolContextList& sc_list) { - const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); - return ResolveFunction (dwarf_cu, die, include_inlines, sc_list); + DWARFDIE die = DebugInfo()->GetDIE (die_ref); + return ResolveFunction (die, include_inlines, sc_list); } bool -SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, +SymbolFileDWARF::ResolveFunction (const DWARFDIE &orig_die, bool include_inlines, SymbolContextList& sc_list) { SymbolContext sc; - if (die == NULL) + if (!orig_die) return false; // If we were passed a die that is not a function, just return false... - if (! (die->Tag() == DW_TAG_subprogram || (include_inlines && die->Tag() == DW_TAG_inlined_subroutine))) + if (!(orig_die.Tag() == DW_TAG_subprogram || (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine))) return false; - - const DWARFDebugInfoEntry* inlined_die = NULL; - if (die->Tag() == DW_TAG_inlined_subroutine) + + DWARFDIE die = orig_die; + DWARFDIE inlined_die; + if (die.Tag() == DW_TAG_inlined_subroutine) { inlined_die = die; - while ((die = die->GetParent()) != NULL) + while (1) { - if (die->Tag() == DW_TAG_subprogram) + die = die.GetParent(); + + if (die) + { + if (die.Tag() == DW_TAG_subprogram) + break; + } + else break; } } - assert (die && die->Tag() == DW_TAG_subprogram); - if (GetFunction (cu, die, sc)) + assert (die && die.Tag() == DW_TAG_subprogram); + if (GetFunction (die, sc)) { Address addr; // Parse all blocks if needed if (inlined_die) { Block &function_block = sc.function->GetBlock (true); - sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset())); + sc.block = function_block.FindBlockByID (inlined_die.GetID()); if (sc.block == NULL) - sc.block = function_block.FindBlockByID (inlined_die->GetOffset()); + sc.block = function_block.FindBlockByID (inlined_die.GetOffset()); if (sc.block == NULL || sc.block->GetStartAddress (addr) == false) addr.Clear(); } @@ -3702,131 +2533,37 @@ SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets, const size_t num_matches = die_offsets.size(); if (num_matches) { - DWARFCompileUnit* dwarf_cu = NULL; for (size_t i=0; i<num_matches; ++i) - { - const dw_offset_t die_offset = die_offsets[i]; - ResolveFunction (die_offset, dwarf_cu, include_inlines, sc_list); - } + ResolveFunction (die_offsets[i], include_inlines, sc_list); } } bool -SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die, - const DWARFCompileUnit *dwarf_cu, - uint32_t name_type_mask, - const char *partial_name, - const char *base_name_start, - const char *base_name_end) +SymbolFileDWARF::DIEInDeclContext (const CompilerDeclContext *decl_ctx, + const DWARFDIE &die) { - // If we are looking only for methods, throw away all the ones that are or aren't in C++ classes: - if (name_type_mask == eFunctionNameTypeMethod || name_type_mask == eFunctionNameTypeBase) - { - clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset()); - if (!containing_decl_ctx) - return false; - - bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()); - - if (name_type_mask == eFunctionNameTypeMethod) - { - if (is_cxx_method == false) - return false; - } - - if (name_type_mask == eFunctionNameTypeBase) - { - if (is_cxx_method == true) - return false; - } - } + // If we have no parent decl context to match this DIE matches, and if the parent + // decl context isn't valid, we aren't trying to look for any particular decl + // context so any die matches. + if (decl_ctx == nullptr || !decl_ctx->IsValid()) + return true; - // Now we need to check whether the name we got back for this type matches the extra specifications - // that were in the name we're looking up: - if (base_name_start != partial_name || *base_name_end != '\0') + if (die) { - // First see if the stuff to the left matches the full name. To do that let's see if - // we can pull out the mips linkage name attribute: - - Mangled best_name; - DWARFDebugInfoEntry::Attributes attributes; - DWARFFormValue form_value; - die->GetAttributes(this, dwarf_cu, NULL, attributes); - uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name); - if (idx == UINT32_MAX) - idx = attributes.FindAttributeIndex(DW_AT_linkage_name); - if (idx != UINT32_MAX) + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) { - if (attributes.ExtractFormValueAtIndex(this, idx, form_value)) - { - const char *mangled_name = form_value.AsCString(&get_debug_str_data()); - if (mangled_name) - best_name.SetValue (ConstString(mangled_name), true); - } - } - - if (!best_name) - { - idx = attributes.FindAttributeIndex(DW_AT_name); - if (idx != UINT32_MAX && attributes.ExtractFormValueAtIndex(this, idx, form_value)) - { - const char *name = form_value.AsCString(&get_debug_str_data()); - best_name.SetValue (ConstString(name), false); - } - } - - const LanguageType cu_language = const_cast<DWARFCompileUnit *>(dwarf_cu)->GetLanguageType(); - if (best_name.GetDemangledName(cu_language)) - { - const char *demangled = best_name.GetDemangledName(cu_language).GetCString(); - if (demangled) - { - std::string name_no_parens(partial_name, base_name_end - partial_name); - const char *partial_in_demangled = strstr (demangled, name_no_parens.c_str()); - if (partial_in_demangled == NULL) - return false; - else - { - // Sort out the case where our name is something like "Process::Destroy" and the match is - // "SBProcess::Destroy" - that shouldn't be a match. We should really always match on - // namespace boundaries... - - if (partial_name[0] == ':' && partial_name[1] == ':') - { - // The partial name was already on a namespace boundary so all matches are good. - return true; - } - else if (partial_in_demangled == demangled) - { - // They both start the same, so this is an good match. - return true; - } - else - { - if (partial_in_demangled - demangled == 1) - { - // Only one character difference, can't be a namespace boundary... - return false; - } - else if (*(partial_in_demangled - 1) == ':' && *(partial_in_demangled - 2) == ':') - { - // We are on a namespace boundary, so this is also good. - return true; - } - else - return false; - } - } - } + CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); + if (actual_decl_ctx) + return actual_decl_ctx == *decl_ctx; } } - - return true; + return false; } uint32_t -SymbolFileDWARF::FindFunctions (const ConstString &name, - const lldb_private::ClangNamespaceDecl *namespace_decl, +SymbolFileDWARF::FindFunctions (const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, @@ -3854,7 +2591,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, if (!append) sc_list.Clear(); - if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return 0; // If name is empty then we won't find anything. @@ -3872,7 +2609,6 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, if (info == NULL) return 0; - DWARFCompileUnit *dwarf_cu = NULL; std::set<const DWARFDebugInfoEntry *> resolved_dies; if (m_using_apple_tables) { @@ -3891,30 +2627,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); for (uint32_t i = 0; i < num_matches; i++) { - const dw_offset_t die_offset = die_offsets[i]; - const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = info->GetDIE (die_ref); if (die) { - if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) - continue; - - if (resolved_dies.find(die) == resolved_dies.end()) + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) - resolved_dies.insert(die); + if (ResolveFunction (die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); } } else { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", - die_offset, name_cstr); + die_ref.die_offset, name_cstr); } } } if (name_type_mask & eFunctionNameTypeSelector) { - if (namespace_decl && *namespace_decl) + if (parent_decl_ctx && parent_decl_ctx->IsValid()) return 0; // no selectors in namespaces num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); @@ -3923,30 +2659,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, for (uint32_t i = 0; i < num_matches; i++) { - const dw_offset_t die_offset = die_offsets[i]; - const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = info->GetDIE (die_ref); if (die) { - const char *die_name = die->GetName(this, dwarf_cu); - if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name)) + const char *die_name = die.GetName(); + if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) { - if (resolved_dies.find(die) == resolved_dies.end()) + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) - resolved_dies.insert(die); + if (ResolveFunction (die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); } } } else { GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", - die_offset, name_cstr); + die_ref.die_offset, name_cstr); } } die_offsets.clear(); } - if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase) + if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || name_type_mask & eFunctionNameTypeBase) { // The apple_names table stores just the "base name" of C++ methods in the table. So we have to // extract the base name, look that up, and if there is any other information in the name we were @@ -3957,16 +2693,16 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, for (uint32_t i = 0; i < num_matches; i++) { - const dw_offset_t die_offset = die_offsets[i]; - const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = info->GetDIE (die_ref); if (die) { - if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) - continue; + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die) == resolved_dies.end()) - if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && ResolveFunction (die, include_inlines, sc_list)) { bool keep_die = true; if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod)) @@ -3986,8 +2722,8 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, if (type) { - clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID()); - if (decl_ctx->isRecord()) + CompilerDeclContext decl_ctx = GetDeclContextContainingUID (type->GetID()); + if (decl_ctx.IsStructUnionOrClass()) { if (name_type_mask & eFunctionNameTypeBase) { @@ -4007,19 +2743,19 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, else { GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type", - die_offset); + die_ref.die_offset); } } } } if (keep_die) - resolved_dies.insert(die); + resolved_dies.insert(die.GetDIE()); } } else { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", - die_offset, name_cstr); + die_ref.die_offset, name_cstr); } } die_offsets.clear(); @@ -4046,10 +2782,10 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, // TODO: The arch in the object file isn't correct for MSVC // binaries on windows, we should find a way to make it // correct and handle those symbols as well. - if (sc_list.GetSize() == 0) + if (sc_list.GetSize() == original_size) { ArchSpec arch; - if (!namespace_decl && + if (!parent_decl_ctx && GetObjectFile()->GetArchitecture(arch) && (arch.GetTriple().isOSFreeBSD() || arch.GetTriple().isOSLinux() || arch.GetMachine() == llvm::Triple::hexagon)) @@ -4076,24 +2812,22 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, } } DIEArray die_offsets; - DWARFCompileUnit *dwarf_cu = NULL; - if (name_type_mask & eFunctionNameTypeBase) { uint32_t num_base = m_function_basename_index.Find(name, die_offsets); for (uint32_t i = 0; i < num_base; i++) { - const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu); + DWARFDIE die = info->GetDIE (die_offsets[i]); if (die) { - if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) - continue; - + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die) == resolved_dies.end()) + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) - resolved_dies.insert(die); + if (ResolveFunction (die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); } } } @@ -4102,21 +2836,21 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, if (name_type_mask & eFunctionNameTypeMethod) { - if (namespace_decl && *namespace_decl) + if (parent_decl_ctx && parent_decl_ctx->IsValid()) return 0; // no methods in namespaces uint32_t num_base = m_function_method_index.Find(name, die_offsets); { for (uint32_t i = 0; i < num_base; i++) { - const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu); + DWARFDIE die = info->GetDIE (die_offsets[i]); if (die) { // If we get to here, the die is good, and we should add it: - if (resolved_dies.find(die) == resolved_dies.end()) + if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) { - if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) - resolved_dies.insert(die); + if (ResolveFunction (die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); } } } @@ -4124,7 +2858,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name, die_offsets.clear(); } - if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl)) + if ((name_type_mask & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid())) { FindFunctions (name, m_function_selector_index, include_inlines, sc_list); } @@ -4196,10 +2930,10 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inli uint32_t SymbolFileDWARF::FindTypes (const SymbolContext& sc, const ConstString &name, - const lldb_private::ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, - TypeList& types) + TypeMap& types) { DWARFDebugInfo* info = DebugInfo(); if (info == NULL) @@ -4209,16 +2943,16 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, if (log) { - if (namespace_decl) + if (parent_decl_ctx) GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)", + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list)", name.GetCString(), - static_cast<void*>(namespace_decl->GetNamespaceDecl()), - namespace_decl->GetQualifiedName().c_str(), + static_cast<const void*>(parent_decl_ctx), + parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches); else GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)", + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list)", name.GetCString(), append, max_matches); } @@ -4227,7 +2961,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, if (!append) types.Clear(); - if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return 0; DIEArray die_offsets; @@ -4253,20 +2987,18 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, if (num_die_matches) { const uint32_t initial_types_size = types.GetSize(); - DWARFCompileUnit* dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_die_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); if (die) { - if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) - continue; + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match - Type *matching_type = ResolveType (dwarf_cu, die); + Type *matching_type = ResolveType (die, true, true); if (matching_type) { // We found a type pointer, now find the shared pointer form our type list @@ -4280,7 +3012,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, name.GetCString()); + die_ref.die_offset, name.GetCString()); } } @@ -4288,20 +3020,20 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, const uint32_t num_matches = types.GetSize() - initial_types_size; if (log && num_matches) { - if (namespace_decl) + if (parent_decl_ctx) { GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u", + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u", name.GetCString(), - static_cast<void*>(namespace_decl->GetNamespaceDecl()), - namespace_decl->GetQualifiedName().c_str(), + static_cast<const void*>(parent_decl_ctx), + parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches, num_matches); } else { GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u", + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list) => %u", name.GetCString(), append, max_matches, num_matches); @@ -4309,14 +3041,112 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, } return num_matches; } + else + { + UpdateExternalModuleListIfNeeded(); + + for (const auto &pair : m_external_type_modules) + { + ModuleSP external_module_sp = pair.second; + if (external_module_sp) + { + SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); + if (sym_vendor) + { + const uint32_t num_external_matches = sym_vendor->FindTypes (sc, + name, + parent_decl_ctx, + append, + max_matches, + types); + if (num_external_matches) + return num_external_matches; + } + } + } + } + + return 0; +} + + +size_t +SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context, + bool append, + TypeMap& types) +{ + if (!append) + types.Clear(); + + if (context.empty()) + return 0; + + DIEArray die_offsets; + + ConstString name = context.back().name; + + if (m_using_apple_tables) + { + if (m_apple_types_ap.get()) + { + const char *name_cstr = name.GetCString(); + m_apple_types_ap->FindByName (name_cstr, die_offsets); + } + } + else + { + if (!m_indexed) + Index (); + + m_type_index.Find (name, die_offsets); + } + + const size_t num_die_matches = die_offsets.size(); + + if (num_die_matches) + { + size_t num_matches = 0; + DWARFDebugInfo* debug_info = DebugInfo(); + for (size_t i=0; i<num_die_matches; ++i) + { + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); + + if (die) + { + std::vector<CompilerContext> die_context; + die.GetDWOContext(die_context); + if (die_context != context) + continue; + + Type *matching_type = ResolveType (die, true, true); + if (matching_type) + { + // We found a type pointer, now find the shared pointer form our type list + types.InsertUnique (matching_type->shared_from_this()); + ++num_matches; + } + } + else + { + if (m_using_apple_tables) + { + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", + die_ref.die_offset, name.GetCString()); + } + } + + } + return num_matches; + } return 0; } -ClangNamespaceDecl +CompilerDeclContext SymbolFileDWARF::FindNamespace (const SymbolContext& sc, const ConstString &name, - const lldb_private::ClangNamespaceDecl *parent_namespace_decl) + const CompilerDeclContext *parent_decl_ctx) { Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -4326,11 +3156,13 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", name.GetCString()); } - - if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl)) - return ClangNamespaceDecl(); - ClangNamespaceDecl namespace_decl; + CompilerDeclContext namespace_decl_ctx; + + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + return namespace_decl_ctx; + + DWARFDebugInfo* info = DebugInfo(); if (info) { @@ -4354,28 +3186,26 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc, m_namespace_index.Find (name, die_offsets); } - DWARFCompileUnit* dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; const size_t num_matches = die_offsets.size(); if (num_matches) { DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); - + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); + if (die) { - if (parent_namespace_decl && !DIEIsInNamespace (parent_namespace_decl, dwarf_cu, die)) - continue; + if (!DIEInDeclContext (parent_decl_ctx, die)) + continue; // The containing decl contexts don't match - clang::NamespaceDecl *clang_namespace_decl = ResolveNamespaceDIE (dwarf_cu, die); - if (clang_namespace_decl) + DWARFASTParser *dwarf_ast = die.GetDWARFParser(); + if (dwarf_ast) { - namespace_decl.SetASTContext (GetClangASTContext().getASTContext()); - namespace_decl.SetNamespaceDecl (clang_namespace_decl); - break; + namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF (die); + if (namespace_decl_ctx) + break; } } else @@ -4383,421 +3213,50 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc, if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, name.GetCString()); + die_ref.die_offset, name.GetCString()); } } } } } - if (log && namespace_decl.GetNamespaceDecl()) + if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"", + "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => CompilerDeclContext(%p/%p) \"%s\"", name.GetCString(), - static_cast<const void*>(namespace_decl.GetNamespaceDecl()), - namespace_decl.GetQualifiedName().c_str()); - } - - return namespace_decl; -} - -uint32_t -SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types) -{ - // Remember how many sc_list are in the list before we search in case - // we are appending the results to a variable list. - uint32_t original_size = types.GetSize(); - - const uint32_t num_die_offsets = die_offsets.size(); - // Parse all of the types we found from the pubtypes matches - uint32_t i; - uint32_t num_matches = 0; - for (i = 0; i < num_die_offsets; ++i) - { - Type *matching_type = ResolveTypeUID (die_offsets[i]); - if (matching_type) - { - // We found a type pointer, now find the shared pointer form our type list - types.InsertUnique (matching_type->shared_from_this()); - ++num_matches; - if (num_matches >= max_matches) - break; - } - } - - // Return the number of variable that were appended to the list - return types.GetSize() - original_size; -} - - -size_t -SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, - clang::DeclContext *containing_decl_ctx, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - bool skip_artificial, - bool &is_static, - bool &is_variadic, - std::vector<ClangASTType>& function_param_types, - std::vector<clang::ParmVarDecl*>& function_param_decls, - unsigned &type_quals) // , - // ClangASTContext::TemplateParameterInfos &template_param_infos)) -{ - if (parent_die == NULL) - return 0; - - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - - size_t arg_idx = 0; - const DWARFDebugInfoEntry *die; - for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) - { - dw_tag_t tag = die->Tag(); - switch (tag) - { - case DW_TAG_formal_parameter: - { - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); - if (num_attributes > 0) - { - const char *name = NULL; - Declaration decl; - dw_offset_t param_type_die_offset = DW_INVALID_OFFSET; - bool is_artificial = false; - // one of None, Auto, Register, Extern, Static, PrivateExtern - - clang::StorageClass storage = clang::SC_None; - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: param_type_die_offset = form_value.Reference(); break; - case DW_AT_artificial: is_artificial = form_value.Boolean(); break; - case DW_AT_location: - // if (form_value.BlockData()) - // { - // const DWARFDataExtractor& debug_info_data = debug_info(); - // uint32_t block_length = form_value.Unsigned(); - // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length); - // } - // else - // { - // } - // break; - case DW_AT_const_value: - case DW_AT_default_value: - case DW_AT_description: - case DW_AT_endianity: - case DW_AT_is_optional: - case DW_AT_segment: - case DW_AT_variable_parameter: - default: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } - - bool skip = false; - if (skip_artificial) - { - if (is_artificial) - { - // In order to determine if a C++ member function is - // "const" we have to look at the const-ness of "this"... - // Ugly, but that - if (arg_idx == 0) - { - if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) - { - // Often times compilers omit the "this" name for the - // specification DIEs, so we can't rely upon the name - // being in the formal parameter DIE... - if (name == NULL || ::strcmp(name, "this")==0) - { - Type *this_type = ResolveTypeUID (param_type_die_offset); - if (this_type) - { - uint32_t encoding_mask = this_type->GetEncodingMask(); - if (encoding_mask & Type::eEncodingIsPointerUID) - { - is_static = false; - - if (encoding_mask & (1u << Type::eEncodingIsConstUID)) - type_quals |= clang::Qualifiers::Const; - if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) - type_quals |= clang::Qualifiers::Volatile; - } - } - } - } - } - skip = true; - } - else - { - - // HACK: Objective C formal parameters "self" and "_cmd" - // are not marked as artificial in the DWARF... - CompileUnit *comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); - if (comp_unit) - { - switch (comp_unit->GetLanguage()) - { - case eLanguageTypeObjC: - case eLanguageTypeObjC_plus_plus: - if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0)) - skip = true; - break; - default: - break; - } - } - } - } - - if (!skip) - { - Type *type = ResolveTypeUID(param_type_die_offset); - if (type) - { - function_param_types.push_back (type->GetClangForwardType()); - - clang::ParmVarDecl *param_var_decl = GetClangASTContext().CreateParameterDeclaration (name, - type->GetClangForwardType(), - storage); - assert(param_var_decl); - function_param_decls.push_back(param_var_decl); - - GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset())); - } - } - } - arg_idx++; - } - break; - - case DW_TAG_unspecified_parameters: - is_variadic = true; - break; - - case DW_TAG_template_type_parameter: - case DW_TAG_template_value_parameter: - // The one caller of this was never using the template_param_infos, - // and the local variable was taking up a large amount of stack space - // in SymbolFileDWARF::ParseType() so this was removed. If we ever need - // the template params back, we can add them back. - // ParseTemplateDIE (dwarf_cu, die, template_param_infos); - break; - - default: - break; - } - } - return arg_idx; -} - -size_t -SymbolFileDWARF::ParseChildEnumerators -( - const SymbolContext& sc, - lldb_private::ClangASTType &clang_type, - bool is_signed, - uint32_t enumerator_byte_size, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die -) -{ - if (parent_die == NULL) - return 0; - - size_t enumerators_added = 0; - const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - - for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) - { - const dw_tag_t tag = die->Tag(); - if (tag == DW_TAG_enumerator) - { - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); - if (num_child_attributes > 0) - { - const char *name = NULL; - bool got_value = false; - int64_t enum_value = 0; - Declaration decl; - - uint32_t i; - for (i=0; i<num_child_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_const_value: - got_value = true; - if (is_signed) - enum_value = form_value.Signed(); - else - enum_value = form_value.Unsigned(); - break; - - case DW_AT_name: - name = form_value.AsCString(&get_debug_str_data()); - break; - - case DW_AT_description: - default: - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_sibling: - break; - } - } - } - - if (name && name[0] && got_value) - { - clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(), - decl, - name, - enum_value, - enumerator_byte_size * 8); - ++enumerators_added; - } - } - } + static_cast<const void*>(namespace_decl_ctx.GetTypeSystem()), + static_cast<const void*>(namespace_decl_ctx.GetOpaqueDeclContext()), + namespace_decl_ctx.GetName().AsCString("<NULL>")); } - return enumerators_added; -} - -void -SymbolFileDWARF::ParseChildArrayInfo -( - const SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - int64_t& first_index, - std::vector<uint64_t>& element_orders, - uint32_t& byte_stride, - uint32_t& bit_stride -) -{ - if (parent_die == NULL) - return; - - const DWARFDebugInfoEntry *die; - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) - { - const dw_tag_t tag = die->Tag(); - switch (tag) - { - case DW_TAG_subrange_type: - { - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); - if (num_child_attributes > 0) - { - uint64_t num_elements = 0; - uint64_t lower_bound = 0; - uint64_t upper_bound = 0; - bool upper_bound_valid = false; - uint32_t i; - for (i=0; i<num_child_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_name: - break; - - case DW_AT_count: - num_elements = form_value.Unsigned(); - break; - - case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); - break; - - case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); - break; - - case DW_AT_lower_bound: - lower_bound = form_value.Unsigned(); - break; - - case DW_AT_upper_bound: - upper_bound_valid = true; - upper_bound = form_value.Unsigned(); - break; - - default: - case DW_AT_abstract_origin: - case DW_AT_accessibility: - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_declaration: - case DW_AT_description: - case DW_AT_sibling: - case DW_AT_threads_scaled: - case DW_AT_type: - case DW_AT_visibility: - break; - } - } - } - if (num_elements == 0) - { - if (upper_bound_valid && upper_bound >= lower_bound) - num_elements = upper_bound - lower_bound + 1; - } - - element_orders.push_back (num_elements); - } - } - break; - } - } + return namespace_decl_ctx; } TypeSP -SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry* die) +SymbolFileDWARF::GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context) { TypeSP type_sp; - if (die != NULL) + if (die) { - assert(dwarf_cu != NULL); - Type *type_ptr = m_die_to_type.lookup (die); + Type *type_ptr = GetDIEToType().lookup (die.GetDIE()); if (type_ptr == NULL) { - CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(dwarf_cu); + CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU()); assert (lldb_cu); SymbolContext sc(lldb_cu); - type_sp = ParseType(sc, dwarf_cu, die, NULL); + const DWARFDebugInfoEntry* parent_die = die.GetParent().GetDIE(); + while (parent_die != nullptr) + { + if (parent_die->Tag() == DW_TAG_subprogram) + break; + parent_die = parent_die->GetParent(); + } + SymbolContext sc_backup = sc; + if (resolve_function_context && parent_die != nullptr && !GetFunction(DWARFDIE(die.GetCU(),parent_die), sc)) + sc = sc_backup; + + type_sp = ParseType(sc, die, NULL); } else if (type_ptr != DIE_IS_BEING_PARSED) { @@ -4809,215 +3268,57 @@ SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfo return type_sp; } -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset) -{ - if (die_offset != DW_INVALID_OFFSET) - { - DWARFCompileUnitSP cu_sp; - const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp); - return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL); - } - return NULL; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextForDIEOffset (const SymbolContext &sc, dw_offset_t die_offset) -{ - if (die_offset != DW_INVALID_OFFSET) - { - DWARFDebugInfo* debug_info = DebugInfo(); - if (debug_info) - { - DWARFCompileUnitSP cu_sp; - const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(die_offset, &cu_sp); - if (die) - return GetClangDeclContextForDIE (sc, cu_sp.get(), die); - } - } - return NULL; -} - -clang::NamespaceDecl * -SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry *die) -{ - if (die && die->Tag() == DW_TAG_namespace) - { - // See if we already parsed this namespace DIE and associated it with a - // uniqued namespace declaration - clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die]); - if (namespace_decl) - return namespace_decl; - else - { - const char *namespace_name = die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL); - clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL); - namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx); - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); - if (log) - { - if (namespace_name) - { - GetObjectFile()->GetModule()->LogMessage (log, - "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", - static_cast<void*>(GetClangASTContext().getASTContext()), - MakeUserID(die->GetOffset()), - namespace_name, - static_cast<void*>(namespace_decl), - static_cast<void*>(namespace_decl->getOriginalNamespace())); - } - else - { - GetObjectFile()->GetModule()->LogMessage (log, - "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", - static_cast<void*>(GetClangASTContext().getASTContext()), - MakeUserID(die->GetOffset()), - static_cast<void*>(namespace_decl), - static_cast<void*>(namespace_decl->getOriginalNamespace())); - } - } - - if (namespace_decl) - LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); - return namespace_decl; - } - } - return NULL; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) -{ - clang::DeclContext *clang_decl_ctx = GetCachedClangDeclContextForDIE (die); - if (clang_decl_ctx) - return clang_decl_ctx; - // If this DIE has a specification, or an abstract origin, then trace to those. - - dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) - return GetClangDeclContextForDIEOffset (sc, die_offset); - - die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) - return GetClangDeclContextForDIEOffset (sc, die_offset); - - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); - if (log) - GetObjectFile()->GetModule()->LogMessage(log, "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu)); - // This is the DIE we want. Parse it, then query our map. - bool assert_not_being_parsed = true; - ResolveTypeUID (cu, die, assert_not_being_parsed); - - clang_decl_ctx = GetCachedClangDeclContextForDIE (die); - - return clang_decl_ctx; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry **decl_ctx_die_copy) -{ - if (m_clang_tu_decl == NULL) - m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl(); - - const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die); - - if (decl_ctx_die_copy) - *decl_ctx_die_copy = decl_ctx_die; - - if (decl_ctx_die) - { - - DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die); - if (pos != m_die_to_decl_ctx.end()) - return pos->second; - - switch (decl_ctx_die->Tag()) - { - case DW_TAG_compile_unit: - return m_clang_tu_decl; - - case DW_TAG_namespace: - return ResolveNamespaceDIE (cu, decl_ctx_die); - break; - - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: - { - Type* type = ResolveType (cu, decl_ctx_die); - if (type) - { - clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType (); - if (decl_ctx) - { - LinkDeclContextToDIE (decl_ctx, decl_ctx_die); - if (decl_ctx) - return decl_ctx; - } - } - } - break; - - default: - break; - } - } - return m_clang_tu_decl; -} - -const DWARFDebugInfoEntry * -SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) +DWARFDIE +SymbolFileDWARF::GetDeclContextDIEContainingDIE (const DWARFDIE &orig_die) { - if (cu && die) + if (orig_die) { - const DWARFDebugInfoEntry * const decl_die = die; + DWARFDIE die = orig_die; - while (die != NULL) + while (die) { // If this is the original DIE that we are searching for a declaration // for, then don't look in the cache as we don't want our own decl // context to be our decl context... - if (decl_die != die) + if (orig_die != die) { - switch (die->Tag()) + switch (die.Tag()) { case DW_TAG_compile_unit: case DW_TAG_namespace: case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: + case DW_TAG_lexical_block: + case DW_TAG_subprogram: return die; default: break; } } - - dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) + + DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification); + if (spec_die) { - DWARFCompileUnit *spec_cu = cu; - const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu); - const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die); - if (spec_die_decl_ctx_die) - return spec_die_decl_ctx_die; + DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die); + if (decl_ctx_die) + return decl_ctx_die; } - - die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) + + DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin); + if (abs_die) { - DWARFCompileUnit *abs_cu = cu; - const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu); - const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die); - if (abs_die_decl_ctx_die) - return abs_die_decl_ctx_die; + DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die); + if (decl_ctx_die) + return decl_ctx_die; } - - die = die->GetParent(); + + die = die.GetParent(); } } - return NULL; + return DWARFDIE(); } @@ -5075,7 +3376,7 @@ SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu) // This function can be used when a DIE is found that is a forward declaration // DIE and we want to try and find a type that has the complete definition. TypeSP -SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, +SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, const ConstString &type_name, bool must_be_implementation) { @@ -5105,15 +3406,13 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry const size_t num_matches = die_offsets.size(); - DWARFCompileUnit* type_cu = NULL; - const DWARFDebugInfoEntry* type_die = NULL; if (num_matches) { DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE type_die = debug_info->GetDIE (die_ref); if (type_die) { @@ -5122,7 +3421,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry // Don't try and resolve the DIE we are looking for with the DIE itself! if (type_die != die) { - switch (type_die->Tag()) + switch (type_die.Tag()) { case DW_TAG_class_type: case DW_TAG_structure_type: @@ -5135,22 +3434,22 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry if (try_resolving_type) { - if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type()) - try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0); + if (must_be_implementation && type_die.Supports_DW_AT_APPLE_objc_complete_type()) + try_resolving_type = type_die.GetAttributeValueAsUnsigned (DW_AT_APPLE_objc_complete_type, 0); if (try_resolving_type) { - Type *resolved_type = ResolveType (type_cu, type_die, false); + Type *resolved_type = ResolveType (type_die, false, true); if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) { DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", - MakeUserID(die->GetOffset()), + die.GetID(), m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"), - MakeUserID(type_die->GetOffset()), - MakeUserID(type_cu->GetOffset())); + type_die.GetID(), + type_cu->GetID()); if (die) - m_die_to_type[die] = resolved_type; + GetDIEToType()[die.GetDIE()] = resolved_type; type_sp = resolved_type->shared_from_this(); break; } @@ -5162,7 +3461,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, type_name.GetCString()); + die_ref.die_offset, type_name.GetCString()); } } @@ -5185,19 +3484,12 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry // when they don't. //---------------------------------------------------------------------- bool -SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1, - DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2) +SymbolFileDWARF::DIEDeclContextsMatch (const DWARFDIE &die1, + const DWARFDIE &die2) { if (die1 == die2) return true; -#if defined (LLDB_CONFIGURATION_DEBUG) - // You can't and shouldn't call this function with a compile unit from - // two different SymbolFileDWARF instances. - assert (DebugInfo()->ContainsCompileUnit (cu1)); - assert (DebugInfo()->ContainsCompileUnit (cu2)); -#endif - DWARFDIECollection decl_ctx_1; DWARFDIECollection decl_ctx_2; //The declaration DIE stack is a stack of the declaration context @@ -5215,8 +3507,8 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn // all the way back to the compiler unit. // First lets grab the decl contexts for both DIEs - die1->GetDeclContextDIEs (this, cu1, decl_ctx_1); - die2->GetDeclContextDIEs (this, cu2, decl_ctx_2); + die1.GetDeclContextDIEs (decl_ctx_1); + die2.GetDeclContextDIEs (decl_ctx_2); // Make sure the context arrays have the same size, otherwise // we are done const size_t count1 = decl_ctx_1.Size(); @@ -5226,32 +3518,32 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn // Make sure the DW_TAG values match all the way back up the // compile unit. If they don't, then we are done. - const DWARFDebugInfoEntry *decl_ctx_die1; - const DWARFDebugInfoEntry *decl_ctx_die2; + DWARFDIE decl_ctx_die1; + DWARFDIE decl_ctx_die2; size_t i; for (i=0; i<count1; i++) { - decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i); - decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i); - if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag()) + decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); + decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); + if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag()) return false; } #if defined LLDB_CONFIGURATION_DEBUG // Make sure the top item in the decl context die array is always // DW_TAG_compile_unit. If it isn't then something went wrong in - // the DWARFDebugInfoEntry::GetDeclContextDIEs() function... - assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit); + // the DWARFDIE::GetDeclContextDIEs() function... + assert (decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit); #endif // Always skip the compile unit when comparing by only iterating up to // "count - 1". Here we compare the names as we go. for (i=0; i<count1 - 1; i++) { - decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i); - decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i); - const char *name1 = decl_ctx_die1->GetName(this, cu1); - const char *name2 = decl_ctx_die2->GetName(this, cu2); + decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); + decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); + const char *name1 = decl_ctx_die1.GetName(); + const char *name2 = decl_ctx_die2.GetName(); // If the string was from a DW_FORM_strp, then the pointer will often // be the same! if (name1 == name2) @@ -5338,22 +3630,20 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & const size_t num_matches = die_offsets.size(); - DWARFCompileUnit* type_cu = NULL; - const DWARFDebugInfoEntry* type_die = NULL; if (num_matches) { DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE type_die = debug_info->GetDIE (die_ref); if (type_die) { bool try_resolving_type = false; // Don't try and resolve the DIE we are looking for with the DIE itself! - const dw_tag_t type_tag = type_die->Tag(); + const dw_tag_t type_tag = type_die.Tag(); // Make sure the tags match if (type_tag == tag) { @@ -5386,7 +3676,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & if (try_resolving_type) { DWARFDeclContext type_dwarf_decl_ctx; - type_die->GetDWARFDeclContext (this, type_cu, type_dwarf_decl_ctx); + type_die.GetDWARFDeclContext (type_dwarf_decl_ctx); if (log) { @@ -5394,14 +3684,14 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), - type_die->GetOffset(), + type_die.GetOffset(), type_dwarf_decl_ctx.GetQualifiedName()); } // Make sure the decl contexts match all the way up if (dwarf_decl_ctx == type_dwarf_decl_ctx) { - Type *resolved_type = ResolveType (type_cu, type_die, false); + Type *resolved_type = ResolveType (type_die, false); if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) { type_sp = resolved_type->shared_from_this(); @@ -5414,12 +3704,12 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & if (log) { std::string qualified_name; - type_die->GetQualifiedName(this, type_cu, qualified_name); + type_die.GetQualifiedName(qualified_name); GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), - type_die->GetOffset(), + type_die.GetOffset(), qualified_name.c_str()); } } @@ -5429,7 +3719,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & if (m_using_apple_tables) { GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", - die_offset, type_name.GetCString()); + die_ref.die_offset, type_name.GetCString()); } } @@ -5440,1744 +3730,32 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & return type_sp; } -bool -SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile, - Type *class_type, - DWARFCompileUnit* src_cu, - const DWARFDebugInfoEntry *src_class_die, - DWARFCompileUnit* dst_cu, - const DWARFDebugInfoEntry *dst_class_die, - DWARFDIECollection &failures) -{ - if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die) - return false; - if (src_class_die->Tag() != dst_class_die->Tag()) - return false; - - // We need to complete the class type so we can get all of the method types - // parsed so we can then unique those types to their equivalent counterparts - // in "dst_cu" and "dst_class_die" - class_type->GetClangFullType(); - - const DWARFDebugInfoEntry *src_die; - const DWARFDebugInfoEntry *dst_die; - UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die; - UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die; - UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die_artificial; - UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die_artificial; - for (src_die = src_class_die->GetFirstChild(); src_die != NULL; src_die = src_die->GetSibling()) - { - if (src_die->Tag() == DW_TAG_subprogram) - { - // Make sure this is a declaration and not a concrete instance by looking - // for DW_AT_declaration set to 1. Sometimes concrete function instances - // are placed inside the class definitions and shouldn't be included in - // the list of things are are tracking here. - if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_declaration, 0) == 1) - { - const char *src_name = src_die->GetMangledName (src_symfile, src_cu); - if (src_name) - { - ConstString src_const_name(src_name); - if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_artificial, 0)) - src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die); - else - src_name_to_die.Append(src_const_name.GetCString(), src_die); - } - } - } - } - for (dst_die = dst_class_die->GetFirstChild(); dst_die != NULL; dst_die = dst_die->GetSibling()) - { - if (dst_die->Tag() == DW_TAG_subprogram) - { - // Make sure this is a declaration and not a concrete instance by looking - // for DW_AT_declaration set to 1. Sometimes concrete function instances - // are placed inside the class definitions and shouldn't be included in - // the list of things are are tracking here. - if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_declaration, 0) == 1) - { - const char *dst_name = dst_die->GetMangledName (this, dst_cu); - if (dst_name) - { - ConstString dst_const_name(dst_name); - if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_artificial, 0)) - dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die); - else - dst_name_to_die.Append(dst_const_name.GetCString(), dst_die); - } - } - } - } - const uint32_t src_size = src_name_to_die.GetSize (); - const uint32_t dst_size = dst_name_to_die.GetSize (); - Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION)); - - // Is everything kosher so we can go through the members at top speed? - bool fast_path = true; - - if (src_size != dst_size) - { - if (src_size != 0 && dst_size != 0) - { - if (log) - log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)", - src_class_die->GetOffset(), - dst_class_die->GetOffset(), - src_size, - dst_size); - } - - fast_path = false; - } - - uint32_t idx; - - if (fast_path) - { - for (idx = 0; idx < src_size; ++idx) - { - src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); - dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); - - if (src_die->Tag() != dst_die->Tag()) - { - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", - src_class_die->GetOffset(), - dst_class_die->GetOffset(), - src_die->GetOffset(), - DW_TAG_value_to_name(src_die->Tag()), - dst_die->GetOffset(), - DW_TAG_value_to_name(src_die->Tag())); - fast_path = false; - } - - const char *src_name = src_die->GetMangledName (src_symfile, src_cu); - const char *dst_name = dst_die->GetMangledName (this, dst_cu); - - // Make sure the names match - if (src_name == dst_name || (strcmp (src_name, dst_name) == 0)) - continue; - - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", - src_class_die->GetOffset(), - dst_class_die->GetOffset(), - src_die->GetOffset(), - src_name, - dst_die->GetOffset(), - dst_name); - - fast_path = false; - } - } - - // Now do the work of linking the DeclContexts and Types. - if (fast_path) - { - // We can do this quickly. Just run across the tables index-for-index since - // we know each node has matching names and tags. - for (idx = 0; idx < src_size; ++idx) - { - src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); - dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); - - clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die]; - if (src_decl_ctx) - { - if (log) - log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_decl_ctx), - src_die->GetOffset(), dst_die->GetOffset()); - LinkDeclContextToDIE (src_decl_ctx, dst_die); - } - else - { - if (log) - log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", - src_die->GetOffset(), dst_die->GetOffset()); - } - - Type *src_child_type = m_die_to_type[src_die]; - if (src_child_type) - { - if (log) - log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_child_type), - src_child_type->GetID(), - src_die->GetOffset(), dst_die->GetOffset()); - m_die_to_type[dst_die] = src_child_type; - } - else - { - if (log) - log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); - } - } - } - else - { - // We must do this slowly. For each member of the destination, look - // up a member in the source with the same name, check its tag, and - // unique them if everything matches up. Report failures. - - if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) - { - src_name_to_die.Sort(); - - for (idx = 0; idx < dst_size; ++idx) - { - const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx); - dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); - src_die = src_name_to_die.Find(dst_name, NULL); - - if (src_die && (src_die->Tag() == dst_die->Tag())) - { - clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die]; - if (src_decl_ctx) - { - if (log) - log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_decl_ctx), - src_die->GetOffset(), - dst_die->GetOffset()); - LinkDeclContextToDIE (src_decl_ctx, dst_die); - } - else - { - if (log) - log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); - } - - Type *src_child_type = m_die_to_type[src_die]; - if (src_child_type) - { - if (log) - log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_child_type), - src_child_type->GetID(), - src_die->GetOffset(), - dst_die->GetOffset()); - m_die_to_type[dst_die] = src_child_type; - } - else - { - if (log) - log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); - } - } - else - { - if (log) - log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset()); - - failures.Append(dst_die); - } - } - } - } - - const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize (); - const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize (); - - UniqueCStringMap<const DWARFDebugInfoEntry *> name_to_die_artificial_not_in_src; - - if (src_size_artificial && dst_size_artificial) - { - dst_name_to_die_artificial.Sort(); - - for (idx = 0; idx < src_size_artificial; ++idx) - { - const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx); - src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx); - dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL); - - if (dst_die) - { - // Both classes have the artificial types, link them - clang::DeclContext *src_decl_ctx = m_die_to_decl_ctx[src_die]; - if (src_decl_ctx) - { - if (log) - log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_decl_ctx), - src_die->GetOffset(), dst_die->GetOffset()); - LinkDeclContextToDIE (src_decl_ctx, dst_die); - } - else - { - if (log) - log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); - } - - Type *src_child_type = m_die_to_type[src_die]; - if (src_child_type) - { - if (log) - log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void*>(src_child_type), - src_child_type->GetID(), - src_die->GetOffset(), dst_die->GetOffset()); - m_die_to_type[dst_die] = src_child_type; - } - else - { - if (log) - log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); - } - } - } - } - - if (dst_size_artificial) - { - for (idx = 0; idx < dst_size_artificial; ++idx) - { - const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); - dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx); - if (log) - log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial); - - failures.Append(dst_die); - } - } - - return (failures.Size() != 0); -} - TypeSP -SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new_ptr) +SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *type_is_new_ptr) { TypeSP type_sp; - if (type_is_new_ptr) - *type_is_new_ptr = false; - -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) - static DIEStack g_die_stack; - DIEStack::ScopedPopper scoped_die_logger(g_die_stack); -#endif - - AccessType accessibility = eAccessNone; - if (die != NULL) + if (die) { - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); - if (log) - { - const DWARFDebugInfoEntry *context_die; - clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die); - - GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')", - die->GetOffset(), - static_cast<void*>(context), - context_die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); - -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) - scoped_die_logger.Push (dwarf_cu, die); - g_die_stack.LogDIEs(log, this); -#endif - } -// -// Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -// if (log && dwarf_cu) -// { -// StreamString s; -// die->DumpLocation (this, dwarf_cu, s); -// GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); -// -// } - - Type *type_ptr = m_die_to_type.lookup (die); - TypeList* type_list = GetTypeList(); - if (type_ptr == NULL) - { - ClangASTContext &ast = GetClangASTContext(); - if (type_is_new_ptr) - *type_is_new_ptr = true; - - const dw_tag_t tag = die->Tag(); - - bool is_forward_declaration = false; - DWARFDebugInfoEntry::Attributes attributes; - const char *type_name_cstr = NULL; - ConstString type_name_const_str; - Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - uint64_t byte_size = 0; - Declaration decl; - - Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; - ClangASTType clang_type; - DWARFFormValue form_value; - - dw_attr_t attr; - - switch (tag) - { - case DW_TAG_base_type: - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - case DW_TAG_typedef: - case DW_TAG_const_type: - case DW_TAG_restrict_type: - case DW_TAG_volatile_type: - case DW_TAG_unspecified_type: - { - // Set a bit that lets us know that we are currently parsing this - m_die_to_type[die] = DIE_IS_BEING_PARSED; - - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - uint32_t encoding = 0; - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; - - if (num_attributes > 0) - { - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: - - type_name_cstr = form_value.AsCString(&get_debug_str_data()); - // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't - // include the "&"... - if (tag == DW_TAG_reference_type) - { - if (strchr (type_name_cstr, '&') == NULL) - type_name_cstr = NULL; - } - if (type_name_cstr) - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; - case DW_AT_encoding: encoding = form_value.Unsigned(); break; - case DW_AT_type: encoding_uid = form_value.Reference(); break; - default: - case DW_AT_sibling: - break; - } - } - } - } - - DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); - - switch (tag) - { - default: - break; - - case DW_TAG_unspecified_type: - if (strcmp(type_name_cstr, "nullptr_t") == 0 || - strcmp(type_name_cstr, "decltype(nullptr)") == 0 ) - { - resolve_state = Type::eResolveStateFull; - clang_type = ast.GetBasicType(eBasicTypeNullPtr); - break; - } - // Fall through to base type below in case we can handle the type there... - - case DW_TAG_base_type: - resolve_state = Type::eResolveStateFull; - clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, - encoding, - byte_size * 8); - break; - - case DW_TAG_pointer_type: encoding_data_type = Type::eEncodingIsPointerUID; break; - case DW_TAG_reference_type: encoding_data_type = Type::eEncodingIsLValueReferenceUID; break; - case DW_TAG_rvalue_reference_type: encoding_data_type = Type::eEncodingIsRValueReferenceUID; break; - case DW_TAG_typedef: encoding_data_type = Type::eEncodingIsTypedefUID; break; - case DW_TAG_const_type: encoding_data_type = Type::eEncodingIsConstUID; break; - case DW_TAG_restrict_type: encoding_data_type = Type::eEncodingIsRestrictUID; break; - case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break; - } - - if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) - { - bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); - - if (translation_unit_is_objc) - { - if (type_name_cstr != NULL) - { - static ConstString g_objc_type_name_id("id"); - static ConstString g_objc_type_name_Class("Class"); - static ConstString g_objc_type_name_selector("SEL"); - - if (type_name_const_str == g_objc_type_name_id) - { - if (log) - GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); - clang_type = ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; - resolve_state = Type::eResolveStateFull; - - } - else if (type_name_const_str == g_objc_type_name_Class) - { - if (log) - GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); - clang_type = ast.GetBasicType(eBasicTypeObjCClass); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; - resolve_state = Type::eResolveStateFull; - } - else if (type_name_const_str == g_objc_type_name_selector) - { - if (log) - GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); - clang_type = ast.GetBasicType(eBasicTypeObjCSel); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; - resolve_state = Type::eResolveStateFull; - } - } - else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID) - { - // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id". - - DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid); - - if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type) - { - if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL)) - { - if (!strcmp(struct_name, "objc_object")) - { - if (log) - GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); - clang_type = ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; - resolve_state = Type::eResolveStateFull; - } - } - } - } - } - } - - type_sp.reset( new Type (MakeUserID(die->GetOffset()), - this, - type_name_const_str, - byte_size, - NULL, - encoding_uid, - encoding_data_type, - &decl, - clang_type, - resolve_state)); - - m_die_to_type[die] = type_sp.get(); - -// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false); -// if (encoding_type != NULL) -// { -// if (encoding_type != DIE_IS_BEING_PARSED) -// type_sp->SetEncodingType(encoding_type); -// else -// m_indirect_fixups.push_back(type_sp.get()); -// } - } - break; - - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: - { - // Set a bit that lets us know that we are currently parsing this - m_die_to_type[die] = DIE_IS_BEING_PARSED; - bool byte_size_valid = false; - - LanguageType class_language = eLanguageTypeUnknown; - bool is_complete_objc_class = false; - //bool struct_is_class = false; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - if (num_attributes > 0) - { - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: - if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid()) - { - // llvm-gcc outputs invalid DW_AT_decl_file attributes that always - // point to the compile unit file, so we clear this invalid value - // so that we can still unique types efficiently. - decl.SetFile(FileSpec ("<invalid>", false)); - } - else - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); - break; - - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - - case DW_AT_name: - type_name_cstr = form_value.AsCString(&get_debug_str_data()); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - byte_size_valid = true; - break; - - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - - case DW_AT_APPLE_runtime_class: - class_language = (LanguageType)form_value.Signed(); - break; - - case DW_AT_APPLE_objc_complete_type: - is_complete_objc_class = form_value.Signed(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - default: - case DW_AT_sibling: - break; - } - } - } - } - - // UniqueDWARFASTType is large, so don't create a local variables on the - // stack, put it on the heap. This function is often called recursively - // and clang isn't good and sharing the stack space for variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); - - // Only try and unique the type if it has a name. - if (type_name_const_str && - GetUniqueDWARFASTTypeMap().Find (type_name_const_str, - this, - dwarf_cu, - die, - decl, - byte_size_valid ? byte_size : -1, - *unique_ast_entry_ap)) - { - // We have already parsed this type or from another - // compile unit. GCC loves to use the "one definition - // rule" which can result in multiple definitions - // of the same class over and over in each compile - // unit. - type_sp = unique_ast_entry_ap->m_type_sp; - if (type_sp) - { - m_die_to_type[die] = type_sp.get(); - return type_sp; - } - } - - DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) - { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } - else if (tag == DW_TAG_union_type) - { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } - else if (tag == DW_TAG_class_type) - { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } - - if (byte_size_valid && byte_size == 0 && type_name_cstr && - die->HasChildren() == false && - sc.comp_unit->GetLanguage() == eLanguageTypeObjC) - { - // Work around an issue with clang at the moment where - // forward declarations for objective C classes are emitted - // as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are - // no children, and the byte size is zero. - is_forward_declaration = true; - } - - if (class_language == eLanguageTypeObjC || - class_language == eLanguageTypeObjC_plus_plus) - { - if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu)) - { - // We have a valid eSymbolTypeObjCClass class symbol whose - // name matches the current objective C class that we - // are trying to find and this DIE isn't the complete - // definition (we checked is_complete_objc_class above and - // know it is false), so the real definition is in here somewhere - type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); - - if (!type_sp && GetDebugMapSymfile ()) - { - // We weren't able to find a full declaration in - // this DWARF, see if we have a declaration anywhere - // else... - type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); - } - - if (type_sp) - { - if (log) - { - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast<void*>(this), - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr, - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere - // so lets use it and cache the fact that we found - // a complete type for this die - m_die_to_type[die] = type_sp.get(); - return type_sp; - } - } - } - - - if (is_forward_declaration) - { - // We have a forward declaration to a type and we need - // to try and find a full declaration. We look in the - // current type index just in case we have a forward - // declaration followed by an actual declarations in the - // DWARF. If this fails, we need to look elsewhere... - if (log) - { - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", - static_cast<void*>(this), - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr); - } - - DWARFDeclContext die_decl_ctx; - die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx); - - //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); - type_sp = FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); - - if (!type_sp && GetDebugMapSymfile ()) - { - // We weren't able to find a full declaration in - // this DWARF, see if we have a declaration anywhere - // else... - type_sp = m_debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); - } - - if (type_sp) - { - if (log) - { - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, - static_cast<void*>(this), - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr, - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere - // so lets use it and cache the fact that we found - // a complete type for this die - m_die_to_type[die] = type_sp.get(); - return type_sp; - } - } - assert (tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); - if (!clang_type) - { - const DWARFDebugInfoEntry *decl_ctx_die; - - clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die); - if (accessibility == eAccessNone && decl_ctx) - { - // Check the decl context that contains this class/struct/union. - // If it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass (containing_decl_kind)) - accessibility = default_accessibility; - } - - ClangASTMetadata metadata; - metadata.SetUserID(MakeUserID(die->GetOffset())); - metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die)); - - if (type_name_cstr && strchr (type_name_cstr, '<')) - { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos)) - { - clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx, - accessibility, - type_name_cstr, - tag_decl_kind, - template_param_infos); - - clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx, - class_template_decl, - tag_decl_kind, - template_param_infos); - clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl); - clang_type_was_created = true; - - GetClangASTContext().SetMetadata (class_template_decl, metadata); - GetClangASTContext().SetMetadata (class_specialization_decl, metadata); - } - } - - if (!clang_type_was_created) - { - clang_type_was_created = true; - clang_type = ast.CreateRecordType (decl_ctx, - accessibility, - type_name_cstr, - tag_decl_kind, - class_language, - &metadata); - } - } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang - // types for function prototypes. - LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); - type_sp.reset (new Type (MakeUserID(die->GetOffset()), - this, - type_name_const_str, - byte_size, - NULL, - LLDB_INVALID_UID, - Type::eEncodingIsUID, - &decl, - clang_type, - Type::eResolveStateForward)); - - type_sp->SetIsCompleteObjCClass(is_complete_objc_class); - - - // Add our type to the unique type map so we don't - // end up creating many copies of the same type over - // and over in the ASTContext for our module - unique_ast_entry_ap->m_type_sp = type_sp; - unique_ast_entry_ap->m_symfile = this; - unique_ast_entry_ap->m_cu = dwarf_cu; - unique_ast_entry_ap->m_die = die; - unique_ast_entry_ap->m_declaration = decl; - unique_ast_entry_ap->m_byte_size = byte_size; - GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, - *unique_ast_entry_ap); - - if (is_forward_declaration && die->HasChildren()) - { - // Check to see if the DIE actually has a definition, some version of GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram, - // members, or inheritance, so we can't trust it - const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); - while (child_die) - { - switch (child_die->Tag()) - { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die = NULL; - is_forward_declaration = false; - break; - default: - child_die = child_die->GetSibling(); - break; - } - } - } - - if (!is_forward_declaration) - { - // Always start the definition for a class type so that - // if the class has child classes or types that require - // the class to be created for use as their decl contexts - // the class will be ready to accept these child definitions. - if (die->HasChildren() == false) - { - // No children for this struct/union/class, lets finish it - clang_type.StartTagDeclarationDefinition (); - clang_type.CompleteTagDeclarationDefinition (); - - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl(); - - if (record_decl) - m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo())); - } - } - else if (clang_type_was_created) - { - // Start the definition if the class is not objective C since - // the underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ class/union/structs - // we want to start the definition in case the class is needed as the - // declaration context for a contained class or type without the need - // to complete that type.. - - if (class_language != eLanguageTypeObjC && - class_language != eLanguageTypeObjC_plus_plus) - clang_type.StartTagDeclarationDefinition (); - - // Leave this as a forward declaration until we need - // to know the details of the type. lldb_private::Type - // will automatically call the SymbolFile virtual function - // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)" - // When the definition needs to be defined. - m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType(); - m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die; - clang_type.SetHasExternalStorage (true); - } - } - - } - break; - - case DW_TAG_enumeration_type: - { - // Set a bit that lets us know that we are currently parsing this - m_die_to_type[die] = DIE_IS_BEING_PARSED; - - lldb::user_id_t encoding_uid = DW_INVALID_OFFSET; - - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - if (num_attributes > 0) - { - uint32_t i; - - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(&get_debug_str_data()); - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_type: encoding_uid = form_value.Reference(); break; - case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; - case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_bit_stride: - case DW_AT_byte_stride: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } - - DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - - ClangASTType enumerator_clang_type; - clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); - if (!clang_type) - { - if (encoding_uid != DW_INVALID_OFFSET) - { - Type *enumerator_type = ResolveTypeUID(encoding_uid); - if (enumerator_type) - enumerator_clang_type = enumerator_type->GetClangFullType(); - } - - if (!enumerator_clang_type) - enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, - DW_ATE_signed, - byte_size * 8); - - clang_type = ast.CreateEnumerationType (type_name_cstr, - GetClangDeclContextContainingDIE (dwarf_cu, die, NULL), - decl, - enumerator_clang_type); - } - else - { - enumerator_clang_type = clang_type.GetEnumerationIntegerType (); - } - - LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); - - type_sp.reset( new Type (MakeUserID(die->GetOffset()), - this, - type_name_const_str, - byte_size, - NULL, - encoding_uid, - Type::eEncodingIsUID, - &decl, - clang_type, - Type::eResolveStateForward)); - - clang_type.StartTagDeclarationDefinition (); - if (die->HasChildren()) - { - SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); - bool is_signed = false; - enumerator_clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die); - } - clang_type.CompleteTagDeclarationDefinition (); - } - } - break; - - case DW_TAG_inlined_subroutine: - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: - { - // Set a bit that lets us know that we are currently parsing this - m_die_to_type[die] = DIE_IS_BEING_PARSED; - - //const char *mangled = NULL; - dw_offset_t type_die_offset = DW_INVALID_OFFSET; - bool is_variadic = false; - bool is_inline = false; - bool is_static = false; - bool is_virtual = false; - bool is_explicit = false; - bool is_artificial = false; - dw_offset_t specification_die_offset = DW_INVALID_OFFSET; - dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET; - dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; - - unsigned type_quals = 0; - clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern - - - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - if (num_attributes > 0) - { - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(&get_debug_str_data()); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: type_die_offset = form_value.Reference(); break; - case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_inline: is_inline = form_value.Boolean(); break; - case DW_AT_virtuality: is_virtual = form_value.Boolean(); break; - case DW_AT_explicit: is_explicit = form_value.Boolean(); break; - case DW_AT_artificial: is_artificial = form_value.Boolean(); break; - - - case DW_AT_external: - if (form_value.Unsigned()) - { - if (storage == clang::SC_None) - storage = clang::SC_Extern; - else - storage = clang::SC_PrivateExtern; - } - break; - - case DW_AT_specification: - specification_die_offset = form_value.Reference(); - break; - - case DW_AT_abstract_origin: - abstract_origin_die_offset = form_value.Reference(); - break; - - case DW_AT_object_pointer: - object_pointer_die_offset = form_value.Reference(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_address_class: - case DW_AT_calling_convention: - case DW_AT_data_location: - case DW_AT_elemental: - case DW_AT_entry_pc: - case DW_AT_frame_base: - case DW_AT_high_pc: - case DW_AT_low_pc: - case DW_AT_prototyped: - case DW_AT_pure: - case DW_AT_ranges: - case DW_AT_recursive: - case DW_AT_return_addr: - case DW_AT_segment: - case DW_AT_start_scope: - case DW_AT_static_link: - case DW_AT_trampoline: - case DW_AT_visibility: - case DW_AT_vtable_elem_location: - case DW_AT_description: - case DW_AT_sibling: - break; - } - } - } - } - - std::string object_pointer_name; - if (object_pointer_die_offset != DW_INVALID_OFFSET) - { - // Get the name from the object pointer die - StreamString s; - if (DWARFDebugInfoEntry::GetName (this, dwarf_cu, object_pointer_die_offset, s)) - { - object_pointer_name.assign(s.GetData()); - } - } - - DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - - ClangASTType return_clang_type; - Type *func_type = NULL; - - if (type_die_offset != DW_INVALID_OFFSET) - func_type = ResolveTypeUID(type_die_offset); - - if (func_type) - return_clang_type = func_type->GetClangForwardType(); - else - return_clang_type = ast.GetBasicType(eBasicTypeVoid); - - - std::vector<ClangASTType> function_param_types; - std::vector<clang::ParmVarDecl*> function_param_decls; - - // Parse the function children for the parameters - - const DWARFDebugInfoEntry *decl_ctx_die = NULL; - clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die); - const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind(); - - const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind); - // Start off static. This will be set to false in ParseChildParameters(...) - // if we find a "this" parameters as the first parameter - if (is_cxx_method) - is_static = true; - - if (die->HasChildren()) - { - bool skip_artificial = true; - ParseChildParameters (sc, - containing_decl_ctx, - dwarf_cu, - die, - skip_artificial, - is_static, - is_variadic, - function_param_types, - function_param_decls, - type_quals); - } - - // clang_type will get the function prototype clang type after this call - clang_type = ast.CreateFunctionType (return_clang_type, - function_param_types.data(), - function_param_types.size(), - is_variadic, - type_quals); - - bool ignore_containing_context = false; - - if (type_name_cstr) - { - bool type_handled = false; - if (tag == DW_TAG_subprogram) - { - ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true); - if (objc_method.IsValid(true)) - { - ClangASTType class_opaque_type; - ConstString class_name(objc_method.GetClassName()); - if (class_name) - { - TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false)); - - if (complete_objc_class_type_sp) - { - ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType(); - if (type_clang_forward_type.IsObjCObjectOrInterfaceType ()) - class_opaque_type = type_clang_forward_type; - } - } - - if (class_opaque_type) - { - // If accessibility isn't set to anything valid, assume public for - // now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr, - clang_type, - accessibility, - is_artificial); - type_handled = objc_method_decl != NULL; - if (type_handled) - { - LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die); - GetClangASTContext().SetMetadataAsUserID (objc_method_decl, MakeUserID(die->GetOffset())); - } - else - { - GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", - die->GetOffset(), - tag, - DW_TAG_value_to_name(tag)); - } - } - } - else if (is_cxx_method) - { - // Look at the parent of this DIE and see if is is - // a class or struct and see if this is actually a - // C++ method - Type *class_type = ResolveType (dwarf_cu, decl_ctx_die); - if (class_type) - { - if (class_type->GetID() != MakeUserID(decl_ctx_die->GetOffset())) - { - // We uniqued the parent class of this function to another class - // so we now need to associate all dies under "decl_ctx_die" to - // DIEs in the DIE for "class_type"... - SymbolFileDWARF *class_symfile = NULL; - DWARFCompileUnitSP class_type_cu_sp; - const DWARFDebugInfoEntry *class_type_die = NULL; - - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) - { - class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID())); - class_type_die = class_symfile->DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp); - } - else - { - class_symfile = this; - class_type_die = DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp); - } - if (class_type_die) - { - DWARFDIECollection failures; - - CopyUniqueClassMethodTypes (class_symfile, - class_type, - class_type_cu_sp.get(), - class_type_die, - dwarf_cu, - decl_ctx_die, - failures); - - // FIXME do something with these failures that's smarter than - // just dropping them on the ground. Unfortunately classes don't - // like having stuff added to them after their definitions are - // complete... - - type_ptr = m_die_to_type[die]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) - { - type_sp = type_ptr->shared_from_this(); - break; - } - } - } - - if (specification_die_offset != DW_INVALID_OFFSET) - { - // We have a specification which we are going to base our function - // prototype off of, so we need this type to be completed so that the - // m_die_to_decl_ctx for the method in the specification has a valid - // clang decl context. - class_type->GetClangForwardType(); - // If we have a specification, then the function type should have been - // made with the specification and not with this die. - DWARFCompileUnitSP spec_cu_sp; - const DWARFDebugInfoEntry* spec_die = DebugInfo()->GetDIEPtr(specification_die_offset, &spec_cu_sp); - clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, spec_die); - if (spec_clang_decl_ctx) - { - LinkDeclContextToDIE(spec_clang_decl_ctx, die); - } - else - { - GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x) has no decl\n", - MakeUserID(die->GetOffset()), - specification_die_offset); - } - type_handled = true; - } - else if (abstract_origin_die_offset != DW_INVALID_OFFSET) - { - // We have a specification which we are going to base our function - // prototype off of, so we need this type to be completed so that the - // m_die_to_decl_ctx for the method in the abstract origin has a valid - // clang decl context. - class_type->GetClangForwardType(); - - DWARFCompileUnitSP abs_cu_sp; - const DWARFDebugInfoEntry* abs_die = DebugInfo()->GetDIEPtr(abstract_origin_die_offset, &abs_cu_sp); - clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, abs_die); - if (abs_clang_decl_ctx) - { - LinkDeclContextToDIE (abs_clang_decl_ctx, die); - } - else - { - GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x) has no decl\n", - MakeUserID(die->GetOffset()), - abstract_origin_die_offset); - } - type_handled = true; - } - else - { - ClangASTType class_opaque_type = class_type->GetClangForwardType(); - if (class_opaque_type.IsCXXClassType ()) - { - if (class_opaque_type.IsBeingDefined ()) - { - // Neither GCC 4.2 nor clang++ currently set a valid accessibility - // in the DWARF for C++ methods... Default to public for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - if (!is_static && !die->HasChildren()) - { - // We have a C++ member function with no children (this pointer!) - // and clang will get mad if we try and make a function that isn't - // well formed in the DWARF, so we will just skip it... - type_handled = true; - } - else - { - clang::CXXMethodDecl *cxx_method_decl; - // REMOVE THE CRASH DESCRIPTION BELOW - Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s", - type_name_cstr, - class_type->GetName().GetCString(), - MakeUserID(die->GetOffset()), - m_obj_file->GetFileSpec().GetPath().c_str()); - - const bool is_attr_used = false; - - cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr, - clang_type, - accessibility, - is_virtual, - is_static, - is_inline, - is_explicit, - is_attr_used, - is_artificial); - - type_handled = cxx_method_decl != NULL; - - if (type_handled) - { - LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die); - - Host::SetCrashDescription (NULL); - - - ClangASTMetadata metadata; - metadata.SetUserID(MakeUserID(die->GetOffset())); - - if (!object_pointer_name.empty()) - { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf ("Setting object pointer name: %s on method object %p.\n", - object_pointer_name.c_str(), - static_cast<void*>(cxx_method_decl)); - } - GetClangASTContext().SetMetadata (cxx_method_decl, metadata); - } - else - { - ignore_containing_context = true; - } - } - } - else - { - // We were asked to parse the type for a method in a class, yet the - // class hasn't been asked to complete itself through the - // clang::ExternalASTSource protocol, so we need to just have the - // class complete itself and do things the right way, then our - // DIE should then have an entry in the m_die_to_type map. First - // we need to modify the m_die_to_type so it doesn't think we are - // trying to parse this DIE anymore... - m_die_to_type[die] = NULL; - - // Now we get the full type to force our class type to complete itself - // using the clang::ExternalASTSource protocol which will parse all - // base classes and all methods (including the method for this DIE). - class_type->GetClangFullType(); - - // The type for this DIE should have been filled in the function call above - type_ptr = m_die_to_type[die]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) - { - type_sp = type_ptr->shared_from_this(); - break; - } - - // FIXME This is fixing some even uglier behavior but we really need to - // uniq the methods of each class as well as the class itself. - // <rdar://problem/11240464> - type_handled = true; - } - } - } - } - } - } - - if (!type_handled) - { - // We just have a function that isn't part of a class - clang::FunctionDecl *function_decl = ast.CreateFunctionDeclaration (ignore_containing_context ? GetClangASTContext().GetTranslationUnitDecl() : containing_decl_ctx, - type_name_cstr, - clang_type, - storage, - is_inline); - -// if (template_param_infos.GetSize() > 0) -// { -// clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx, -// function_decl, -// type_name_cstr, -// template_param_infos); -// -// ast.CreateFunctionTemplateSpecializationInfo (function_decl, -// func_template_decl, -// template_param_infos); -// } - // Add the decl to our DIE to decl context map - assert (function_decl); - LinkDeclContextToDIE(function_decl, die); - if (!function_param_decls.empty()) - ast.SetFunctionParameters (function_decl, - &function_param_decls.front(), - function_param_decls.size()); - - ClangASTMetadata metadata; - metadata.SetUserID(MakeUserID(die->GetOffset())); - - if (!object_pointer_name.empty()) - { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf ("Setting object pointer name: %s on function object %p.", - object_pointer_name.c_str(), - static_cast<void*>(function_decl)); - } - GetClangASTContext().SetMetadata (function_decl, metadata); - } - } - type_sp.reset( new Type (MakeUserID(die->GetOffset()), - this, - type_name_const_str, - 0, - NULL, - LLDB_INVALID_UID, - Type::eEncodingIsUID, - &decl, - clang_type, - Type::eResolveStateFull)); - assert(type_sp.get()); - } - break; - - case DW_TAG_array_type: - { - // Set a bit that lets us know that we are currently parsing this - m_die_to_type[die] = DIE_IS_BEING_PARSED; - - lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; - int64_t first_index = 0; - uint32_t byte_stride = 0; - uint32_t bit_stride = 0; - bool is_vector = false; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - - if (num_attributes > 0) - { - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(&get_debug_str_data()); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_type: type_die_offset = form_value.Reference(); break; - case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break; - case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; - case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break; - case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break; - case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_ordering: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } - - DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - - Type *element_type = ResolveTypeUID(type_die_offset); - - if (element_type) - { - std::vector<uint64_t> element_orders; - ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride); - if (byte_stride == 0 && bit_stride == 0) - byte_stride = element_type->GetByteSize(); - ClangASTType array_element_type = element_type->GetClangForwardType(); - uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - if (element_orders.size() > 0) - { - uint64_t num_elements = 0; - std::vector<uint64_t>::const_reverse_iterator pos; - std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend(); - for (pos = element_orders.rbegin(); pos != end; ++pos) - { - num_elements = *pos; - clang_type = ast.CreateArrayType (array_element_type, - num_elements, - is_vector); - array_element_type = clang_type; - array_element_bit_stride = num_elements ? - array_element_bit_stride * num_elements : - array_element_bit_stride; - } - } - else - { - clang_type = ast.CreateArrayType (array_element_type, 0, is_vector); - } - ConstString empty_name; - type_sp.reset( new Type (MakeUserID(die->GetOffset()), - this, - empty_name, - array_element_bit_stride / 8, - NULL, - type_die_offset, - Type::eEncodingIsUID, - &decl, - clang_type, - Type::eResolveStateFull)); - type_sp->SetEncodingType (element_type); - } - } - } - break; + TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - case DW_TAG_ptr_to_member_type: - { - dw_offset_t type_die_offset = DW_INVALID_OFFSET; - dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET; - - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - - if (num_attributes > 0) { - uint32_t i; - for (i=0; i<num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) - { - switch (attr) - { - case DW_AT_type: - type_die_offset = form_value.Reference(); break; - case DW_AT_containing_type: - containing_type_die_offset = form_value.Reference(); break; - } - } - } - - Type *pointee_type = ResolveTypeUID(type_die_offset); - Type *class_type = ResolveTypeUID(containing_type_die_offset); - - ClangASTType pointee_clang_type = pointee_type->GetClangForwardType(); - ClangASTType class_clang_type = class_type->GetClangLayoutType(); - - clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type); - - byte_size = clang_type.GetByteSize(nullptr); - - type_sp.reset( new Type (MakeUserID(die->GetOffset()), - this, - type_name_const_str, - byte_size, - NULL, - LLDB_INVALID_UID, - Type::eEncodingIsUID, - NULL, - clang_type, - Type::eResolveStateForward)); - } - - break; - } - default: - GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", - die->GetOffset(), - tag, - DW_TAG_value_to_name(tag)); - break; - } - - if (type_sp.get()) + if (type_system) + { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast) { - const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; - - SymbolContextScope * symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit) + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, type_is_new_ptr); + if (type_sp) { - symbol_context_scope = sc.comp_unit; + TypeList* type_list = GetTypeList(); + if (type_list) + type_list->Insert(type_sp); } - else if (sc.function != NULL && sc_parent_die) - { - symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } - - if (symbol_context_scope != NULL) - { - type_sp->SetSymbolContextScope(symbol_context_scope); - } - - // We are ready to put this type into the uniqued list up at the module level - type_list->Insert (type_sp); - - m_die_to_type[die] = type_sp.get(); } } - else if (type_ptr != DIE_IS_BEING_PARSED) - { - type_sp = type_ptr->shared_from_this(); - } } + return type_sp; } @@ -7185,38 +3763,38 @@ size_t SymbolFileDWARF::ParseTypes ( const SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, + const DWARFDIE &orig_die, bool parse_siblings, bool parse_children ) { size_t types_added = 0; - while (die != NULL) + DWARFDIE die = orig_die; + while (die) { bool type_is_new = false; - if (ParseType(sc, dwarf_cu, die, &type_is_new).get()) + if (ParseType(sc, die, &type_is_new).get()) { if (type_is_new) ++types_added; } - if (parse_children && die->HasChildren()) + if (parse_children && die.HasChildren()) { - if (die->Tag() == DW_TAG_subprogram) + if (die.Tag() == DW_TAG_subprogram) { SymbolContext child_sc(sc); - child_sc.function = sc.comp_unit->FindFunctionByUID(MakeUserID(die->GetOffset())).get(); - types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true); + child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); + types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true); } else - types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true); + types_added += ParseTypes(sc, die.GetFirstChild(), true, true); } if (parse_siblings) - die = die->GetSibling(); + die = die.GetSibling(); else - die = NULL; + die.Clear(); } return types_added; } @@ -7230,11 +3808,11 @@ SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc) DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (dwarf_cu) { - dw_offset_t function_die_offset = sc.function->GetID(); - const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset); + const dw_offset_t function_die_offset = sc.function->GetID(); + DWARFDIE function_die = dwarf_cu->GetDIE (function_die_offset); if (function_die) { - ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, 0); + ParseFunctionBlocks(sc, &sc.function->GetBlock (false), function_die, LLDB_INVALID_ADDRESS, 0); } } @@ -7254,18 +3832,18 @@ SymbolFileDWARF::ParseTypes (const SymbolContext &sc) if (sc.function) { dw_offset_t function_die_offset = sc.function->GetID(); - const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset); - if (func_die && func_die->HasChildren()) + DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset); + if (func_die && func_die.HasChildren()) { - types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true); + types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true); } } else { - const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE(); - if (dwarf_cu_die && dwarf_cu_die->HasChildren()) + DWARFDIE dwarf_cu_die = dwarf_cu->DIE(); + if (dwarf_cu_die && dwarf_cu_die.HasChildren()) { - types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true); + types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true); } } } @@ -7284,17 +3862,12 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) if (sc.function) { - DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get(); + DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID())); - if (dwarf_cu == NULL) - return 0; - - const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID()); - - dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); + const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (func_lo_pc != LLDB_INVALID_ADDRESS) { - const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true); + const size_t num_variables = ParseVariables(sc, function_die.GetFirstChild(), func_lo_pc, true, true); // Let all blocks know they have parse all their variables sc.function->GetBlock (false).SetDidParseVariables (true, true); @@ -7303,7 +3876,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) } else if (sc.comp_unit) { - DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get(); + DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()); if (dwarf_cu == NULL) return 0; @@ -7316,8 +3889,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) variables.reset(new VariableList()); sc.comp_unit->SetVariableList(variables); - DWARFCompileUnit* match_dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; DIEArray die_offsets; if (m_using_apple_tables) { @@ -7340,7 +3911,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) Index (); m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(), - dwarf_cu->GetNextCompileUnitOffset(), die_offsets); } @@ -7350,11 +3920,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; i<num_matches; ++i) { - const dw_offset_t die_offset = die_offsets[i]; - die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &match_dwarf_cu); + const DIERef& die_ref = die_offsets[i]; + DWARFDIE die = debug_info->GetDIE (die_ref); if (die) { - VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, LLDB_INVALID_ADDRESS)); + VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS)); if (var_sp) { variables->AddVariableIfUnique (var_sp); @@ -7365,7 +3935,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) { if (m_using_apple_tables) { - GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_ref.die_offset); } } @@ -7378,37 +3948,43 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) return 0; } - VariableSP SymbolFileDWARF::ParseVariableDIE ( const SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, + const DWARFDIE &die, const lldb::addr_t func_low_pc ) { - VariableSP var_sp (m_die_to_variable_sp[die]); + if (die.GetDWARF() != this) + return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc); + + VariableSP var_sp; + if (!die) + return var_sp; + + var_sp = GetDIEToVariable()[die.GetDIE()]; if (var_sp) return var_sp; // Already been parsed! - const dw_tag_t tag = die->Tag(); + const dw_tag_t tag = die.Tag(); ModuleSP module = GetObjectFile()->GetModule(); if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) || (tag == DW_TAG_formal_parameter && sc.function)) { - DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + DWARFDIE spec_die; if (num_attributes > 0) { const char *name = NULL; const char *mangled = NULL; Declaration decl; uint32_t i; - lldb::user_id_t type_uid = LLDB_INVALID_UID; - DWARFExpression location; + DWARFFormValue type_die_form; + DWARFExpression location(die.GetCU()); bool is_external = false; bool is_artificial = false; bool location_is_const_value_data = false; @@ -7421,17 +3997,17 @@ SymbolFileDWARF::ParseVariableDIE dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(this, i, form_value)) + if (attributes.ExtractFormValueAtIndex(i, form_value)) { switch (attr) { case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; - case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; + case DW_AT_name: name = form_value.AsCString(); break; case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: type_uid = form_value.Reference(); break; + case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(); break; + case DW_AT_type: type_die_form = form_value; break; case DW_AT_external: is_external = form_value.Boolean(); break; case DW_AT_const_value: // If we have already found a DW_AT_location attribute, ignore this attribute. @@ -7450,9 +4026,12 @@ SymbolFileDWARF::ParseVariableDIE else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize ( + attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), + attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); - uint32_t data_length = fixed_form_sizes[form_value.Form()]; + uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form()); if (data_length == 0) { const uint8_t *data_pointer = form_value.BlockData(); @@ -7474,14 +4053,17 @@ SymbolFileDWARF::ParseVariableDIE // Retrieve the value as a string expression. if (form_value.Form() == DW_FORM_strp) { - const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize ( + attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), + attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); - uint32_t data_length = fixed_form_sizes[form_value.Form()]; + uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form()); location.CopyOpcodeData(module, debug_info_data, data_offset, data_length); } else { - const char *str = form_value.AsCString(&debug_info_data); + const char *str = form_value.AsCString(); uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); uint32_t string_length = strlen(str) + 1; location.CopyOpcodeData(module, debug_info_data, string_offset, string_length); @@ -7503,10 +4085,10 @@ SymbolFileDWARF::ParseVariableDIE } else { - const DWARFDataExtractor& debug_loc_data = get_debug_loc_data(); + const DWARFDataExtractor& debug_loc_data = get_debug_loc_data(); const dw_offset_t debug_loc_offset = form_value.Unsigned(); - size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset); + size_t loc_list_length = DWARFExpression::LocationListSize(die.GetCU(), debug_loc_data, debug_loc_offset); if (loc_list_length > 0) { location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); @@ -7516,7 +4098,13 @@ SymbolFileDWARF::ParseVariableDIE } } break; - + case DW_AT_specification: + { + DWARFDebugInfo* debug_info = DebugInfo(); + if (debug_info) + spec_die = debug_info->GetDIE(DIERef(form_value)); + break; + } case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: @@ -7528,16 +4116,18 @@ SymbolFileDWARF::ParseVariableDIE default: case DW_AT_abstract_origin: case DW_AT_sibling: - case DW_AT_specification: break; } } } + const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); + const dw_tag_t parent_tag = die.GetParent().Tag(); + bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type); + ValueType scope = eValueTypeInvalid; - const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); - dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; + const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); SymbolContextScope * symbol_context_scope = NULL; if (!mangled) @@ -7548,12 +4138,12 @@ SymbolFileDWARF::ParseVariableDIE // B which in turn is contained in a namespace A, the command "frame var j" returns // "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able // to generate a fully qualified name from the declaration context. - if (die->GetParent()->Tag() == DW_TAG_compile_unit && - LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType())) + if (parent_tag == DW_TAG_compile_unit && + Language::LanguageIsCPlusPlus(die.GetLanguage())) { DWARFDeclContext decl_ctx; - die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx); + die.GetDWARFDeclContext(decl_ctx); mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString(); } } @@ -7582,7 +4172,7 @@ SymbolFileDWARF::ParseVariableDIE { StreamString strm; location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL); - GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str()); + GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str()); } } @@ -7670,7 +4260,10 @@ SymbolFileDWARF::ParseVariableDIE } else { - scope = eValueTypeVariableLocal; + if (location_is_const_value_data) + scope = eValueTypeVariableStatic; + else + scope = eValueTypeVariableLocal; } } @@ -7683,7 +4276,7 @@ SymbolFileDWARF::ParseVariableDIE case DW_TAG_lexical_block: if (sc.function) { - symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); + symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); if (symbol_context_scope == NULL) symbol_context_scope = sc.function; } @@ -7697,12 +4290,12 @@ SymbolFileDWARF::ParseVariableDIE if (symbol_context_scope) { - SymbolFileTypeSP type_sp(new SymbolFileType(*this, type_uid)); + SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID())); if (const_value.Form() && type_sp && type_sp->GetType()) - location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), dwarf_cu->GetAddressByteSize()); + location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize()); - var_sp.reset (new Variable (MakeUserID(die->GetOffset()), + var_sp.reset (new Variable (die.GetID(), name, mangled, type_sp, @@ -7711,7 +4304,8 @@ SymbolFileDWARF::ParseVariableDIE &decl, location, is_external, - is_artificial)); + is_artificial, + is_static_member)); var_sp->SetLocationIsConstantValueData (location_is_const_value_data); } @@ -7727,57 +4321,42 @@ SymbolFileDWARF::ParseVariableDIE // was missing vital information to be able to be displayed in the debugger // (missing location due to optimization, etc)) so we don't re-parse // this DIE over and over later... - m_die_to_variable_sp[die] = var_sp; + GetDIEToVariable()[die.GetDIE()] = var_sp; + if (spec_die) + GetDIEToVariable()[spec_die.GetDIE()] = var_sp; } return var_sp; } -const DWARFDebugInfoEntry * -SymbolFileDWARF::FindBlockContainingSpecification (dw_offset_t func_die_offset, - dw_offset_t spec_block_die_offset, - DWARFCompileUnit **result_die_cu_handle) +DWARFDIE +SymbolFileDWARF::FindBlockContainingSpecification (const DIERef& func_die_ref, + dw_offset_t spec_block_die_offset) { // Give the concrete function die specified by "func_die_offset", find the // concrete block whose DW_AT_specification or DW_AT_abstract_origin points // to "spec_block_die_offset" - DWARFDebugInfo* info = DebugInfo(); - - const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint(func_die_offset, result_die_cu_handle); - if (die) - { - assert (*result_die_cu_handle); - return FindBlockContainingSpecification (*result_die_cu_handle, die, spec_block_die_offset, result_die_cu_handle); - } - return NULL; + return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), spec_block_die_offset); } -const DWARFDebugInfoEntry * -SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - dw_offset_t spec_block_die_offset, - DWARFCompileUnit **result_die_cu_handle) +DWARFDIE +SymbolFileDWARF::FindBlockContainingSpecification(const DWARFDIE &die, + dw_offset_t spec_block_die_offset) { if (die) { - switch (die->Tag()) + switch (die.Tag()) { case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: { - if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset) - { - *result_die_cu_handle = dwarf_cu; + if (die.GetAttributeValueAsReference (DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset) return die; - } - if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset) - { - *result_die_cu_handle = dwarf_cu; + if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset) return die; - } } break; } @@ -7785,49 +4364,42 @@ SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu, // Give the concrete function die specified by "func_die_offset", find the // concrete block whose DW_AT_specification or DW_AT_abstract_origin points // to "spec_block_die_offset" - for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); child_die != NULL; child_die = child_die->GetSibling()) + for (DWARFDIE child_die = die.GetFirstChild(); child_die; child_die = child_die.GetSibling()) { - const DWARFDebugInfoEntry *result_die = FindBlockContainingSpecification (dwarf_cu, - child_die, - spec_block_die_offset, - result_die_cu_handle); + DWARFDIE result_die = FindBlockContainingSpecification (child_die, spec_block_die_offset); if (result_die) return result_die; } } - *result_die_cu_handle = NULL; - return NULL; + return DWARFDIE(); } size_t -SymbolFileDWARF::ParseVariables -( - const SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const lldb::addr_t func_low_pc, - const DWARFDebugInfoEntry *orig_die, - bool parse_siblings, - bool parse_children, - VariableList* cc_variable_list -) +SymbolFileDWARF::ParseVariables (const SymbolContext& sc, + const DWARFDIE &orig_die, + const lldb::addr_t func_low_pc, + bool parse_siblings, + bool parse_children, + VariableList* cc_variable_list) { - if (orig_die == NULL) + if (!orig_die) return 0; VariableListSP variable_list_sp; size_t vars_added = 0; - const DWARFDebugInfoEntry *die = orig_die; - while (die != NULL) + DWARFDIE die = orig_die; + while (die) { - dw_tag_t tag = die->Tag(); + dw_tag_t tag = die.Tag(); // Check to see if we have already parsed this variable or constant? - if (m_die_to_variable_sp[die]) + VariableSP var_sp = GetDIEToVariable()[die.GetDIE()]; + if (var_sp) { if (cc_variable_list) - cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]); + cc_variable_list->AddVariableIfUnique (var_sp); } else { @@ -7838,8 +4410,8 @@ SymbolFileDWARF::ParseVariables { if (variable_list_sp.get() == NULL) { - const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die); - dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; + DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die); + dw_tag_t parent_tag = sc_parent_die.Tag(); switch (parent_tag) { case DW_TAG_compile_unit: @@ -7855,10 +4427,10 @@ SymbolFileDWARF::ParseVariables else { GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64 " %s.\n", - MakeUserID(sc_parent_die->GetOffset()), - DW_TAG_value_to_name (parent_tag), - MakeUserID(orig_die->GetOffset()), - DW_TAG_value_to_name (orig_die->Tag())); + sc_parent_die.GetID(), + sc_parent_die.GetTagAsCString(), + orig_die.GetID(), + orig_die.GetTagAsCString()); } break; @@ -7869,19 +4441,17 @@ SymbolFileDWARF::ParseVariables { // Check to see if we already have parsed the variables for the given scope - Block *block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); + Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); if (block == NULL) { // This must be a specification or abstract origin with // a concrete block counterpart in the current function. We need // to find the concrete block so we can correctly add the // variable to it - DWARFCompileUnit *concrete_block_die_cu = dwarf_cu; - const DWARFDebugInfoEntry *concrete_block_die = FindBlockContainingSpecification (sc.function->GetID(), - sc_parent_die->GetOffset(), - &concrete_block_die_cu); + const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()), + sc_parent_die.GetOffset()); if (concrete_block_die) - block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(concrete_block_die->GetOffset())); + block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID()); } if (block != NULL) @@ -7899,15 +4469,15 @@ SymbolFileDWARF::ParseVariables default: GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64 " %s.\n", - MakeUserID(orig_die->GetOffset()), - DW_TAG_value_to_name (orig_die->Tag())); + orig_die.GetID(), + orig_die.GetTagAsCString()); break; } } if (variable_list_sp) { - VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc)); + VariableSP var_sp (ParseVariableDIE(sc, die, func_low_pc)); if (var_sp) { variable_list_sp->AddVariableIfUnique (var_sp); @@ -7921,15 +4491,15 @@ SymbolFileDWARF::ParseVariables bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); - if (!skip_children && parse_children && die->HasChildren()) + if (!skip_children && parse_children && die.HasChildren()) { - vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list); + vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, true, cc_variable_list); } if (parse_siblings) - die = die->GetSibling(); + die = die.GetSibling(); else - die = NULL; + die.Clear(); } return vars_added; } @@ -7950,24 +4520,6 @@ SymbolFileDWARF::GetPluginVersion() } void -SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl) -{ - SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; - ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); - if (clang_type) - symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -} - -void -SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl) -{ - SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; - ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); - if (clang_type) - symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -} - -void SymbolFileDWARF::DumpIndexes () { StreamFile s(stdout, false); @@ -7982,147 +4534,7 @@ SymbolFileDWARF::DumpIndexes () s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s); s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s); s.Printf("\nTypes:\n"); m_type_index.Dump (&s); - s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s); -} - -void -SymbolFileDWARF::SearchDeclContext (const clang::DeclContext *decl_context, - const char *name, - llvm::SmallVectorImpl <clang::NamedDecl *> *results) -{ - DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find(decl_context); - - if (iter == m_decl_ctx_to_die.end()) - return; - - for (DIEPointerSet::iterator pos = iter->second.begin(), end = iter->second.end(); pos != end; ++pos) - { - const DWARFDebugInfoEntry *context_die = *pos; - - if (!results) - return; - - DWARFDebugInfo* info = DebugInfo(); - - DIEArray die_offsets; - - DWARFCompileUnit* dwarf_cu = NULL; - const DWARFDebugInfoEntry* die = NULL; - - if (m_using_apple_tables) - { - if (m_apple_types_ap.get()) - m_apple_types_ap->FindByName (name, die_offsets); - } - else - { - if (!m_indexed) - Index (); - - m_type_index.Find (ConstString(name), die_offsets); - } - - const size_t num_matches = die_offsets.size(); - - if (num_matches) - { - for (size_t i = 0; i < num_matches; ++i) - { - const dw_offset_t die_offset = die_offsets[i]; - die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); - - if (die->GetParent() != context_die) - continue; - - Type *matching_type = ResolveType (dwarf_cu, die); - - clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType(); - - if (const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr())) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - results->push_back(tag_decl); - } - else if (const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(qual_type.getTypePtr())) - { - clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - results->push_back(typedef_decl); - } - } - } - } -} - -void -SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton, - const clang::DeclContext *decl_context, - clang::DeclarationName decl_name, - llvm::SmallVectorImpl <clang::NamedDecl *> *results) -{ - - switch (decl_context->getDeclKind()) - { - case clang::Decl::Namespace: - case clang::Decl::TranslationUnit: - { - SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; - symbol_file_dwarf->SearchDeclContext (decl_context, decl_name.getAsString().c_str(), results); - } - break; - default: - break; - } -} - -bool -SymbolFileDWARF::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, - uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ - SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; - return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets); -} - -bool -SymbolFileDWARF::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); - RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl); - bool success = false; - base_offsets.clear(); - vbase_offsets.clear(); - if (pos != m_record_decl_to_layout_map.end()) - { - bit_size = pos->second.bit_size; - alignment = pos->second.alignment; - field_offsets.swap(pos->second.field_offsets); - base_offsets.swap (pos->second.base_offsets); - vbase_offsets.swap (pos->second.vbase_offsets); - m_record_decl_to_layout_map.erase(pos); - success = true; - } - else - { - bit_size = 0; - alignment = 0; - field_offsets.clear(); - } - - if (log) - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i", - static_cast<const void*>(record_decl), - bit_size, alignment, - static_cast<uint32_t>(field_offsets.size()), - static_cast<uint32_t>(base_offsets.size()), - static_cast<uint32_t>(vbase_offsets.size()), - success); - return success; + s.Printf("\nNamespaces:\n"); m_namespace_index.Dump (&s); } @@ -8142,4 +4554,8 @@ SymbolFileDWARF::GetDebugMapSymfile () return m_debug_map_symfile; } - +DWARFExpression::LocationListFormat +SymbolFileDWARF::GetLocationListFormat() const +{ + return DWARFExpression::RegularLocationList; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2f0b3f05b153..c2e78a417b7a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -14,24 +14,22 @@ // C++ Includes #include <list> #include <map> +#include <mutex> #include <set> +#include <unordered_map> #include <vector> // Other libraries and framework includes -#include "clang/AST/CharUnits.h" -#include "clang/AST/ExternalASTSource.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Flags.h" #include "lldb/Core/RangeMap.h" #include "lldb/Core/UniqueCStringMap.h" -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -61,12 +59,18 @@ class DWARFDIECollection; class DWARFFormValue; class SymbolFileDWARFDebugMap; +#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1) + class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID { public: friend class SymbolFileDWARFDebugMap; + friend class SymbolFileDWARFDwo; friend class DebugMapModule; friend class DWARFCompileUnit; + friend class DWARFASTParserClang; + friend class DWARFASTParserGo; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -76,6 +80,9 @@ public: static void Terminate(); + static void + DebuggerInitialize(lldb_private::Debugger &debugger); + static lldb_private::ConstString GetPluginNameStatic(); @@ -84,481 +91,419 @@ public: static lldb_private::SymbolFile* CreateInstance (lldb_private::ObjectFile* obj_file); + //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - SymbolFileDWARF(lldb_private::ObjectFile* ofile); - virtual ~SymbolFileDWARF(); - virtual uint32_t CalculateAbilities (); - virtual void InitializeObject(); + SymbolFileDWARF(lldb_private::ObjectFile* ofile); + + ~SymbolFileDWARF() override; + + uint32_t + CalculateAbilities () override; + + void + InitializeObject() override; //------------------------------------------------------------------ // Compile Unit function calls //------------------------------------------------------------------ - virtual uint32_t GetNumCompileUnits(); - virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index); - - virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc); - virtual size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc); - virtual bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc); - virtual bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files); - virtual bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules); - virtual size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc); - virtual size_t ParseTypes (const lldb_private::SymbolContext& sc); - virtual size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc); - - virtual lldb_private::Type* ResolveTypeUID(lldb::user_id_t type_uid); - virtual bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type); - - virtual lldb_private::Type* ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed = true); - virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid); - virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid); - - virtual uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc); - virtual uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list); - virtual uint32_t FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables); - virtual uint32_t FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables); - virtual uint32_t FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); - virtual uint32_t FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); - virtual uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types); - virtual lldb_private::TypeList * - GetTypeList (); - virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope, - uint32_t type_mask, - lldb_private::TypeList &type_list); - - virtual lldb_private::ClangASTContext & - GetClangASTContext (); - - virtual lldb_private::ClangNamespaceDecl - FindNamespace (const lldb_private::SymbolContext& sc, - const lldb_private::ConstString &name, - const lldb_private::ClangNamespaceDecl *parent_namespace_decl); + uint32_t + GetNumCompileUnits() override; - //------------------------------------------------------------------ - // ClangASTContext callbacks for external source lookups. - //------------------------------------------------------------------ - static void - CompleteTagDecl (void *baton, clang::TagDecl *); - - static void - CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); + lldb::CompUnitSP + ParseCompileUnitAtIndex(uint32_t index) override; + + lldb::LanguageType + ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override; + + size_t + ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override; + + bool + ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; + + bool + ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override; + + bool + ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, + lldb_private::FileSpecList& support_files) override; + + bool + ParseImportedModules (const lldb_private::SymbolContext &sc, + std::vector<lldb_private::ConstString> &imported_modules) override; + + size_t + ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; + + size_t + ParseTypes (const lldb_private::SymbolContext& sc) override; + + size_t + ParseVariablesForContext (const lldb_private::SymbolContext& sc) override; + + lldb_private::Type * + ResolveTypeUID(lldb::user_id_t type_uid) override; + + bool + CompleteType (lldb_private::CompilerType& compiler_type) override; + + lldb_private::Type * + ResolveType (const DWARFDIE &die, + bool assert_not_being_parsed = true, + bool resolve_function_context = false); + + lldb_private::CompilerDecl + GetDeclForUID (lldb::user_id_t uid) override; + + lldb_private::CompilerDeclContext + GetDeclContextForUID (lldb::user_id_t uid) override; + + lldb_private::CompilerDeclContext + GetDeclContextContainingUID (lldb::user_id_t uid) override; + + void + ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override; - static void - FindExternalVisibleDeclsByName (void *baton, - const clang::DeclContext *DC, - clang::DeclarationName Name, - llvm::SmallVectorImpl <clang::NamedDecl *> *results); - - static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); - - bool LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); - - struct LayoutInfo - { - LayoutInfo () : - bit_size(0), - alignment(0), - field_offsets(), - base_offsets(), - vbase_offsets() - { - } - uint64_t bit_size; - uint64_t alignment; - llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; - }; + + uint32_t + ResolveSymbolContext (const lldb_private::Address& so_addr, + uint32_t resolve_scope, + lldb_private::SymbolContext& sc) override; + + uint32_t + ResolveSymbolContext (const lldb_private::FileSpec& file_spec, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + lldb_private::SymbolContextList& sc_list) override; + + uint32_t + FindGlobalVariables (const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + bool append, + uint32_t max_matches, + lldb_private::VariableList& variables) override; + + uint32_t + FindGlobalVariables (const lldb_private::RegularExpression& regex, + bool append, + uint32_t max_matches, + lldb_private::VariableList& variables) override; + + uint32_t + FindFunctions (const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, + bool include_inlines, + bool append, + lldb_private::SymbolContextList& sc_list) override; + + uint32_t + FindFunctions (const lldb_private::RegularExpression& regex, + bool include_inlines, + bool append, + lldb_private::SymbolContextList& sc_list) override; + + uint32_t + FindTypes (const lldb_private::SymbolContext& sc, + const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + bool append, + uint32_t max_matches, + lldb_private::TypeMap& types) override; + + size_t + FindTypes (const std::vector<lldb_private::CompilerContext> &context, + bool append, + lldb_private::TypeMap& types) override; + + lldb_private::TypeList * + GetTypeList () override; + + size_t + GetTypes (lldb_private::SymbolContextScope *sc_scope, + uint32_t type_mask, + lldb_private::TypeList &type_list) override; + + lldb_private::TypeSystem * + GetTypeSystemForLanguage (lldb::LanguageType language) override; + + lldb_private::CompilerDeclContext + FindNamespace (const lldb_private::SymbolContext& sc, + const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx) override; + + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; - // Approach 2 - count + accessor - // Index compile units would scan the initial compile units and register - // them with the module. This would only be done on demand if and only if - // the compile units were needed. - //virtual size_t GetCompUnitCount() = 0; - //virtual CompUnitSP GetCompUnitAtIndex(size_t cu_idx) = 0; + uint32_t + GetPluginVersion() override; const lldb_private::DWARFDataExtractor& get_debug_abbrev_data (); + const lldb_private::DWARFDataExtractor& get_debug_addr_data (); const lldb_private::DWARFDataExtractor& get_debug_aranges_data (); const lldb_private::DWARFDataExtractor& get_debug_frame_data (); const lldb_private::DWARFDataExtractor& get_debug_info_data (); const lldb_private::DWARFDataExtractor& get_debug_line_data (); + const lldb_private::DWARFDataExtractor& get_debug_macro_data (); const lldb_private::DWARFDataExtractor& get_debug_loc_data (); const lldb_private::DWARFDataExtractor& get_debug_ranges_data (); const lldb_private::DWARFDataExtractor& get_debug_str_data (); + const lldb_private::DWARFDataExtractor& get_debug_str_offsets_data (); const lldb_private::DWARFDataExtractor& get_apple_names_data (); const lldb_private::DWARFDataExtractor& get_apple_types_data (); const lldb_private::DWARFDataExtractor& get_apple_namespaces_data (); const lldb_private::DWARFDataExtractor& get_apple_objc_data (); - DWARFDebugAbbrev* DebugAbbrev(); - const DWARFDebugAbbrev* DebugAbbrev() const; + DWARFDebugAbbrev* + DebugAbbrev(); - DWARFDebugInfo* DebugInfo(); - const DWARFDebugInfo* DebugInfo() const; + const DWARFDebugAbbrev* + DebugAbbrev() const; - DWARFDebugRanges* DebugRanges(); - const DWARFDebugRanges* DebugRanges() const; + DWARFDebugInfo* + DebugInfo(); - const lldb_private::DWARFDataExtractor& - GetCachedSectionData (uint32_t got_flag, - lldb::SectionType sect_type, - lldb_private::DWARFDataExtractor &data); + const DWARFDebugInfo* + DebugInfo() const; + + DWARFDebugRanges* + DebugRanges(); + + const DWARFDebugRanges* + DebugRanges() const; static bool SupportedVersion(uint16_t version); - clang::DeclContext * - GetCachedClangDeclContextForDIE (const DWARFDebugInfoEntry *die) - { - DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die); - if (pos != m_die_to_decl_ctx.end()) - return pos->second; - else - return NULL; - } + DWARFDIE + GetDeclContextDIEContainingDIE (const DWARFDIE &die); - clang::DeclContext * - GetClangDeclContextForDIE (const lldb_private::SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die); - - clang::DeclContext * - GetClangDeclContextForDIEOffset (const lldb_private::SymbolContext &sc, dw_offset_t die_offset); - - clang::DeclContext * - GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, - const DWARFDebugInfoEntry **decl_ctx_die); - - clang::DeclContext * - GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset); + bool + HasForwardDeclForClangType (const lldb_private::CompilerType &compiler_type); - const DWARFDebugInfoEntry * - GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die); + lldb_private::CompileUnit* + GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, + uint32_t cu_idx = UINT32_MAX); - void - SearchDeclContext (const clang::DeclContext *decl_context, - const char *name, - llvm::SmallVectorImpl <clang::NamedDecl *> *results); - - lldb_private::Flags& - GetFlags () + lldb::user_id_t + MakeUserID (dw_offset_t die_offset) const { - return m_flags; + return GetID() | die_offset; } - const lldb_private::Flags& - GetFlags () const - { - return m_flags; - } + size_t + GetObjCMethodDIEOffsets (lldb_private::ConstString class_name, + DIEArray &method_die_offsets); bool - HasForwardDeclForClangType (const lldb_private::ClangASTType &clang_type); + Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); + + lldb_private::DebugMacrosSP + ParseDebugMacros(lldb::offset_t *offset); + + static DWARFDIE + GetParentSymbolContextDIE(const DWARFDIE &die); + + virtual lldb::CompUnitSP + ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx); + + virtual lldb_private::DWARFExpression::LocationListFormat + GetLocationListFormat() const; + + lldb::ModuleSP + GetDWOModule (lldb_private::ConstString name); protected: + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType; + typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE; - enum + struct DWARFDataSegment { - flagsGotDebugAbbrevData = (1 << 0), - flagsGotDebugArangesData = (1 << 1), - flagsGotDebugFrameData = (1 << 2), - flagsGotDebugInfoData = (1 << 3), - flagsGotDebugLineData = (1 << 4), - flagsGotDebugLocData = (1 << 5), - flagsGotDebugMacInfoData = (1 << 6), - flagsGotDebugPubNamesData = (1 << 7), - flagsGotDebugPubTypesData = (1 << 8), - flagsGotDebugRangesData = (1 << 9), - flagsGotDebugStrData = (1 << 10), - flagsGotAppleNamesData = (1 << 11), - flagsGotAppleTypesData = (1 << 12), - flagsGotAppleNamespacesData = (1 << 13), - flagsGotAppleObjCData = (1 << 14) + std::once_flag m_flag; + lldb_private::DWARFDataExtractor m_data; }; - - bool NamespaceDeclMatchesThisSymbolFile (const lldb_private::ClangNamespaceDecl *namespace_decl); - - bool DIEIsInNamespace (const lldb_private::ClangNamespaceDecl *namespace_decl, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry* die); DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF); - lldb::CompUnitSP ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx); - DWARFCompileUnit* GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); - DWARFCompileUnit* GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu); - lldb_private::CompileUnit* GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX); - bool GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc); - lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die); - size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc, - lldb_private::Block *parent_block, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - lldb::addr_t subprogram_low_pc, - uint32_t depth); - size_t ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children); - lldb::TypeSP ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new); - lldb_private::Type* ResolveTypeUID (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed); - - lldb::VariableSP ParseVariableDIE( - const lldb_private::SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - const lldb::addr_t func_low_pc); - - size_t ParseVariables( - const lldb_private::SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const lldb::addr_t func_low_pc, - const DWARFDebugInfoEntry *die, - bool parse_siblings, - bool parse_children, - lldb_private::VariableList* cc_variable_list = NULL); - - class DelayedAddObjCClassProperty; - typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList; - - bool ClassOrStructIsVirtual ( - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die); - - size_t ParseChildMembers( - const lldb_private::SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - lldb_private::ClangASTType &class_clang_type, - const lldb::LanguageType class_language, - std::vector<clang::CXXBaseSpecifier *>& base_classes, - std::vector<int>& member_accessibilities, - DWARFDIECollection& member_function_dies, - DelayedPropertyList& delayed_properties, - lldb::AccessType &default_accessibility, - bool &is_a_class, - LayoutInfo &layout_info); - - size_t ParseChildParameters( - const lldb_private::SymbolContext& sc, - clang::DeclContext *containing_decl_ctx, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - bool skip_artificial, - bool &is_static, - bool &is_variadic, - std::vector<lldb_private::ClangASTType>& function_args, - std::vector<clang::ParmVarDecl*>& function_param_decls, - unsigned &type_quals); - // lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); // not currently needed - - - size_t ParseChildEnumerators( - const lldb_private::SymbolContext& sc, - lldb_private::ClangASTType &clang_type, - bool is_signed, - uint32_t enumerator_byte_size, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *enum_die); - - void ParseChildArrayInfo( - const lldb_private::SymbolContext& sc, - DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - int64_t& first_index, - std::vector<uint64_t>& element_orders, - uint32_t& byte_stride, - uint32_t& bit_stride); - - // Given a die_offset, figure out the symbol context representing that die. - bool ResolveFunction (dw_offset_t offset, - DWARFCompileUnit *&dwarf_cu, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - - bool ResolveFunction (DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - - bool FunctionDieMatchesPartialName ( - const DWARFDebugInfoEntry* die, - const DWARFCompileUnit *dwarf_cu, - uint32_t name_type_mask, - const char *partial_name, - const char *base_name_start, - const char *base_name_end); - - void FindFunctions( - const lldb_private::ConstString &name, - const NameToDIE &name_to_die, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - - void FindFunctions ( - const lldb_private::RegularExpression ®ex, - const NameToDIE &name_to_die, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - - void FindFunctions ( - const lldb_private::RegularExpression ®ex, - const DWARFMappedHash::MemoryTable &memory_table, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - - lldb::TypeSP FindDefinitionTypeForDWARFDeclContext ( - const DWARFDeclContext &die_decl_ctx); - - lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE ( - const DWARFDebugInfoEntry *die, - const lldb_private::ConstString &type_name, - bool must_be_implementation); - - bool Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); - - lldb::TypeSP FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name, - bool header_definition_ok); - - lldb_private::Symbol * GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name); - - void ParseFunctions (const DIEArray &die_offsets, - bool include_inlines, - lldb_private::SymbolContextList& sc_list); - lldb::TypeSP GetTypeForDIE (DWARFCompileUnit *cu, - const DWARFDebugInfoEntry* die); - - uint32_t FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, lldb_private::TypeList& types); - - void Index(); - - void DumpIndexes(); - void SetDebugMapModule (const lldb::ModuleSP &module_sp) - { - m_debug_map_module_wp = module_sp; - } + const lldb_private::DWARFDataExtractor& + GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment); + + virtual void + LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data); + + bool + DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx); + + bool + DIEInDeclContext (const lldb_private::CompilerDeclContext *parent_decl_ctx, + const DWARFDIE &die); + + virtual DWARFCompileUnit* + GetDWARFCompileUnit (lldb_private::CompileUnit *comp_unit); + + DWARFCompileUnit* + GetNextUnparsedDWARFCompileUnit (DWARFCompileUnit* prev_cu); + + bool + GetFunction (const DWARFDIE &die, + lldb_private::SymbolContext& sc); + + lldb_private::Function * + ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, + const DWARFDIE &die); + + size_t + ParseFunctionBlocks (const lldb_private::SymbolContext& sc, + lldb_private::Block *parent_block, + const DWARFDIE &die, + lldb::addr_t subprogram_low_pc, + uint32_t depth); + + size_t + ParseTypes (const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + bool parse_siblings, + bool parse_children); + + lldb::TypeSP + ParseType (const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + bool *type_is_new); + + lldb_private::Type * + ResolveTypeUID (const DWARFDIE &die, + bool assert_not_being_parsed); + + lldb::VariableSP + ParseVariableDIE(const lldb_private::SymbolContext& sc, + const DWARFDIE &die, + const lldb::addr_t func_low_pc); + + size_t + ParseVariables (const lldb_private::SymbolContext& sc, + const DWARFDIE &orig_die, + const lldb::addr_t func_low_pc, + bool parse_siblings, + bool parse_children, + lldb_private::VariableList* cc_variable_list = NULL); + + bool + ClassOrStructIsVirtual (const DWARFDIE &die); + + // Given a die_offset, figure out the symbol context representing that die. + bool + ResolveFunction (const DIERef& die_ref, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + bool + ResolveFunction (const DWARFDIE &die, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + void + FindFunctions(const lldb_private::ConstString &name, + const NameToDIE &name_to_die, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + void + FindFunctions (const lldb_private::RegularExpression ®ex, + const NameToDIE &name_to_die, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + void + FindFunctions (const lldb_private::RegularExpression ®ex, + const DWARFMappedHash::MemoryTable &memory_table, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + virtual lldb::TypeSP + FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx); + + lldb::TypeSP + FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, + const lldb_private::ConstString &type_name, + bool must_be_implementation); + + lldb::TypeSP + FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name, + bool header_definition_ok); + + lldb_private::Symbol * + GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name); + + void + ParseFunctions (const DIEArray &die_offsets, + bool include_inlines, + lldb_private::SymbolContextList& sc_list); + + lldb::TypeSP + GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context = false); + + void + Index(); - SymbolFileDWARFDebugMap * - GetDebugMapSymfile (); + void + DumpIndexes(); - const DWARFDebugInfoEntry * - FindBlockContainingSpecification (dw_offset_t func_die_offset, - dw_offset_t spec_block_die_offset, - DWARFCompileUnit **dwarf_cu_handle); + void + SetDebugMapModule (const lldb::ModuleSP &module_sp) + { + m_debug_map_module_wp = module_sp; + } + + SymbolFileDWARFDebugMap * + GetDebugMapSymfile (); - const DWARFDebugInfoEntry * - FindBlockContainingSpecification (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - dw_offset_t spec_block_die_offset, - DWARFCompileUnit **dwarf_cu_handle); + DWARFDIE + FindBlockContainingSpecification (const DIERef& func_die_ref, dw_offset_t spec_block_die_offset); - clang::NamespaceDecl * - ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die); + DWARFDIE + FindBlockContainingSpecification (const DWARFDIE &die, dw_offset_t spec_block_die_offset); - UniqueDWARFASTTypeMap & + virtual UniqueDWARFASTTypeMap & GetUniqueDWARFASTTypeMap (); - - void LinkDeclContextToDIE (clang::DeclContext *decl_ctx, - const DWARFDebugInfoEntry *die) - { - m_die_to_decl_ctx[die] = decl_ctx; - // There can be many DIEs for a single decl context - m_decl_ctx_to_die[decl_ctx].insert(die); - } bool UserIDMatches (lldb::user_id_t uid) const { const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull; - if (high_uid) + if (high_uid != 0 && GetID() != 0) return high_uid == GetID(); return true; } - lldb::user_id_t - MakeUserID (dw_offset_t die_offset) const - { - return GetID() | die_offset; - } - - static bool - DeclKindIsCXXClass (clang::Decl::Kind decl_kind) - { - switch (decl_kind) - { - case clang::Decl::CXXRecord: - case clang::Decl::ClassTemplateSpecialization: - return true; - default: - break; - } - return false; - } - - bool - ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *parent_die, - lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - bool - ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, - lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - - clang::ClassTemplateDecl * - ParseClassTemplateDecl (clang::DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *parent_name, - int tag_decl_kind, - const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - - bool - DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1, - DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2); + DIEDeclContextsMatch (const DWARFDIE &die1, + const DWARFDIE &die2); bool - ClassContainsSelector (DWARFCompileUnit *dwarf_cu, - const DWARFDebugInfoEntry *class_die, + ClassContainsSelector (const DWARFDIE &class_die, const lldb_private::ConstString &selector); bool - CopyUniqueClassMethodTypes (SymbolFileDWARF *class_symfile, - lldb_private::Type *class_type, - DWARFCompileUnit* src_cu, - const DWARFDebugInfoEntry *src_class_die, - DWARFCompileUnit* dst_cu, - const DWARFDebugInfoEntry *dst_class_die, - DWARFDIECollection &failures); - - bool FixupAddress (lldb_private::Address &addr); typedef std::set<lldb_private::Type *> TypeSet; - typedef struct { - lldb_private::ConstString m_name; - lldb::ModuleSP m_module_sp; - } ClangModuleInfo; - - typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap; + typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap; void - GetTypes (DWARFCompileUnit* dwarf_cu, - const DWARFDebugInfoEntry *die, + GetTypes (const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, @@ -572,23 +517,37 @@ protected: void UpdateExternalModuleListIfNeeded(); + virtual DIEToTypePtr& + GetDIEToType() { return m_die_to_type; } + + virtual DIEToVariableSP& + GetDIEToVariable() { return m_die_to_variable_sp; } + + virtual DIEToClangType& + GetForwardDeclDieToClangType() { return m_forward_decl_die_to_clang_type; } + + virtual ClangTypeToDIE& + GetForwardDeclClangTypeToDie() { return m_forward_decl_clang_type_to_die; } + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap * m_debug_map_symfile; - clang::TranslationUnitDecl * m_clang_tu_decl; - lldb_private::Flags m_flags; - lldb_private::DWARFDataExtractor m_dwarf_data; - lldb_private::DWARFDataExtractor m_data_debug_abbrev; - lldb_private::DWARFDataExtractor m_data_debug_aranges; - lldb_private::DWARFDataExtractor m_data_debug_frame; - lldb_private::DWARFDataExtractor m_data_debug_info; - lldb_private::DWARFDataExtractor m_data_debug_line; - lldb_private::DWARFDataExtractor m_data_debug_loc; - lldb_private::DWARFDataExtractor m_data_debug_ranges; - lldb_private::DWARFDataExtractor m_data_debug_str; - lldb_private::DWARFDataExtractor m_data_apple_names; - lldb_private::DWARFDataExtractor m_data_apple_types; - lldb_private::DWARFDataExtractor m_data_apple_namespaces; - lldb_private::DWARFDataExtractor m_data_apple_objc; + lldb_private::DWARFDataExtractor m_dwarf_data; + + DWARFDataSegment m_data_debug_abbrev; + DWARFDataSegment m_data_debug_addr; + DWARFDataSegment m_data_debug_aranges; + DWARFDataSegment m_data_debug_frame; + DWARFDataSegment m_data_debug_info; + DWARFDataSegment m_data_debug_line; + DWARFDataSegment m_data_debug_macro; + DWARFDataSegment m_data_debug_loc; + DWARFDataSegment m_data_debug_ranges; + DWARFDataSegment m_data_debug_str; + DWARFDataSegment m_data_debug_str_offsets; + DWARFDataSegment m_data_apple_names; + DWARFDataSegment m_data_apple_types; + DWARFDataSegment m_data_apple_namespaces; + DWARFDataSegment m_data_apple_objc; // The unique pointer items below are generated on demand if and when someone accesses // them through a non const version of this class. @@ -600,6 +559,10 @@ protected: std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap; std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap; std::unique_ptr<GlobalVariableMap> m_global_aranges_ap; + + typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> DebugMacrosMap; + DebugMacrosMap m_debug_macros_map; + ExternalTypeModuleMap m_external_type_modules; NameToDIE m_function_basename_index; // All concrete functions NameToDIE m_function_fullname_index; // All concrete functions @@ -610,28 +573,16 @@ protected: NameToDIE m_type_index; // All type DIE offsets NameToDIE m_namespace_index; // All type DIE offsets bool m_indexed:1, - m_is_external_ast_source:1, m_using_apple_tables:1, m_fetched_external_modules:1; lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; std::unique_ptr<DWARFDebugRanges> m_ranges; UniqueDWARFASTTypeMap m_unique_ast_type_map; - typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; - typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType; - typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE; - typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap; - DIEToDeclContextMap m_die_to_decl_ctx; - DeclContextToDIEMap m_decl_ctx_to_die; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; DIEToClangType m_forward_decl_die_to_clang_type; ClangTypeToDIE m_forward_decl_clang_type_to_die; - RecordDeclToLayoutMap m_record_decl_to_layout_map; }; #endif // SymbolFileDWARF_SymbolFileDWARF_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index de972acd7ed7..be25dfc99dee 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1,4 +1,4 @@ -//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===// +//===-- SymbolFileDWARFDebugMap.cpp -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "SymbolFileDWARFDebugMap.h" #include "DWARFDebugAranges.h" @@ -24,11 +28,11 @@ #endif #include "lldb/Core/Timer.h" -#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/VariableList.h" #include "LogChannelDWARF.h" @@ -41,9 +45,6 @@ using namespace lldb_private; // (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()" // (so we can fixup the symbol file id. - - - const SymbolFileDWARFDebugMap::FileRangeMap & SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile) { @@ -173,7 +174,6 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa return file_range_map; } - class DebugMapModule : public Module { public: @@ -190,14 +190,10 @@ public: { } - virtual - ~DebugMapModule () - { - } + ~DebugMapModule() override = default; - - virtual SymbolVendor* - GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) + SymbolVendor* + GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) override { // Scope for locker if (m_symfile_ap.get() || can_create == false) @@ -259,7 +255,6 @@ SymbolFileDWARFDebugMap::Terminate() PluginManager::UnregisterPlugin (CreateInstance); } - lldb_private::ConstString SymbolFileDWARFDebugMap::GetPluginNameStatic() { @@ -279,7 +274,6 @@ SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file) return new SymbolFileDWARFDebugMap (obj_file); } - SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) : SymbolFile(ofile), m_flags(), @@ -290,7 +284,6 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) : { } - SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() { } @@ -298,15 +291,6 @@ SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() void SymbolFileDWARFDebugMap::InitializeObject() { - // Install our external AST source callbacks so we can complete Clang types. - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap ( - new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl, - SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl, - NULL, - SymbolFileDWARFDebugMap::LayoutRecordType, - this)); - - GetClangASTContext().SetExternalSource (ast_source_ap); } void @@ -517,7 +501,6 @@ SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_inf return NULL; } - bool SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec) { @@ -532,8 +515,6 @@ SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec return false; } - - ObjectFile * SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx) { @@ -561,7 +542,6 @@ SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit return NULL; } - uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info) { @@ -637,7 +617,6 @@ SymbolFileDWARFDebugMap::GetNumCompileUnits() return m_compile_unit_infos.size(); } - CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { @@ -660,7 +639,8 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) NULL, so_file_spec, cu_id, - eLanguageTypeUnknown)); + eLanguageTypeUnknown, + false)); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { @@ -687,7 +667,6 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc) return NULL; } - size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule (const lldb_private::Module *module, std::vector<CompileUnitInfo *>& cu_infos) { @@ -728,6 +707,15 @@ SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc) } bool +SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros (const SymbolContext& sc) +{ + SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); + if (oso_dwarf) + return oso_dwarf->ParseCompileUnitDebugMacros (sc); + return false; +} + +bool SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) { SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); @@ -754,7 +742,6 @@ SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc) return 0; } - size_t SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc) { @@ -764,7 +751,6 @@ SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc) return 0; } - size_t SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc) { @@ -774,8 +760,6 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc) return 0; } - - Type* SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { @@ -787,10 +771,22 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) } bool -SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type) +SymbolFileDWARFDebugMap::CompleteType (CompilerType& compiler_type) { - // We have a struct/union/class/enum that needs to be fully resolved. - return false; + bool success = false; + if (compiler_type) + { + ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { + if (oso_dwarf->HasForwardDeclForClangType (compiler_type)) + { + oso_dwarf->CompleteType (compiler_type); + success = true; + return true; + } + return false; + }); + } + return success; } uint32_t @@ -834,7 +830,6 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3 return resolved_flags; } - uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) { @@ -871,7 +866,7 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables ( const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name" uint32_t max_matches, VariableList& variables @@ -888,7 +883,7 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx); if (oso_dwarf) { - if (oso_dwarf->FindGlobalVariables(name, namespace_decl, true, max_matches, variables)) + if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true, max_matches, variables)) if (variables.GetSize() > max_matches) break; } @@ -898,7 +893,11 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables } uint32_t -SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) +SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + bool append, + uint32_t max_matches, + VariableList& variables) { // If we aren't appending the results to this list, then clear the list @@ -913,7 +912,7 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (name, - namespace_decl, + parent_decl_ctx, true, max_matches, variables); @@ -941,7 +940,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla return variables.GetSize() - original_size; } - uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) { @@ -983,7 +981,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bo return variables.GetSize() - original_size; } - int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) { @@ -998,7 +995,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr return 1; } - int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) { @@ -1013,7 +1009,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, return 1; } - SymbolFileDWARFDebugMap::CompileUnitInfo* SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr) { @@ -1062,7 +1057,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID (user_id_t symbol_id, return comp_unit_info; } - static void RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextList &sc_list, uint32_t start_idx) { @@ -1091,7 +1085,12 @@ RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextLis } uint32_t -SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) +SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, + bool include_inlines, + bool append, + SymbolContextList& sc_list) { Timer scoped_timer (__PRETTY_FUNCTION__, "SymbolFileDWARFDebugMap::FindFunctions (name = %s)", @@ -1105,7 +1104,7 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, true, sc_list)) + if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, true, sc_list)) { RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx); } @@ -1115,7 +1114,6 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames return sc_list.GetSize() - initial_size; } - uint32_t SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) { @@ -1150,8 +1148,7 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope, Timer scoped_timer (__PRETTY_FUNCTION__, "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)", type_mask); - - + uint32_t initial_size = type_list.GetSize(); SymbolFileDWARF *oso_dwarf = NULL; if (sc_scope) @@ -1177,7 +1174,6 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope, return type_list.GetSize() - initial_size; } - TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) { @@ -1189,8 +1185,6 @@ SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclC return type_sp; } - - bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso) { @@ -1210,7 +1204,7 @@ SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWAR } TypeSP -SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, +SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, const ConstString &type_name, bool must_be_implementation) { @@ -1280,10 +1274,10 @@ SymbolFileDWARFDebugMap::FindTypes ( const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *namespace_decl, - bool append, + const CompilerDeclContext *parent_decl_ctx, + bool append, uint32_t max_matches, - TypeList& types + TypeMap& types ) { if (!append) @@ -1296,12 +1290,12 @@ SymbolFileDWARFDebugMap::FindTypes { oso_dwarf = GetSymbolFile (sc); if (oso_dwarf) - return oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types); + return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types); } else { ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types); + oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types); return false; }); } @@ -1320,24 +1314,24 @@ SymbolFileDWARFDebugMap::FindTypes //} -ClangNamespaceDecl +CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, - const ClangNamespaceDecl *parent_namespace_decl) + const CompilerDeclContext *parent_decl_ctx) { - ClangNamespaceDecl matching_namespace; + CompilerDeclContext matching_namespace; SymbolFileDWARF *oso_dwarf; if (sc.comp_unit) { oso_dwarf = GetSymbolFile (sc); if (oso_dwarf) - matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl); + matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx); } else { ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl); + matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx); return (bool)matching_namespace; }); @@ -1401,7 +1395,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf) return NULL; } - void SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp) { @@ -1427,78 +1420,33 @@ SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompU } } - -void -SymbolFileDWARFDebugMap::CompleteTagDecl (void *baton, clang::TagDecl *decl) -{ - SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; - ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); - if (clang_type) - { - symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - if (oso_dwarf->HasForwardDeclForClangType (clang_type)) - { - oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); - return true; - } - return false; - }); - } -} - -void -SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl) -{ - SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; - ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); - if (clang_type) - { - symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - if (oso_dwarf->HasForwardDeclForClangType (clang_type)) - { - oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); - return true; - } - return false; - }); - } -} - -bool -SymbolFileDWARFDebugMap::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, - uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ - SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; - bool laid_out = false; - symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - return (laid_out = oso_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets)); - }); - return laid_out; -} - - - -clang::DeclContext* -SymbolFileDWARFDebugMap::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARFDebugMap::GetDeclContextForUID (lldb::user_id_t type_uid) { const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx); if (oso_dwarf) - return oso_dwarf->GetClangDeclContextContainingTypeUID (type_uid); - return NULL; + return oso_dwarf->GetDeclContextForUID (type_uid); + return CompilerDeclContext(); } -clang::DeclContext* -SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARFDebugMap::GetDeclContextContainingUID (lldb::user_id_t type_uid) { const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx); if (oso_dwarf) - return oso_dwarf->GetClangDeclContextForTypeUID (sc, type_uid); - return NULL; + return oso_dwarf->GetDeclContextContainingUID (type_uid); + return CompilerDeclContext(); +} + +void +SymbolFileDWARFDebugMap::ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) +{ + ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { + oso_dwarf->ParseDeclsForContext (decl_ctx); + return true; // Keep iterating + }); } bool @@ -1613,7 +1561,6 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA const FileRangeMap::Entry* entry = file_range_map.GetEntryAtIndex(idx); if (entry) { - printf ("[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", entry->GetRangeBase(), entry->GetRangeEnd()); debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(), entry->GetRangeEnd()); num_line_entries_added++; } @@ -1622,4 +1569,3 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA } return num_line_entries_added; } - diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index ce0cfd744f0b..1eb33c927bdf 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -14,19 +14,14 @@ #include <vector> #include <bitset> -#include "clang/AST/CharUnits.h" - #include "lldb/Core/RangeMap.h" #include "lldb/Symbol/SymbolFile.h" #include "UniqueDWARFASTType.h" class SymbolFileDWARF; -class DWARFCompileUnit; class DWARFDebugAranges; -class DWARFDebugInfoEntry; class DWARFDeclContext; -class DebugMapModule; class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { @@ -57,7 +52,6 @@ public: ~SymbolFileDWARFDebugMap () override; uint32_t CalculateAbilities () override; - void InitializeObject() override; //------------------------------------------------------------------ @@ -69,6 +63,7 @@ public: lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override; size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override; bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; + bool ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override; bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override; bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override; size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; @@ -76,39 +71,26 @@ public: size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc) override; lldb_private::Type* ResolveTypeUID (lldb::user_id_t type_uid) override; - clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) override; - clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) override; - bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type) override; + lldb_private::CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) override; + lldb_private::CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) override; + void ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override; + + bool CompleteType (lldb_private::CompilerType& compiler_type) override; uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc) override; uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list) override; - uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override; + uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override; uint32_t FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override; - uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override; + uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override; uint32_t FindFunctions (const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override; - uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types) override; - lldb_private::ClangNamespaceDecl + uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::TypeMap& types) override; + lldb_private::CompilerDeclContext FindNamespace (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, - const lldb_private::ClangNamespaceDecl *parent_namespace_decl) override; + const lldb_private::CompilerDeclContext *parent_decl_ctx) override; size_t GetTypes (lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list) override; - - //------------------------------------------------------------------ - // ClangASTContext callbacks for external source lookups. - //------------------------------------------------------------------ - static void - CompleteTagDecl (void *baton, clang::TagDecl *); - - static void - CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); - - static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); - //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -128,6 +110,7 @@ protected: friend class DWARFCompileUnit; friend class SymbolFileDWARF; friend class DebugMapModule; + friend class DWARFASTParserClang; struct OSOInfo { lldb::ModuleSP module_sp; @@ -259,7 +242,7 @@ protected: uint32_t PrivateFindGlobalVariables (const lldb_private::ConstString &name, - const lldb_private::ClangNamespaceDecl *namespace_decl, + const lldb_private::CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, lldb_private::VariableList& variables); @@ -281,7 +264,7 @@ protected: Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso); lldb::TypeSP - FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, + FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, const lldb_private::ConstString &type_name, bool must_be_implementation); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp new file mode 100644 index 000000000000..326c397c83d5 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -0,0 +1,131 @@ +//===-- SymbolFileDWARFDwo.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwo.h" + +#include "lldb/Core/Section.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu) : + SymbolFileDWARF(objfile.get()), + m_obj_file_sp(objfile), + m_base_dwarf_cu(dwarf_cu) +{ + SetID(((lldb::user_id_t)dwarf_cu->GetOffset())<<32); +} + +void +SymbolFileDWARFDwo::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data) +{ + const SectionList* section_list = m_obj_file->GetSectionList(false /* update_module_section_list */); + if (section_list) + { + SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); + if (section_sp) + { + // See if we memory mapped the DWARF segment? + if (m_dwarf_data.GetByteSize()) + { + data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize()); + return; + } + + if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) + return; + + data.Clear(); + } + } + + SymbolFileDWARF::LoadSectionData(sect_type, data); +} + +lldb::CompUnitSP +SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) +{ + assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible compile unit"); + return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX); +} + +DWARFCompileUnit* +SymbolFileDWARFDwo::GetCompileUnit() +{ + // Only dwo files with 1 compile unit is supported + if (GetNumCompileUnits() == 1) + return DebugInfo()->GetCompileUnitAtIndex(0); + else + return nullptr; +} + +DWARFCompileUnit* +SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) +{ + return GetCompileUnit(); +} + +SymbolFileDWARF::DIEToTypePtr& +SymbolFileDWARFDwo::GetDIEToType() +{ + return GetBaseSymbolFile()->GetDIEToType(); +} + +SymbolFileDWARF::DIEToVariableSP& +SymbolFileDWARFDwo::GetDIEToVariable() +{ + return GetBaseSymbolFile()->GetDIEToVariable(); +} + +SymbolFileDWARF::DIEToClangType& +SymbolFileDWARFDwo::GetForwardDeclDieToClangType() +{ + return GetBaseSymbolFile()->GetForwardDeclDieToClangType(); +} + +SymbolFileDWARF::ClangTypeToDIE& +SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() +{ + return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie(); +} + +UniqueDWARFASTTypeMap& +SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() +{ + return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap(); +} + +lldb::TypeSP +SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) +{ + return GetBaseSymbolFile()->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); +} + +SymbolFileDWARF* +SymbolFileDWARFDwo::GetBaseSymbolFile() +{ + return m_base_dwarf_cu->GetSymbolFileDWARF(); +} + +DWARFExpression::LocationListFormat +SymbolFileDWARFDwo::GetLocationListFormat() const +{ + return DWARFExpression::SplitDwarfLocationList; +} + +TypeSystem* +SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) +{ + return GetBaseSymbolFile()->GetTypeSystemForLanguage(language); +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h new file mode 100644 index 000000000000..39ed6502229b --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -0,0 +1,70 @@ +//===-- SymbolFileDWARFDwo.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ +#define SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "SymbolFileDWARF.h" + +class SymbolFileDWARFDwo : public SymbolFileDWARF +{ +public: + SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu); + + ~SymbolFileDWARFDwo() override = default; + + lldb::CompUnitSP + ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) override; + + DWARFCompileUnit* + GetCompileUnit(); + + DWARFCompileUnit* + GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override; + + lldb_private::DWARFExpression::LocationListFormat + GetLocationListFormat() const override; + + lldb_private::TypeSystem* + GetTypeSystemForLanguage(lldb::LanguageType language) override; + +protected: + void + LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data) override; + + DIEToTypePtr& + GetDIEToType() override; + + DIEToVariableSP& + GetDIEToVariable() override; + + DIEToClangType& + GetForwardDeclDieToClangType() override; + + ClangTypeToDIE& + GetForwardDeclClangTypeToDie() override; + + UniqueDWARFASTTypeMap& + GetUniqueDWARFASTTypeMap() override; + + lldb::TypeSP + FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) override; + + SymbolFileDWARF* + GetBaseSymbolFile(); + + lldb::ObjectFileSP m_obj_file_sp; + DWARFCompileUnit* m_base_dwarf_cu; +}; + +#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 94044c0feb30..2ca407b9e48a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -15,58 +15,51 @@ // Project includes #include "lldb/Symbol/Declaration.h" -#include "DWARFDebugInfoEntry.h" - bool -UniqueDWARFASTTypeList::Find -( - SymbolFileDWARF *symfile, - const DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, - const lldb_private::Declaration &decl, - const int32_t byte_size, - UniqueDWARFASTType &entry -) const +UniqueDWARFASTTypeList::Find (const DWARFDIE &die, + const lldb_private::Declaration &decl, + const int32_t byte_size, + UniqueDWARFASTType &entry) const { - collection::const_iterator pos, end = m_collection.end(); - for (pos = m_collection.begin(); pos != end; ++pos) + for (const UniqueDWARFASTType &udt : m_collection) { // Make sure the tags match - if (pos->m_die->Tag() == die->Tag()) + if (udt.m_die.Tag() == die.Tag()) { // Validate byte sizes of both types only if both are valid. - if (pos->m_byte_size < 0 || byte_size < 0 || pos->m_byte_size == byte_size) + if (udt.m_byte_size < 0 || byte_size < 0 || udt.m_byte_size == byte_size) { // Make sure the file and line match - if (pos->m_declaration == decl) + if (udt.m_declaration == decl) { // The type has the same name, and was defined on the same // file and line. Now verify all of the parent DIEs match. - const DWARFDebugInfoEntry *parent_arg_die = die->GetParent(); - const DWARFDebugInfoEntry *parend_pos_die = pos->m_die->GetParent(); + DWARFDIE parent_arg_die = die.GetParent(); + DWARFDIE parent_pos_die = udt.m_die.GetParent(); bool match = true; bool done = false; - while (!done && match && parent_arg_die && parend_pos_die) + while (!done && match && parent_arg_die && parent_pos_die) { - if (parent_arg_die->Tag() == parend_pos_die->Tag()) + const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); + const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); + if (parent_arg_tag == parent_pos_tag) { - const dw_tag_t tag = parent_arg_die->Tag(); - switch (tag) + switch (parent_arg_tag) { case DW_TAG_class_type: case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_namespace: { - const char *parent_arg_die_name = parent_arg_die->GetName(symfile, cu); + const char *parent_arg_die_name = parent_arg_die.GetName(); if (parent_arg_die_name == NULL) // Anonymous (i.e. no-name) struct { match = false; } else { - const char *parent_pos_die_name = parend_pos_die->GetName(pos->m_symfile, pos->m_cu); - if (parent_pos_die_name == NULL || strcmp (parent_arg_die_name, parent_pos_die_name)) + const char *parent_pos_die_name = parent_pos_die.GetName(); + if (parent_pos_die_name == NULL || ((parent_arg_die_name != parent_pos_die_name) && strcmp (parent_arg_die_name, parent_pos_die_name))) match = false; } } @@ -77,13 +70,13 @@ UniqueDWARFASTTypeList::Find break; } } - parent_arg_die = parent_arg_die->GetParent(); - parend_pos_die = parend_pos_die->GetParent(); + parent_arg_die = parent_arg_die.GetParent(); + parent_pos_die = parent_pos_die.GetParent(); } if (match) { - entry = *pos; + entry = udt; return true; } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index c85e175235ca..b7b18efd8769 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -19,10 +19,7 @@ // Project includes #include "lldb/Symbol/Declaration.h" - -class DWARFCompileUnit; -class DWARFDebugInfoEntry; -class SymbolFileDWARF; +#include "DWARFDIE.h" class UniqueDWARFASTType { @@ -32,23 +29,17 @@ public: //------------------------------------------------------------------ UniqueDWARFASTType () : m_type_sp (), - m_symfile (NULL), - m_cu (NULL), - m_die (NULL), + m_die (), m_declaration (), m_byte_size (-1) // Set to negative value to make sure we have a valid value { } UniqueDWARFASTType (lldb::TypeSP &type_sp, - SymbolFileDWARF *symfile, - DWARFCompileUnit *cu, - DWARFDebugInfoEntry *die, + const DWARFDIE &die, const lldb_private::Declaration &decl, int32_t byte_size) : m_type_sp (type_sp), - m_symfile (symfile), - m_cu (cu), m_die (die), m_declaration (decl), m_byte_size (byte_size) @@ -57,8 +48,6 @@ public: UniqueDWARFASTType (const UniqueDWARFASTType &rhs) : m_type_sp (rhs.m_type_sp), - m_symfile (rhs.m_symfile), - m_cu (rhs.m_cu), m_die (rhs.m_die), m_declaration (rhs.m_declaration), m_byte_size (rhs.m_byte_size) @@ -75,8 +64,6 @@ public: if (this != &rhs) { m_type_sp = rhs.m_type_sp; - m_symfile = rhs.m_symfile; - m_cu = rhs.m_cu; m_die = rhs.m_die; m_declaration = rhs.m_declaration; m_byte_size = rhs.m_byte_size; @@ -85,9 +72,7 @@ public: } lldb::TypeSP m_type_sp; - SymbolFileDWARF *m_symfile; - const DWARFCompileUnit *m_cu; - const DWARFDebugInfoEntry *m_die; + DWARFDIE m_die; lldb_private::Declaration m_declaration; int32_t m_byte_size; }; @@ -117,9 +102,7 @@ public: } bool - Find (SymbolFileDWARF *symfile, - const DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, + Find (const DWARFDIE &die, const lldb_private::Declaration &decl, const int32_t byte_size, UniqueDWARFASTType &entry) const; @@ -149,10 +132,8 @@ public: } bool - Find (const lldb_private::ConstString &name, - SymbolFileDWARF *symfile, - const DWARFCompileUnit *cu, - const DWARFDebugInfoEntry *die, + Find (const lldb_private::ConstString &name, + const DWARFDIE &die, const lldb_private::Declaration &decl, const int32_t byte_size, UniqueDWARFASTType &entry) const @@ -161,7 +142,7 @@ public: collection::const_iterator pos = m_collection.find (unique_name_cstr); if (pos != m_collection.end()) { - return pos->second.Find (symfile, cu, die, decl, byte_size, entry); + return pos->second.Find (die, decl, byte_size, entry); } return false; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 09b919782608..d3dd1ae923e0 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -12,7 +12,6 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Timer.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -79,14 +78,6 @@ SymbolFileSymtab::~SymbolFileSymtab() { } -ClangASTContext & -SymbolFileSymtab::GetClangASTContext () -{ - ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); - - return ast; -} - uint32_t SymbolFileSymtab::CalculateAbilities () { @@ -115,6 +106,7 @@ SymbolFileSymtab::CalculateAbilities () if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes)) { symtab->SortSymbolIndexesByValue(m_code_indexes, true); + abilities |= Functions; } if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes)) @@ -161,7 +153,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown)); + cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false)); } return cu_sp; } @@ -261,6 +253,12 @@ SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc) } bool +SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc) +{ + return false; +} + +bool SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) { return false; @@ -299,17 +297,11 @@ SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) } bool -SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type) +SymbolFileSymtab::CompleteType (lldb_private::CompilerType& compiler_type) { return false; } -ClangNamespaceDecl -SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl) -{ - return ClangNamespaceDecl(); -} - uint32_t SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) { @@ -326,63 +318,6 @@ SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve return resolved_flags; } -uint32_t -SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) -{ - return 0; -} - -uint32_t -SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) -{ - return 0; -} - -uint32_t -SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) -{ - return 0; -} - -uint32_t -SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - Timer scoped_timer (__PRETTY_FUNCTION__, - "SymbolFileSymtab::FindFunctions (name = '%s')", - name.GetCString()); - // If we ever support finding STABS or COFF debug info symbols, - // we will need to add support here. We are not trying to find symbols - // here, just "lldb_private::Function" objects that come from complete - // debug information. Any symbol queries should go through the symbol - // table itself in the module's object file. - return 0; -} - -uint32_t -SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - Timer scoped_timer (__PRETTY_FUNCTION__, - "SymbolFileSymtab::FindFunctions (regex = '%s')", - regex.GetText()); - // If we ever support finding STABS or COFF debug info symbols, - // we will need to add support here. We are not trying to find symbols - // here, just "lldb_private::Function" objects that come from complete - // debug information. Any symbol queries should go through the symbol - // table itself in the module's object file. - return 0; -} - -uint32_t -SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc, - const lldb_private::ConstString &name, - const ClangNamespaceDecl *namespace_decl, - bool append, - uint32_t max_matches, - lldb_private::TypeList& types) -{ - return 0; -} - //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index d606419a0d94..4648da49cb9f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -10,14 +10,26 @@ #ifndef liblldb_SymbolFileSymtab_h_ #define liblldb_SymbolFileSymtab_h_ +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Symtab.h" -#include <vector> class SymbolFileSymtab : public lldb_private::SymbolFile { public: //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolFileSymtab(lldb_private::ObjectFile* obj_file); + + ~SymbolFileSymtab() override; + + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ static void @@ -35,94 +47,71 @@ public: static lldb_private::SymbolFile* CreateInstance (lldb_private::ObjectFile* obj_file); - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - SymbolFileSymtab(lldb_private::ObjectFile* obj_file); - - virtual - ~SymbolFileSymtab(); - - virtual uint32_t CalculateAbilities (); + uint32_t + CalculateAbilities() override; //------------------------------------------------------------------ // Compile Unit function calls //------------------------------------------------------------------ - virtual uint32_t - GetNumCompileUnits(); - - virtual lldb::CompUnitSP - ParseCompileUnitAtIndex(uint32_t index); - - virtual lldb::LanguageType - ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc); - - virtual size_t - ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc); - - virtual bool - ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc); + uint32_t + GetNumCompileUnits() override; - virtual bool - ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files); - - virtual bool - ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules); - - virtual size_t - ParseFunctionBlocks (const lldb_private::SymbolContext& sc); - - virtual size_t - ParseTypes (const lldb_private::SymbolContext& sc); + lldb::CompUnitSP + ParseCompileUnitAtIndex(uint32_t index) override; - virtual size_t - ParseVariablesForContext (const lldb_private::SymbolContext& sc); + lldb::LanguageType + ParseCompileUnitLanguage(const lldb_private::SymbolContext& sc) override; - virtual lldb_private::Type* - ResolveTypeUID(lldb::user_id_t type_uid); + size_t + ParseCompileUnitFunctions(const lldb_private::SymbolContext& sc) override; - virtual bool - ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type); + bool + ParseCompileUnitLineTable(const lldb_private::SymbolContext& sc) override; - virtual uint32_t - ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc); + bool + ParseCompileUnitDebugMacros(const lldb_private::SymbolContext& sc) override; - virtual uint32_t - ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list); + bool + ParseCompileUnitSupportFiles(const lldb_private::SymbolContext& sc, + lldb_private::FileSpecList &support_files) override; + + bool + ParseImportedModules(const lldb_private::SymbolContext &sc, + std::vector<lldb_private::ConstString> &imported_modules) override; - virtual uint32_t - FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables); + size_t + ParseFunctionBlocks(const lldb_private::SymbolContext& sc) override; - virtual uint32_t - FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables); + size_t + ParseTypes(const lldb_private::SymbolContext& sc) override; - virtual uint32_t - FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); + size_t + ParseVariablesForContext(const lldb_private::SymbolContext& sc) override; - virtual uint32_t - FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); + lldb_private::Type* + ResolveTypeUID(lldb::user_id_t type_uid) override; - virtual uint32_t - FindTypes (const lldb_private::SymbolContext& sc,const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types); + bool + CompleteType(lldb_private::CompilerType& compiler_type) override; - virtual size_t - GetTypes (lldb_private::SymbolContextScope *sc_scope, - uint32_t type_mask, - lldb_private::TypeList &type_list); + uint32_t + ResolveSymbolContext(const lldb_private::Address& so_addr, + uint32_t resolve_scope, + lldb_private::SymbolContext& sc) override; - virtual lldb_private::ClangNamespaceDecl - FindNamespace (const lldb_private::SymbolContext& sc, - const lldb_private::ConstString &name, - const lldb_private::ClangNamespaceDecl *parent_namespace_decl); + size_t + GetTypes(lldb_private::SymbolContextScope *sc_scope, + uint32_t type_mask, + lldb_private::TypeList &type_list) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap; @@ -133,13 +122,9 @@ protected: lldb_private::Symtab::IndexCollection m_data_indexes; lldb_private::Symtab::NameToIndexMap m_objc_class_name_to_index; TypeMap m_objc_class_types; - - lldb_private::ClangASTContext & - GetClangASTContext (); private: DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab); }; - -#endif // liblldb_SymbolFileSymtab_h_ +#endif // liblldb_SymbolFileSymtab_h_ |