From d1767f05b550dfe1a689e61574d9547284cf0de0 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Thu, 8 Dec 2011 02:13:16 +0000 Subject: [PATCH] Added a new class called lldb_private::SymbolFileType which is designed to take a SymbolFile reference and a lldb::user_id_t and be used in objects which represent things in debug symbols that have types where we don't need to know the true type yet, such as in lldb_private::Variable objects. This allows us to defer resolving the type until something is used. More specifically this allows us to get 1000 local variables from the current function, and if the user types "frame variable argc", we end up _only_ resolving the type for "argc" and not for the 999 other local variables. We can expand the use of this as needed in the future. Modified the DWARFMappedHash class to be able to read the HashData that has more than just the DIE offset. It currently will read the atoms in the header definition and read the data correctly. Currently only the DIE offset and type flags are supported. This is needed for adding type flags to the .apple_types hash accelerator tables. Fixed a assertion crash that would happen if we have a variable that had a DW_AT_const_value instead of a location where "location.LocationContains_DW_OP_addr()" would end up asserting when it tried to parse the variable location as a DWARF opcode list. Decreased the amount of memory that LLDB would use when evaluating an expression by 3x - 4x for clang. There was a place in the namespace lookup code that was parsing all namespaces with a certain name in a DWARF file instead of stopping when it found the first match. This was causing all of the compile units with a matching namespace to get parsed into memory and causing unnecessary memory bloat. Improved "Target::EvaluateExpression(...)" to not try and find a variable when the expression contains characters that would certainly cause an expression to need to be evaluated by the debugger. llvm-svn: 146130 --- lldb/include/lldb/Core/MappedHash.h | 6 + lldb/include/lldb/Symbol/Type.h | 29 ++ lldb/include/lldb/Symbol/Variable.h | 15 +- lldb/include/lldb/lldb-forward-rtti.h | 1 + lldb/include/lldb/lldb-forward.h | 1 + lldb/source/Commands/CommandObjectTarget.cpp | 60 ++-- .../SymbolFile/DWARF/DWARFFormValue.cpp | 21 ++ .../Plugins/SymbolFile/DWARF/DWARFFormValue.h | 4 +- .../SymbolFile/DWARF/HashedNameToDIE.h | 299 ++++++++++++++++-- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 165 ++++++---- lldb/source/Symbol/Type.cpp | 9 + lldb/source/Symbol/Variable.cpp | 24 +- lldb/source/Target/Target.cpp | 24 +- 13 files changed, 503 insertions(+), 155 deletions(-) diff --git a/lldb/include/lldb/Core/MappedHash.h b/lldb/include/lldb/Core/MappedHash.h index 32beb80663c5..1198a2dee039 100644 --- a/lldb/include/lldb/Core/MappedHash.h +++ b/lldb/include/lldb/Core/MappedHash.h @@ -508,6 +508,12 @@ public: uint32_t* hash_data_offset_ptr, Pair &pair) const = 0; + const HeaderType & + GetHeader() + { + return m_header; + } + protected: // Implementation agnostic information HeaderType m_header; diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 9c11ae41f2f8..6c78ffba3927 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -19,6 +19,35 @@ #include namespace lldb_private { + +class SymbolFileType : + public ReferenceCountedBaseVirtual, + public UserID + { + public: + SymbolFileType (SymbolFile &symbol_file, lldb::user_id_t uid) : + UserID (uid), + m_symbol_file (symbol_file) + { + } + + ~SymbolFileType () + { + } + + Type * + operator->() + { + return GetType (); + } + + Type * + GetType (); + + protected: + SymbolFile &m_symbol_file; + lldb::TypeSP m_type_sp; + }; class Type : public ReferenceCountedBaseVirtual, diff --git a/lldb/include/lldb/Symbol/Variable.h b/lldb/include/lldb/Symbol/Variable.h index 85412afdf6d8..3459494faecd 100644 --- a/lldb/include/lldb/Symbol/Variable.h +++ b/lldb/include/lldb/Symbol/Variable.h @@ -30,7 +30,7 @@ public: Variable (lldb::user_id_t uid, const char *name, const char *mangled, // The mangled variable name for variables in namespaces - Type *type, + const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope, SymbolContextScope *owner_scope, Declaration* decl, @@ -81,16 +81,7 @@ public: NameMatches (const RegularExpression& regex) const; Type * - GetType() - { - return m_type; - } - - const Type * - GetType() const - { - return m_type; - } + GetType(); lldb::ValueType GetScope() const @@ -169,7 +160,7 @@ public: protected: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of hte variable - Type *m_type; // The type pointer of the variable (int, struct, class, etc) + lldb::SymbolFileTypeSP m_symfile_type_sp; // The type pointer of the variable (int, struct, class, etc) lldb::ValueType m_scope; // global, parameter, local SymbolContextScope *m_owner_scope; // The symbol file scope that this variable was defined in Declaration m_declaration; // Declaration location for this item. diff --git a/lldb/include/lldb/lldb-forward-rtti.h b/lldb/include/lldb/lldb-forward-rtti.h index 63b1d6fa8dac..c9f7b539047e 100644 --- a/lldb/include/lldb/lldb-forward-rtti.h +++ b/lldb/include/lldb/lldb-forward-rtti.h @@ -70,6 +70,7 @@ namespace lldb { typedef SharedPtr::Type StringSummaryFormatSP; typedef SharedPtr::Type SummaryFormatSP; typedef SharedPtr::Type SymbolFileSP; + typedef IntrusiveSharedPtr::Type SymbolFileTypeSP; typedef SharedPtr::Type SymbolContextSpecifierSP; typedef SharedPtr::Type SyntheticChildrenSP; typedef SharedPtr::Type SyntheticChildrenFrontEndSP; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 94cd4e23cd9d..e877c6e9c43d 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -158,6 +158,7 @@ class SymbolContextList; class SymbolContextScope; class SymbolContextSpecifier; class SymbolFile; +class SymbolFileType; class SymbolVendor; class Symtab; class SyntheticChildren; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 014f980288e7..44bab7b6fdfc 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1524,47 +1524,35 @@ LookupTypeInModule (CommandInterpreter &interpreter, { if (module && name_cstr && name_cstr[0]) { - /*SymbolContextList sc_list; - - SymbolVendor *symbol_vendor = module->GetSymbolVendor(); - if (symbol_vendor) - {*/ - TypeList type_list; - uint32_t num_matches = 0; - SymbolContext sc; - // if (name_is_regex) - // { - // RegularExpression name_regex (name_cstr); - // num_matches = symbol_vendor->FindFunctions(sc, name_regex, true, UINT32_MAX, type_list); - // } - // else - // { - ConstString name(name_cstr); - num_matches = module->FindTypes(sc, name, NULL, true, UINT32_MAX, type_list); - // } + TypeList type_list; + const uint32_t max_num_matches = 1; + uint32_t num_matches = 0; + SymbolContext sc; + + ConstString name(name_cstr); + num_matches = module->FindTypes(sc, name, NULL, true, max_num_matches, type_list); - if (num_matches) + if (num_matches) + { + strm.Indent (); + strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : ""); + DumpFullpath (strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + const uint32_t num_types = type_list.GetSize(); + for (uint32_t i=0; i 1 ? "es" : ""); - DumpFullpath (strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - const uint32_t num_types = type_list.GetSize(); - for (uint32_t i=0; iGetClangFullType (); - type_sp->GetDescription (&strm, eDescriptionLevelFull, true); - } - strm.EOL(); + // Resolve the clang type so that any forward references + // to types that haven't yet been parsed will get parsed. + type_sp->GetClangFullType (); + type_sp->GetDescription (&strm, eDescriptionLevelFull, true); } + strm.EOL(); } - return num_matches; - //} + } + return num_matches; } return 0; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index ac417e5cc1e5..507dea2718dc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -472,6 +472,27 @@ DWARFFormValue::Reference(const DWARFCompileUnit* cu) const return die_offset; } +uint64_t +DWARFFormValue::Reference (dw_offset_t base_offset) const +{ + uint64_t die_offset = m_value.value.uval; + switch (m_form) + { + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + die_offset += base_offset; + break; + + default: + break; + } + + return die_offset; +} + //---------------------------------------------------------------------- // Resolve any compile unit specific references so that we don't need // the compile unit at a later time in order to work with the form diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 4194e1c32c5a..5051a5125f26 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -10,9 +10,10 @@ #ifndef SymbolFileDWARF_DWARFFormValue_h_ #define SymbolFileDWARF_DWARFFormValue_h_ -#include "SymbolFileDWARF.h" #include // for NULL +class DWARFCompileUnit; + class DWARFFormValue { public: @@ -52,6 +53,7 @@ public: bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; } const uint8_t* BlockData() const; uint64_t Reference(const DWARFCompileUnit* cu) const; + uint64_t Reference (dw_offset_t offset) const; bool ResolveCompileUnitReferences(const DWARFCompileUnit* cu); uint64_t Unsigned() const { return m_value.value.uval; } void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index 43b3830726a6..690072de0131 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -11,17 +11,55 @@ #define SymbolFileDWARF_HashedNameToDIE_h_ #include + +#include "DWARFFormValue.h" + #include "lldb/lldb-defines.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/MappedHash.h" + class SymbolFileDWARF; +class DWARFCompileUnit; +class DWARFDebugInfoEntry; struct DWARFMappedHash { + struct DIEInfo + { + dw_offset_t offset; // The DIE offset + uint32_t type_flags; // Any flags for this DIEInfo + + DIEInfo (dw_offset_t _offset = DW_INVALID_OFFSET, + uint32_t _type_flags = 0) : + offset(_offset), + type_flags (_type_flags) + { + } + + void + Clear() + { + offset = DW_INVALID_OFFSET; + type_flags = 0; + } + }; + + typedef std::vector DIEInfoArray; typedef std::vector 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 AtomArray; + static uint32_t + GetTypeFlags (SymbolFileDWARF *dwarf2Data, + const DWARFCompileUnit* cu, + const DWARFDebugInfoEntry* die); + static const char * GetAtomTypeName (uint16_t atom) { @@ -66,14 +140,18 @@ struct DWARFMappedHash // DIE offset base so die offsets in hash_data can be CU relative dw_offset_t die_base_offset; AtomArray atoms; + size_t min_hash_data_byte_size; Prologue (dw_offset_t _die_base_offset = 0) : - die_base_offset (_die_base_offset) + die_base_offset (_die_base_offset), + atoms(), + min_hash_data_byte_size(0) { // 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 - atoms.push_back (Atom(eAtomTypeDIEOffset, DW_FORM_data4)); + AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); + min_hash_data_byte_size = 4; } virtual ~Prologue() @@ -87,12 +165,60 @@ struct DWARFMappedHash atoms.clear(); } + void + AppendAtom (AtomType type, dw_form_t form) + { + atoms.push_back (Atom(type, form)); + 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_flag: + case DW_FORM_data1: + case DW_FORM_ref1: + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_sec_offset: + case DW_FORM_ref_udata: + min_hash_data_byte_size += 1; + break; + case DW_FORM_block2: + case DW_FORM_data2: + case DW_FORM_ref2: + min_hash_data_byte_size += 2; + break; + case DW_FORM_block4: + 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); uint32_t Read (const lldb_private::DataExtractor &data, uint32_t offset) { + atoms.clear(); + die_base_offset = data.GetU32 (&offset); const uint32_t atom_count = data.GetU32 (&offset); @@ -103,16 +229,15 @@ struct DWARFMappedHash /* do nothing */; // Hardcode to the only know value for now. - atoms.push_back (Atom(eAtomTypeDIEOffset, DW_FORM_data4)); + AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); } else { - Atom atom; for (uint32_t i=0; i @@ -147,6 +279,11 @@ struct DWARFMappedHash return header_data.GetByteSize(); } + size_t + GetHashDataByteSize () + { + return header_data.GetHashDataByteSize(); + } // virtual void // Dump (std::ostream* ostrm_ptr); @@ -161,9 +298,89 @@ struct DWARFMappedHash } return offset; } - // - // virtual void - // Write (BinaryStreamBuf &s); + + bool + Read (const lldb_private::DataExtractor &data, + uint32_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 0) + strm.PutCString (", "); + + DWARFFormValue form_value (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 eAtomTypeTypeFlags: // Flags from enum TypeFlags + strm.Printf ("0x%2.2x ( type = ", hash_data.type_flags); + switch (hash_data.type_flags & eTypeFlagClassMask) + { + case eTypeClassInvalid: strm.PutCString ("invalid"); break; + case eTypeClassOther: strm.PutCString ("other"); break; + case eTypeClassBuiltIn: strm.PutCString ("built-in"); break; + case eTypeClassClassOrStruct: strm.PutCString ("class-struct"); break; + case eTypeClassClassOBJC: strm.PutCString ("class-objc"); break; + case eTypeClassEnum: strm.PutCString ("enum"); break; + case eTypeClassTypedef: strm.PutCString ("typedef"); break; + case eTypeClassUnion: strm.PutCString ("union"); break; + default: strm.PutCString ("???"); break; + } + + if (hash_data.type_flags & ~eTypeFlagClassMask) + { + strm.PutCString (", flags ="); + if (hash_data.type_flags & eTypeFlagNameIsFullyQualified) + strm.PutCString (" qualified"); + + if (hash_data.type_flags & eTypeFlagClassIsImplementation) + strm.PutCString (" implementation"); + } + strm.PutCString (" )"); + break; + + default: + strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); + break; + } + } + } + }; // class ExportTable @@ -210,7 +427,7 @@ struct DWARFMappedHash // }; // // // Map uniqued .debug_str offset to the corresponding DIE offsets -// typedef std::map NameInfo; +// typedef std::map NameInfo; // // Map a name hash to one or more name infos // typedef std::map BucketEntry; // @@ -226,14 +443,14 @@ struct DWARFMappedHash // A class for reading and using a saved hash table from a block of data // in memory - class MemoryTable : public MappedHash::MemoryTable + class MemoryTable : public MappedHash::MemoryTable { public: MemoryTable (lldb_private::DataExtractor &table_data, const lldb_private::DataExtractor &string_table, const char *name) : - MappedHash::MemoryTable (table_data), + MappedHash::MemoryTable (table_data), m_data (table_data), m_string_table (string_table), m_name (name) @@ -270,14 +487,18 @@ struct DWARFMappedHash return eResultError; const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); - const uint32_t data_size = count * sizeof(uint32_t); + const uint32_t data_size = count * m_header.header_data.GetHashDataByteSize(); if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, data_size)) { if (strcmp (name, strp_cstr) == 0) { pair.value.clear(); for (uint32_t i=0; i 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, data_size)) { if (regex.Execute(strp_cstr)) { for (uint32_t i=0; iAppendAllDIEsThatMatchingRegex (regex, die_offsets); + { + DWARFMappedHash::DIEInfoArray hash_data_array; + if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex (regex, hash_data_array)) + DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); + } } else { @@ -2556,8 +2560,10 @@ SymbolFileDWARF::FindFunctions (const RegularExpression ®ex, SymbolContextList& sc_list) { DIEArray die_offsets; - if (memory_table.AppendAllDIEsThatMatchingRegex (regex, die_offsets)) + DWARFMappedHash::DIEInfoArray hash_data_array; + if (memory_table.AppendAllDIEsThatMatchingRegex (regex, hash_data_array)) { + DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); ParseFunctions (die_offsets, sc_list); } } @@ -2965,7 +2971,12 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, Symb } uint32_t -SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) +SymbolFileDWARF::FindTypes (const SymbolContext& sc, + const ConstString &name, + const lldb_private::ClangNamespaceDecl *namespace_decl, + bool append, + uint32_t max_matches, + TypeList& types) { DWARFDebugInfo* info = DebugInfo(); if (info == NULL) @@ -3113,6 +3124,7 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc, { namespace_decl.SetASTContext (GetClangASTContext().getASTContext()); namespace_decl.SetNamespaceDecl (clang_namespace_decl); + break; } } else @@ -3929,8 +3941,18 @@ SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu, { if (m_apple_types_ap.get()) { - const char *name_cstr = type_name.GetCString(); - m_apple_types_ap->FindByName (name_cstr, die_offsets); + if (m_apple_types_ap->GetHeader().header_data.atoms.size() > 1) + { + std::string qualified_name; + const char *qualified_cstr = die->GetQualifiedName(this, cu, qualified_name); + DWARFMappedHash::DIEInfoArray hash_data_array; + m_apple_types_ap->FindByName (qualified_cstr, hash_data_array); + DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); + } + else + { + m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets); + } } } else @@ -5308,9 +5330,15 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) if (m_using_apple_tables) { if (m_apple_names_ap.get()) - m_apple_names_ap->AppendAllDIEsInRange (dwarf_cu->GetOffset(), - dwarf_cu->GetNextCompileUnitOffset(), - die_offsets); + { + DWARFMappedHash::DIEInfoArray hash_data_array; + if (m_apple_names_ap->AppendAllDIEsInRange (dwarf_cu->GetOffset(), + dwarf_cu->GetNextCompileUnitOffset(), + hash_data_array)) + { + DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); + } + } } else { @@ -5387,7 +5415,7 @@ SymbolFileDWARF::ParseVariableDIE const char *mangled = NULL; Declaration decl; uint32_t i; - Type *var_type = NULL; + lldb::user_id_t type_uid = LLDB_INVALID_UID; DWARFExpression location; bool is_external = false; bool is_artificial = false; @@ -5407,7 +5435,7 @@ SymbolFileDWARF::ParseVariableDIE 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_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; - case DW_AT_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); break; + case DW_AT_type: type_uid = form_value.Reference(dwarf_cu); break; case DW_AT_external: is_external = form_value.Unsigned() != 0; break; case DW_AT_const_value: location_is_const_value_data = true; @@ -5457,8 +5485,6 @@ SymbolFileDWARF::ParseVariableDIE if (location.IsValid()) { - assert(var_type != DIE_IS_BEING_PARSED); - ValueType scope = eValueTypeInvalid; const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); @@ -5477,64 +5503,74 @@ SymbolFileDWARF::ParseVariableDIE // then we can correctly classify our variables. if (tag == DW_TAG_formal_parameter) scope = eValueTypeVariableArgument; - else if (location.LocationContains_DW_OP_addr ()) + else { - if (is_external) + // Check if the location has a DW_OP_addr with any address value... + addr_t location_has_op_addr = false; + if (!location_is_const_value_data) + location_has_op_addr = location.LocationContains_DW_OP_addr (); + + if (location_has_op_addr) { - if (m_debug_map_symfile) + if (is_external) { - // When leaving the DWARF in the .o files on darwin, - // when we have a global variable that wasn't initialized, - // the .o file might not have allocated a virtual - // address for the global variable. In this case it will - // have created a symbol for the global variable - // that is undefined and external and the value will - // be the byte size of the variable. When we do the - // address map in SymbolFileDWARFDebugMap we rely on - // having an address, we need to do some magic here - // so we can get the correct address for our global - // variable. The address for all of these entries - // will be zero, and there will be an undefined symbol - // in this object file, and the executable will have - // a matching symbol with a good address. So here we - // dig up the correct address and replace it in the - // location for the variable, and set the variable's - // symbol context scope to be that of the main executable - // so the file address will resolve correctly. - if (location.LocationContains_DW_OP_addr (0)) + scope = eValueTypeVariableGlobal; + + if (m_debug_map_symfile) { - - // we have a possible uninitialized extern global - Symtab *symtab = m_obj_file->GetSymtab(); - if (symtab) + // When leaving the DWARF in the .o files on darwin, + // when we have a global variable that wasn't initialized, + // the .o file might not have allocated a virtual + // address for the global variable. In this case it will + // have created a symbol for the global variable + // that is undefined and external and the value will + // be the byte size of the variable. When we do the + // address map in SymbolFileDWARFDebugMap we rely on + // having an address, we need to do some magic here + // so we can get the correct address for our global + // variable. The address for all of these entries + // will be zero, and there will be an undefined symbol + // in this object file, and the executable will have + // a matching symbol with a good address. So here we + // dig up the correct address and replace it in the + // location for the variable, and set the variable's + // symbol context scope to be that of the main executable + // so the file address will resolve correctly. + if (location.LocationContains_DW_OP_addr (0)) { - ConstString const_name(name); - Symbol *undefined_symbol = symtab->FindFirstSymbolWithNameAndType (const_name, - eSymbolTypeUndefined, - Symtab::eDebugNo, - Symtab::eVisibilityExtern); - if (undefined_symbol) + // we have a possible uninitialized extern global + Symtab *symtab = m_obj_file->GetSymtab(); + if (symtab) { - ObjectFile *debug_map_objfile = m_debug_map_symfile->GetObjectFile(); - if (debug_map_objfile) + ConstString const_name(name); + Symbol *undefined_symbol = symtab->FindFirstSymbolWithNameAndType (const_name, + eSymbolTypeUndefined, + Symtab::eDebugNo, + Symtab::eVisibilityExtern); + + if (undefined_symbol) { - Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); - Symbol *defined_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, - eSymbolTypeData, - Symtab::eDebugYes, - Symtab::eVisibilityExtern); - if (defined_symbol) + ObjectFile *debug_map_objfile = m_debug_map_symfile->GetObjectFile(); + if (debug_map_objfile) { - const AddressRange *defined_range = defined_symbol->GetAddressRangePtr(); - if (defined_range) + Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); + Symbol *defined_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, + eSymbolTypeData, + Symtab::eDebugYes, + Symtab::eVisibilityExtern); + if (defined_symbol) { - const addr_t defined_addr = defined_range->GetBaseAddress().GetFileAddress(); - if (defined_addr != LLDB_INVALID_ADDRESS) + const AddressRange *defined_range = defined_symbol->GetAddressRangePtr(); + if (defined_range) { - if (location.Update_DW_OP_addr (defined_addr)) + const addr_t defined_addr = defined_range->GetBaseAddress().GetFileAddress(); + if (defined_addr != LLDB_INVALID_ADDRESS) { - symbol_context_scope = defined_symbol; + if (location.Update_DW_OP_addr (defined_addr)) + { + symbol_context_scope = defined_symbol; + } } } } @@ -5544,13 +5580,16 @@ SymbolFileDWARF::ParseVariableDIE } } } - scope = eValueTypeVariableGlobal; + else + { + scope = eValueTypeVariableStatic; + } } else - scope = eValueTypeVariableStatic; + { + scope = eValueTypeVariableLocal; + } } - else - scope = eValueTypeVariableLocal; if (symbol_context_scope == NULL) { @@ -5578,7 +5617,7 @@ SymbolFileDWARF::ParseVariableDIE var_sp.reset (new Variable (MakeUserID(die->GetOffset()), name, mangled, - var_type, + SymbolFileTypeSP (new SymbolFileType(*this, type_uid)), scope, symbol_context_scope, &decl, diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 706e4defa276..80571d0207a6 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -30,6 +30,15 @@ using namespace lldb; using namespace lldb_private; +Type * +SymbolFileType::GetType () +{ + if (!m_type_sp) + m_type_sp = m_symbol_file.ResolveTypeUID (GetID()); + return m_type_sp.get(); +} + + Type::Type ( lldb::user_id_t uid, diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index d5bba289e59d..cb3f86eb97f3 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -36,7 +36,7 @@ Variable::Variable lldb::user_id_t uid, const char *name, const char *mangled, // The mangled variable name for variables in namespaces - Type *type, + const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, SymbolContextScope *context, Declaration* decl_ptr, @@ -47,7 +47,7 @@ Variable::Variable UserID(uid), m_name(name), m_mangled (mangled, true), - m_type(type), + m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), m_declaration(decl_ptr), @@ -81,6 +81,14 @@ Variable::NameMatches (const RegularExpression& regex) const return m_mangled.NameMatches (regex); } +Type * +Variable::GetType() +{ + if (m_symfile_type_sp) + return m_symfile_type_sp->GetType(); + return NULL; +} + void Variable::Dump(Stream *s, bool show_context) const { @@ -91,11 +99,15 @@ Variable::Dump(Stream *s, bool show_context) const if (m_name) *s << ", name = \"" << m_name << "\""; - if (m_type != NULL) + if (m_symfile_type_sp) { - *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " ("; - m_type->DumpTypeName(s); - s->PutChar(')'); + Type *type = m_symfile_type_sp->GetType(); + if (type) + { + *s << ", type = {" << type->GetID() << "} " << (void*)type << " ("; + type->DumpTypeName(s); + s->PutChar(')'); + } } if (m_scope != eValueTypeInvalid) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 978ab5ec4d5c..a887866b02e7 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1471,13 +1471,19 @@ Target::EvaluateExpression ExecutionResults execution_results = eExecutionSetupError; result_valobj_sp.reset(); - + + if (expr_cstr == NULL || expr_cstr[0] == '\0') + return execution_results; + // We shouldn't run stop hooks in expressions. // Be sure to reset this if you return anywhere within this function. bool old_suppress_value = m_suppress_stop_hooks; m_suppress_stop_hooks = true; ExecutionContext exe_ctx; + + const size_t expr_cstr_len = ::strlen (expr_cstr); + if (frame) { frame->CalculateExecutionContext(exe_ctx); @@ -1486,11 +1492,17 @@ Target::EvaluateExpression StackFrame::eExpressionPathOptionsNoFragileObjcIvar | StackFrame::eExpressionPathOptionsNoSyntheticChildren; lldb::VariableSP var_sp; - result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, - use_dynamic, - expr_path_options, - var_sp, - error); + + // Make sure we don't have any things that we know a variable expression + // won't be able to deal with before calling into it + if (::strcspn (expr_cstr, "()+*&|!~<=/^%,?") == expr_cstr_len) + { + result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, + use_dynamic, + expr_path_options, + var_sp, + error); + } } else if (m_process_sp) {