diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
| commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
| tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Symbol | |
| parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) | |
Notes
Diffstat (limited to 'source/Symbol')
31 files changed, 3743 insertions, 1038 deletions
diff --git a/source/Symbol/ArmUnwindInfo.cpp b/source/Symbol/ArmUnwindInfo.cpp index 0d3e974bebbe..95207cbe320d 100644 --- a/source/Symbol/ArmUnwindInfo.cpp +++ b/source/Symbol/ArmUnwindInfo.cpp @@ -103,7 +103,7 @@ ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_o while (offset < max_offset) { uint8_t byte = GetByteAtOffset(data, offset++); - result |= (byte & 0x7f) << shift; + result |= (uint64_t)(byte & 0x7f) << shift; if ((byte & 0x80) == 0) break; shift += 7; diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp index dfe9217362bd..9d50c5cb7c9a 100644 --- a/source/Symbol/Block.cpp +++ b/source/Symbol/Block.cpp @@ -486,16 +486,24 @@ uint32_t Block::AppendBlockVariables (bool can_create, bool get_child_block_variables, bool stop_if_child_block_is_inlined_function, + const std::function<bool(Variable*)>& filter, VariableList *variable_list) { uint32_t num_variables_added = 0; VariableList *block_var_list = GetBlockVariableList (can_create).get(); if (block_var_list) { - num_variables_added += block_var_list->GetSize(); - variable_list->AddVariables (block_var_list); + for (size_t i = 0; i < block_var_list->GetSize(); ++i) + { + VariableSP variable = block_var_list->GetVariableAtIndex(i); + if (filter(variable.get())) + { + num_variables_added++; + variable_list->AddVariable(variable); + } + } } - + if (get_child_block_variables) { collection::const_iterator pos, end = m_children.end(); @@ -508,6 +516,7 @@ Block::AppendBlockVariables (bool can_create, num_variables_added += child_block->AppendBlockVariables (can_create, get_child_block_variables, stop_if_child_block_is_inlined_function, + filter, variable_list); } } @@ -521,6 +530,7 @@ Block::AppendVariables bool can_create, bool get_parent_variables, bool stop_if_block_is_inlined_function, + const std::function<bool(Variable*)>& filter, VariableList *variable_list ) { @@ -528,12 +538,19 @@ Block::AppendVariables VariableListSP variable_list_sp(GetBlockVariableList(can_create)); bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; - if (variable_list_sp.get()) + if (variable_list_sp) { - num_variables_added = variable_list_sp->GetSize(); - variable_list->AddVariables(variable_list_sp.get()); + for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) + { + VariableSP variable = variable_list_sp->GetVariableAtIndex(i); + if (filter(variable.get())) + { + num_variables_added++; + variable_list->AddVariable(variable); + } + } } - + if (get_parent_variables) { if (stop_if_block_is_inlined_function && is_inlined_function) @@ -541,7 +558,11 @@ Block::AppendVariables Block* parent_block = GetParent(); if (parent_block) - num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); + num_variables_added += parent_block->AppendVariables(can_create, + get_parent_variables, + stop_if_block_is_inlined_function, + filter, + variable_list); } return num_variables_added; } diff --git a/source/Symbol/CMakeLists.txt b/source/Symbol/CMakeLists.txt index 6372fffde1f1..320a780dc98e 100644 --- a/source/Symbol/CMakeLists.txt +++ b/source/Symbol/CMakeLists.txt @@ -5,6 +5,7 @@ add_lldb_library(lldbSymbol ClangASTImporter.cpp ClangExternalASTSourceCallbacks.cpp ClangExternalASTSourceCommon.cpp + ClangUtil.cpp CompilerDecl.cpp CompilerDeclContext.cpp CompilerType.cpp @@ -16,6 +17,7 @@ add_lldb_library(lldbSymbol Function.cpp FuncUnwinders.cpp GoASTContext.cpp + JavaASTContext.cpp LineEntry.cpp LineTable.cpp ObjectFile.cpp diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index 621bd1615f80..02882ef2ef4d 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -63,21 +63,24 @@ #include "llvm/Support/Signals.h" +#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h" +#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Flags.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/Scalar.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" -#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h" -#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h" -#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/VerifyDecl.h" @@ -86,8 +89,10 @@ #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" +#include "Plugins/SymbolFile/PDB/PDBASTParser.h" #include <stdio.h> @@ -105,7 +110,10 @@ namespace return language == eLanguageTypeUnknown || // Clang is the default type system Language::LanguageIsC (language) || Language::LanguageIsCPlusPlus (language) || - Language::LanguageIsObjC (language); + Language::LanguageIsObjC (language) || + // Use Clang for Rust until there is a proper language plugin for it + language == eLanguageTypeRust || + language == eLanguageTypeExtRenderScript; } } @@ -332,22 +340,7 @@ ClangASTContext::ClangASTContext (const char *target_triple) : //---------------------------------------------------------------------- ClangASTContext::~ClangASTContext() { - if (m_ast_ap.get()) - { - GetASTMap().Erase(m_ast_ap.get()); - if (!m_ast_owned) - m_ast_ap.release(); - } - - m_builtins_ap.reset(); - m_selector_table_ap.reset(); - m_identifier_table_ap.reset(); - m_target_info_ap.reset(); - m_target_options_rp.reset(); - m_diagnostics_engine_ap.reset(); - m_source_manager_ap.reset(); - m_language_options_ap.reset(); - m_ast_ap.reset(); + Finalize(); } ConstString @@ -471,6 +464,27 @@ ClangASTContext::Terminate() PluginManager::UnregisterPlugin (CreateInstance); } +void +ClangASTContext::Finalize() +{ + if (m_ast_ap.get()) + { + GetASTMap().Erase(m_ast_ap.get()); + if (!m_ast_owned) + m_ast_ap.release(); + } + + m_builtins_ap.reset(); + m_selector_table_ap.reset(); + m_identifier_table_ap.reset(); + m_target_info_ap.reset(); + m_target_options_rp.reset(); + m_diagnostics_engine_ap.reset(); + m_source_manager_ap.reset(); + m_language_options_ap.reset(); + m_ast_ap.reset(); + m_scratch_ast_source_ap.reset(); +} void ClangASTContext::Clear() @@ -678,8 +692,9 @@ public: { m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); } - - void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const Diagnostic &info) + + void + HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { if (m_log) { @@ -707,11 +722,11 @@ ClangASTContext::getDiagnosticConsumer() return m_diagnostic_consumer_ap.get(); } -std::shared_ptr<TargetOptions> & +std::shared_ptr<clang::TargetOptions> & ClangASTContext::getTargetOptions() { if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) { - m_target_options_rp = std::make_shared<TargetOptions>(); + m_target_options_rp = std::make_shared<clang::TargetOptions>(); if (m_target_options_rp.get() != nullptr) m_target_options_rp->Triple = m_target_triple; } @@ -773,8 +788,8 @@ ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding break; case eEncodingSint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); + if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) + return CompilerType (ast, ast->SignedCharTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) return CompilerType (ast, ast->ShortTy); if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) @@ -901,113 +916,12 @@ ClangASTContext::GetBasicType (lldb::BasicType basic_type) CompilerType ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type) { - if (ast) - { - lldb::opaque_compiler_type_t clang_type = nullptr; - - switch (basic_type) - { - case eBasicTypeInvalid: - case eBasicTypeOther: - break; - case eBasicTypeVoid: - clang_type = ast->VoidTy.getAsOpaquePtr(); - break; - case eBasicTypeChar: - clang_type = ast->CharTy.getAsOpaquePtr(); - break; - case eBasicTypeSignedChar: - clang_type = ast->SignedCharTy.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedChar: - clang_type = ast->UnsignedCharTy.getAsOpaquePtr(); - break; - case eBasicTypeWChar: - clang_type = ast->getWCharType().getAsOpaquePtr(); - break; - case eBasicTypeSignedWChar: - clang_type = ast->getSignedWCharType().getAsOpaquePtr(); - break; - case eBasicTypeUnsignedWChar: - clang_type = ast->getUnsignedWCharType().getAsOpaquePtr(); - break; - case eBasicTypeChar16: - clang_type = ast->Char16Ty.getAsOpaquePtr(); - break; - case eBasicTypeChar32: - clang_type = ast->Char32Ty.getAsOpaquePtr(); - break; - case eBasicTypeShort: - clang_type = ast->ShortTy.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedShort: - clang_type = ast->UnsignedShortTy.getAsOpaquePtr(); - break; - case eBasicTypeInt: - clang_type = ast->IntTy.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedInt: - clang_type = ast->UnsignedIntTy.getAsOpaquePtr(); - break; - case eBasicTypeLong: - clang_type = ast->LongTy.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedLong: - clang_type = ast->UnsignedLongTy.getAsOpaquePtr(); - break; - case eBasicTypeLongLong: - clang_type = ast->LongLongTy.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedLongLong: - clang_type = ast->UnsignedLongLongTy.getAsOpaquePtr(); - break; - case eBasicTypeInt128: - clang_type = ast->Int128Ty.getAsOpaquePtr(); - break; - case eBasicTypeUnsignedInt128: - clang_type = ast->UnsignedInt128Ty.getAsOpaquePtr(); - break; - case eBasicTypeBool: - clang_type = ast->BoolTy.getAsOpaquePtr(); - break; - case eBasicTypeHalf: - clang_type = ast->HalfTy.getAsOpaquePtr(); - break; - case eBasicTypeFloat: - clang_type = ast->FloatTy.getAsOpaquePtr(); - break; - case eBasicTypeDouble: - clang_type = ast->DoubleTy.getAsOpaquePtr(); - break; - case eBasicTypeLongDouble: - clang_type = ast->LongDoubleTy.getAsOpaquePtr(); - break; - case eBasicTypeFloatComplex: - clang_type = ast->FloatComplexTy.getAsOpaquePtr(); - break; - case eBasicTypeDoubleComplex: - clang_type = ast->DoubleComplexTy.getAsOpaquePtr(); - break; - case eBasicTypeLongDoubleComplex: - clang_type = ast->LongDoubleComplexTy.getAsOpaquePtr(); - break; - case eBasicTypeObjCID: - clang_type = ast->getObjCIdType().getAsOpaquePtr(); - break; - case eBasicTypeObjCClass: - clang_type = ast->getObjCClassType().getAsOpaquePtr(); - break; - case eBasicTypeObjCSel: - clang_type = ast->getObjCSelType().getAsOpaquePtr(); - break; - case eBasicTypeNullPtr: - clang_type = ast->NullPtrTy.getAsOpaquePtr(); - break; - } - - if (clang_type) - return CompilerType (GetASTContext(ast), clang_type); - } + if (!ast) + return CompilerType(); + lldb::opaque_compiler_type_t clang_type = GetOpaqueCompilerType(ast, basic_type); + + if (clang_type) + return CompilerType(GetASTContext(ast), clang_type); return CompilerType(); } @@ -1049,7 +963,7 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name if (::strstr(type_name, "complex")) { CompilerType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); - return CompilerType (ast, ast->getComplexType (GetQualType(complex_int_clang_type))); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_int_clang_type))); } } break; @@ -1064,7 +978,7 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name else { CompilerType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); - return CompilerType (ast, ast->getComplexType (GetQualType(complex_float_clang_type))); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_float_clang_type))); } break; @@ -1294,9 +1208,9 @@ ClangASTContext::AreTypesSame (CompilerType type1, if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) return true; - QualType type1_qual = GetQualType(type1); - QualType type2_qual = GetQualType(type2); - + QualType type1_qual = ClangUtil::GetQualType(type1); + QualType type2_qual = ClangUtil::GetQualType(type2); + if (ignore_qualifiers) { type1_qual = type1_qual.getUnqualifiedType(); @@ -1488,9 +1402,7 @@ ClangASTContext::CreateFunctionTemplateSpecializationInfo (FunctionDecl *func_de clang::FunctionTemplateDecl *func_tmpl_decl, const TemplateParameterInfos &infos) { - TemplateArgumentList template_args (TemplateArgumentList::OnStack, - infos.args.data(), - infos.args.size()); + TemplateArgumentList template_args (TemplateArgumentList::OnStack, infos.args); func_decl->setFunctionTemplateSpecialization (func_tmpl_decl, &template_args, @@ -1588,8 +1500,7 @@ ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx, SourceLocation(), SourceLocation(), class_template_decl, - &template_param_infos.args.front(), - template_param_infos.args.size(), + template_param_infos.args, nullptr); class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization); @@ -1652,25 +1563,14 @@ ClangASTContext::CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, ui clang::AccessSpecifier ClangASTContext::UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs) { - clang::AccessSpecifier ret = lhs; - // Make the access equal to the stricter of the field and the nested field's access - switch (ret) - { - case clang::AS_none: - break; - case clang::AS_private: - break; - case clang::AS_protected: - if (rhs == AS_private) - ret = AS_private; - break; - case clang::AS_public: - ret = rhs; - break; - } - - return ret; + if (lhs == AS_none || rhs == AS_none) + return AS_none; + if (lhs == AS_private || rhs == AS_private) + return AS_private; + if (lhs == AS_protected || rhs == AS_protected) + return AS_protected; + return AS_public; } bool @@ -1884,6 +1784,17 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d return namespace_decl; } +NamespaceDecl * +ClangASTContext::GetUniqueNamespaceDeclaration (clang::ASTContext *ast, + const char *name, + clang::DeclContext *decl_ctx) +{ + ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast); + if (ast_ctx == nullptr) + return nullptr; + + return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx); +} clang::BlockDecl * ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx) @@ -1977,6 +1888,78 @@ ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, co return nullptr; } +lldb::opaque_compiler_type_t +ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast, lldb::BasicType basic_type) +{ + switch (basic_type) + { + case eBasicTypeVoid: + return ast->VoidTy.getAsOpaquePtr(); + case eBasicTypeChar: + return ast->CharTy.getAsOpaquePtr(); + case eBasicTypeSignedChar: + return ast->SignedCharTy.getAsOpaquePtr(); + case eBasicTypeUnsignedChar: + return ast->UnsignedCharTy.getAsOpaquePtr(); + case eBasicTypeWChar: + return ast->getWCharType().getAsOpaquePtr(); + case eBasicTypeSignedWChar: + return ast->getSignedWCharType().getAsOpaquePtr(); + case eBasicTypeUnsignedWChar: + return ast->getUnsignedWCharType().getAsOpaquePtr(); + case eBasicTypeChar16: + return ast->Char16Ty.getAsOpaquePtr(); + case eBasicTypeChar32: + return ast->Char32Ty.getAsOpaquePtr(); + case eBasicTypeShort: + return ast->ShortTy.getAsOpaquePtr(); + case eBasicTypeUnsignedShort: + return ast->UnsignedShortTy.getAsOpaquePtr(); + case eBasicTypeInt: + return ast->IntTy.getAsOpaquePtr(); + case eBasicTypeUnsignedInt: + return ast->UnsignedIntTy.getAsOpaquePtr(); + case eBasicTypeLong: + return ast->LongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLong: + return ast->UnsignedLongTy.getAsOpaquePtr(); + case eBasicTypeLongLong: + return ast->LongLongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLongLong: + return ast->UnsignedLongLongTy.getAsOpaquePtr(); + case eBasicTypeInt128: + return ast->Int128Ty.getAsOpaquePtr(); + case eBasicTypeUnsignedInt128: + return ast->UnsignedInt128Ty.getAsOpaquePtr(); + case eBasicTypeBool: + return ast->BoolTy.getAsOpaquePtr(); + case eBasicTypeHalf: + return ast->HalfTy.getAsOpaquePtr(); + case eBasicTypeFloat: + return ast->FloatTy.getAsOpaquePtr(); + case eBasicTypeDouble: + return ast->DoubleTy.getAsOpaquePtr(); + case eBasicTypeLongDouble: + return ast->LongDoubleTy.getAsOpaquePtr(); + case eBasicTypeFloatComplex: + return ast->FloatComplexTy.getAsOpaquePtr(); + case eBasicTypeDoubleComplex: + return ast->DoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeLongDoubleComplex: + return ast->LongDoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeObjCID: + return ast->getObjCIdType().getAsOpaquePtr(); + case eBasicTypeObjCClass: + return ast->getObjCClassType().getAsOpaquePtr(); + case eBasicTypeObjCSel: + return ast->getObjCSelType().getAsOpaquePtr(); + case eBasicTypeNullPtr: + return ast->NullPtrTy.getAsOpaquePtr(); + default: + return nullptr; + } +} + #pragma mark Function Types FunctionDecl * @@ -1997,31 +1980,17 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, if (name && name[0]) { - func_decl = FunctionDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - DeclarationName (&ast->Idents.get(name)), - GetQualType(function_clang_type), - nullptr, - (clang::StorageClass)storage, - is_inline, - hasWrittenPrototype, - isConstexprSpecified); + func_decl = FunctionDecl::Create( + *ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName(&ast->Idents.get(name)), + ClangUtil::GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, is_inline, + hasWrittenPrototype, isConstexprSpecified); } else { - func_decl = FunctionDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - DeclarationName (), - GetQualType(function_clang_type), - nullptr, - (clang::StorageClass)storage, - is_inline, - hasWrittenPrototype, - isConstexprSpecified); + func_decl = + FunctionDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), DeclarationName(), + ClangUtil::GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, + is_inline, hasWrittenPrototype, isConstexprSpecified); } if (func_decl) decl_ctx->addDecl (func_decl); @@ -2041,10 +2010,33 @@ ClangASTContext::CreateFunctionType (ASTContext *ast, bool is_variadic, unsigned type_quals) { - assert (ast != nullptr); + if (ast == nullptr) + return CompilerType(); // invalid AST + + if (!result_type || !ClangUtil::IsClangType(result_type)) + return CompilerType(); // invalid return type + std::vector<QualType> qual_type_args; + if (num_args > 0 && args == nullptr) + return CompilerType(); // invalid argument array passed in + + // Verify that all arguments are valid and the right type for (unsigned i=0; i<num_args; ++i) - qual_type_args.push_back (GetQualType(args[i])); + { + if (args[i]) + { + // Make sure we have a clang type in args[i] and not a type from another + // language whose name might match + const bool is_clang_type = ClangUtil::IsClangType(args[i]); + lldbassert(is_clang_type); + if (is_clang_type) + qual_type_args.push_back(ClangUtil::GetQualType(args[i])); + else + return CompilerType(); // invalid argument type (must be a clang type) + } + else + return CompilerType(); // invalid argument type (empty) + } // TODO: Detect calling convention in DWARF? FunctionProtoType::ExtProtoInfo proto_info; @@ -2053,9 +2045,7 @@ ClangASTContext::CreateFunctionType (ASTContext *ast, proto_info.TypeQuals = type_quals; proto_info.RefQualifier = RQ_None; - return CompilerType (ast, ast->getFunctionType (GetQualType(result_type), - qual_type_args, - proto_info)); + return CompilerType(ast, ast->getFunctionType(ClangUtil::GetQualType(result_type), qual_type_args, proto_info)); } ParmVarDecl * @@ -2063,15 +2053,9 @@ ClangASTContext::CreateParameterDeclaration (const char *name, const CompilerTyp { ASTContext *ast = getASTContext(); assert (ast != nullptr); - return ParmVarDecl::Create(*ast, - ast->getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, - GetQualType(param_type), - nullptr, - (clang::StorageClass)storage, - nullptr); + return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, ClangUtil::GetQualType(param_type), + nullptr, (clang::StorageClass)storage, nullptr); } void @@ -2081,6 +2065,13 @@ ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl function_decl->setParams (ArrayRef<ParmVarDecl*>(params, num_params)); } +CompilerType +ClangASTContext::CreateBlockPointerType (const CompilerType &function_type) +{ + QualType block_type = m_ast_ap->getBlockPointerType(clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); + + return CompilerType (this, block_type.getAsOpaquePtr()); +} #pragma mark Array Types @@ -2096,7 +2087,7 @@ ClangASTContext::CreateArrayType (const CompilerType &element_type, if (is_vector) { - return CompilerType (ast, ast->getExtVectorType(GetQualType(element_type), element_count)); + return CompilerType(ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), element_count)); } else { @@ -2104,16 +2095,13 @@ ClangASTContext::CreateArrayType (const CompilerType &element_type, llvm::APInt ap_element_count (64, element_count); if (element_count == 0) { - return CompilerType (ast, ast->getIncompleteArrayType (GetQualType(element_type), - ArrayType::Normal, - 0)); + return CompilerType(ast, ast->getIncompleteArrayType(ClangUtil::GetQualType(element_type), + clang::ArrayType::Normal, 0)); } else { - return CompilerType (ast, ast->getConstantArrayType (GetQualType(element_type), - ap_element_count, - ArrayType::Normal, - 0)); + return CompilerType(ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), + ap_element_count, clang::ArrayType::Normal, 0)); } } } @@ -2121,13 +2109,17 @@ ClangASTContext::CreateArrayType (const CompilerType &element_type, } CompilerType -ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) +ClangASTContext::CreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, + bool packed) { CompilerType type; - if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + if (!type_name.IsEmpty() && (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + { + lldbassert("Trying to create a type for an existing name"); return type; + } + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); StartTagDeclarationDefinition(type); for (const auto& field : type_fields) @@ -2138,6 +2130,20 @@ ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, return type; } +CompilerType +ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, + bool packed) +{ + CompilerType type; + if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + return type; + + return CreateStructForIdentifier (type_name, + type_fields, + packed); +} + #pragma mark Enumeration Types CompilerType @@ -2171,8 +2177,8 @@ ClangASTContext::CreateEnumerationType if (enum_decl) { // TODO: check if we should be setting the promotion type too? - enum_decl->setIntegerType(GetQualType(integer_clang_type)); - + enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); + enum_decl->setAccess(AS_public); // TODO respect what's in the debug info return CompilerType (ast, ast->getTagDeclType(enum_decl)); @@ -2565,7 +2571,7 @@ ClangASTContext::SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl clang::DeclContext * ClangASTContext::GetDeclContextForType (const CompilerType& type) { - return GetDeclContextForType(GetQualType(type)); + return GetDeclContextForType(ClangUtil::GetQualType(type)); } clang::DeclContext * @@ -2632,8 +2638,8 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool all external_ast_source->CompleteType(cxx_record_decl); if (cxx_record_decl->isCompleteDefinition()) { - cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true); cxx_record_decl->field_begin(); + cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true); } } } @@ -3082,9 +3088,11 @@ ClangASTContext::IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, Comp bool is_hva = false; bool is_hfa = false; clang::QualType base_qual_type; + uint64_t base_bitwidth = 0; for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos) { clang::QualType field_qual_type = field_pos->getType(); + uint64_t field_bitwidth = getASTContext()->getTypeSize (qual_type); if (field_qual_type->isFloatingType()) { if (field_qual_type->isComplexType()) @@ -3105,22 +3113,21 @@ ClangASTContext::IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, Comp } else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType()) { - const clang::VectorType *array = field_qual_type.getTypePtr()->getAs<clang::VectorType>(); - if (array && array->getNumElements() <= 4) + if (num_fields == 0) { - if (num_fields == 0) - base_qual_type = array->getElementType(); - else - { - if (is_hfa) - return 0; - is_hva = true; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } + base_qual_type = field_qual_type; + base_bitwidth = field_bitwidth; } else - return 0; + { + if (is_hfa) + return 0; + is_hva = true; + if (base_bitwidth != field_bitwidth) + return 0; + if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) + return 0; + } } else return 0; @@ -3166,7 +3173,7 @@ ClangASTContext::GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, { if (type) { - clang::QualType qual_type (GetCanonicalQualType(type)); + clang::QualType qual_type (GetQualType(type)); const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); if (func) { @@ -3216,6 +3223,52 @@ ClangASTContext::IsFunctionPointerType (lldb::opaque_compiler_type_t type) } bool +ClangASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + if (type) + { + clang::QualType qual_type (GetCanonicalQualType(type)); + + if (qual_type->isBlockPointerType()) + { + if (function_pointer_type_ptr) + { + const clang::BlockPointerType *block_pointer_type = qual_type->getAs<clang::BlockPointerType>(); + QualType pointee_type = block_pointer_type->getPointeeType(); + QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); + *function_pointer_type_ptr = CompilerType (getASTContext(), function_pointer_type); + } + return true; + } + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + default: + break; + case clang::Type::Typedef: + return IsBlockPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Auto: + return IsBlockPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Elaborated: + return IsBlockPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), function_pointer_type_ptr); + case clang::Type::Paren: + return IsBlockPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), function_pointer_type_ptr); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + { + const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsBlockPointerType(reference_type->getPointeeType().getAsOpaquePtr(), function_pointer_type_ptr); + } + break; + } + } + return false; +} + +bool ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) { if (!type) @@ -3237,6 +3290,23 @@ ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_sign } bool +ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type, bool &is_signed) +{ + if (type) + { + const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)->getCanonicalTypeInternal()); + + if (enum_type) + { + IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(), is_signed); + return true; + } + } + + return false; +} + +bool ClangASTContext::IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { if (type) @@ -3466,8 +3536,8 @@ ClangASTContext::IsObjCClassType (const CompilerType& type) { if (type) { - clang::QualType qual_type (GetCanonicalQualType(type)); - + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); if (obj_pointer_type) @@ -3479,13 +3549,33 @@ ClangASTContext::IsObjCClassType (const CompilerType& type) bool ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type) { - if (IsClangType(type)) - return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); + if (ClangUtil::IsClangType(type)) + return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); return false; } bool -ClangASTContext::IsPolymorphicClass (lldb::opaque_compiler_type_t type) +ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) +{ + if (!type) + return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Record); +} + +bool +ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) +{ + if (!type) + return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Enum); +} + +bool +ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { if (type) { @@ -3539,6 +3629,14 @@ ClangASTContext::IsPossibleDynamicType (lldb::opaque_compiler_type_t type, Compi case clang::Type::ObjCObjectPointer: if (check_objc) { + if (auto objc_pointee_type = qual_type->getPointeeType().getTypePtrOrNull()) + { + if (auto objc_object_type = llvm::dyn_cast_or_null<clang::ObjCObjectType>(objc_pointee_type)) + { + if (objc_object_type->isObjCClass()) + return false; + } + } if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); return true; @@ -3696,7 +3794,7 @@ ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_n { if (type) { - clang::QualType qual_type (GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); if (!qual_type.isNull()) { clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); @@ -3717,8 +3815,8 @@ ClangASTContext::IsCXXClassType (const CompilerType& type) { if (!type) return false; - - clang::QualType qual_type (GetCanonicalQualType(type)); + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) return true; return false; @@ -3742,7 +3840,7 @@ ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType if (!type) return false; - clang::QualType qual_type (GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) { @@ -3770,9 +3868,9 @@ ClangASTContext::GetObjCClassName (const CompilerType& type, std::string &class_ { if (!type) return false; - - clang::QualType qual_type (GetCanonicalQualType(type)); - + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); if (object_type) { @@ -3809,7 +3907,6 @@ ClangASTContext::GetTypeName (lldb::opaque_compiler_type_t type) clang::PrintingPolicy printing_policy (getASTContext()->getPrintingPolicy()); clang::QualType qual_type(GetQualType(type)); printing_policy.SuppressTagKeyword = true; - printing_policy.LangOpts.WChar = true; const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>(); if (typedef_type) { @@ -4491,7 +4588,7 @@ ClangASTContext::CreateTypedefType (const CompilerType& type, if (!ast) return CompilerType(); clang::ASTContext* clang_ast = ast->getASTContext(); - clang::QualType qual_type (GetQualType(type)); + clang::QualType qual_type(ClangUtil::GetQualType(type)); clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); if (decl_ctx == nullptr) @@ -4621,6 +4718,20 @@ ClangASTContext::CreateTypedef (lldb::opaque_compiler_type_t type, const char *t &clang_ast->Idents.get(typedef_name), clang_ast->getTrivialTypeSourceInfo(qual_type)); + clang::TagDecl *tdecl = nullptr; + if (!qual_type.isNull()) + { + if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) + tdecl = rt->getDecl(); + if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) + tdecl = et->getDecl(); + } + + // Check whether this declaration is an anonymous struct, union, or enum, hidden behind a typedef. If so, we + // try to check whether we have a typedef tag to attach to the original record declaration + if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl()) + tdecl->setTypedefNameForAnonDecl(decl); + decl->setAccess(clang::AS_public); // TODO respect proper access specifier // Get a uniqued clang::QualType for the typedef decl type @@ -4643,18 +4754,6 @@ ClangASTContext::GetTypedefedType (lldb::opaque_compiler_type_t type) return CompilerType(); } -CompilerType -ClangASTContext::RemoveFastQualifiers (const CompilerType& type) -{ - if (IsClangType(type)) - { - clang::QualType qual_type(GetQualType(type)); - qual_type.getQualifiers().removeFastQualifiers(); - return CompilerType (type.GetTypeSystem(), qual_type.getAsOpaquePtr()); - } - return type; -} - //---------------------------------------------------------------------- // Create related types using the current type's AST @@ -4675,8 +4774,16 @@ ClangASTContext::GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContext if (GetCompleteType (type)) { clang::QualType qual_type(GetCanonicalQualType(type)); - switch (qual_type->getTypeClass()) + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) + return getASTContext()->getTypeSize(qual_type); + else + return 0; + break; + case clang::Type::ObjCInterface: case clang::Type::ObjCObject: { @@ -4710,7 +4817,7 @@ ClangASTContext::GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContext } } } - // fallthrough + LLVM_FALLTHROUGH; default: const uint32_t bit_size = getASTContext()->getTypeSize (qual_type); if (bit_size == 0) @@ -4740,97 +4847,127 @@ ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count { if (!type) return lldb::eEncodingInvalid; - + count = 1; clang::QualType qual_type(GetCanonicalQualType(type)); - + switch (qual_type->getTypeClass()) { case clang::Type::UnaryTransform: break; - + case clang::Type::FunctionNoProto: case clang::Type::FunctionProto: break; - + case clang::Type::IncompleteArray: case clang::Type::VariableArray: break; - + case clang::Type::ConstantArray: break; - + case clang::Type::ExtVector: case clang::Type::Vector: // TODO: Set this to more than one??? break; - + case clang::Type::Builtin: switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::Void: - break; - - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: return lldb::eEncodingSint; - - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: return lldb::eEncodingUint; - - case clang::BuiltinType::Half: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754; - - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint; - - case clang::BuiltinType::NullPtr: return lldb::eEncodingUint; - - case clang::BuiltinType::Kind::ARCUnbridgedCast: - case clang::BuiltinType::Kind::BoundMember: - case clang::BuiltinType::Kind::BuiltinFn: - case clang::BuiltinType::Kind::Dependent: - case clang::BuiltinType::Kind::OCLClkEvent: - case clang::BuiltinType::Kind::OCLEvent: - case clang::BuiltinType::Kind::OCLImage1d: - case clang::BuiltinType::Kind::OCLImage1dArray: - case clang::BuiltinType::Kind::OCLImage1dBuffer: - case clang::BuiltinType::Kind::OCLImage2d: - case clang::BuiltinType::Kind::OCLImage2dArray: - case clang::BuiltinType::Kind::OCLImage2dArrayDepth: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAA: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepth: - case clang::BuiltinType::Kind::OCLImage2dDepth: - case clang::BuiltinType::Kind::OCLImage2dMSAA: - case clang::BuiltinType::Kind::OCLImage2dMSAADepth: - case clang::BuiltinType::Kind::OCLImage3d: - case clang::BuiltinType::Kind::OCLQueue: - case clang::BuiltinType::Kind::OCLNDRange: - case clang::BuiltinType::Kind::OCLReserveID: - case clang::BuiltinType::Kind::OCLSampler: - case clang::BuiltinType::Kind::OMPArraySection: - case clang::BuiltinType::Kind::Overload: - case clang::BuiltinType::Kind::PseudoObject: - case clang::BuiltinType::Kind::UnknownAny: - break; - } + { + case clang::BuiltinType::Void: + break; + + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + return lldb::eEncodingSint; + + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + return lldb::eEncodingUint; + + case clang::BuiltinType::Half: + case clang::BuiltinType::Float: + case clang::BuiltinType::Float128: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return lldb::eEncodingIEEE754; + + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCSel: + return lldb::eEncodingUint; + + case clang::BuiltinType::NullPtr: + return lldb::eEncodingUint; + + case clang::BuiltinType::Kind::ARCUnbridgedCast: + case clang::BuiltinType::Kind::BoundMember: + case clang::BuiltinType::Kind::BuiltinFn: + case clang::BuiltinType::Kind::Dependent: + case clang::BuiltinType::Kind::OCLClkEvent: + case clang::BuiltinType::Kind::OCLEvent: + case clang::BuiltinType::Kind::OCLImage1dRO: + case clang::BuiltinType::Kind::OCLImage1dWO: + case clang::BuiltinType::Kind::OCLImage1dRW: + case clang::BuiltinType::Kind::OCLImage1dArrayRO: + case clang::BuiltinType::Kind::OCLImage1dArrayWO: + case clang::BuiltinType::Kind::OCLImage1dArrayRW: + case clang::BuiltinType::Kind::OCLImage1dBufferRO: + case clang::BuiltinType::Kind::OCLImage1dBufferWO: + case clang::BuiltinType::Kind::OCLImage1dBufferRW: + case clang::BuiltinType::Kind::OCLImage2dRO: + case clang::BuiltinType::Kind::OCLImage2dWO: + case clang::BuiltinType::Kind::OCLImage2dRW: + case clang::BuiltinType::Kind::OCLImage2dArrayRO: + case clang::BuiltinType::Kind::OCLImage2dArrayWO: + case clang::BuiltinType::Kind::OCLImage2dArrayRW: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage2dDepthRO: + case clang::BuiltinType::Kind::OCLImage2dDepthWO: + case clang::BuiltinType::Kind::OCLImage2dDepthRW: + case clang::BuiltinType::Kind::OCLImage2dMSAARO: + case clang::BuiltinType::Kind::OCLImage2dMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dMSAARW: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage3dRO: + case clang::BuiltinType::Kind::OCLImage3dWO: + case clang::BuiltinType::Kind::OCLImage3dRW: + case clang::BuiltinType::Kind::OCLQueue: + case clang::BuiltinType::Kind::OCLNDRange: + case clang::BuiltinType::Kind::OCLReserveID: + case clang::BuiltinType::Kind::OCLSampler: + case clang::BuiltinType::Kind::OMPArraySection: + case clang::BuiltinType::Kind::Overload: + case clang::BuiltinType::Kind::PseudoObject: + case clang::BuiltinType::Kind::UnknownAny: + break; + } break; // All pointer types are represented as unsigned integer encodings. // We may nee to add a eEncodingPointer if we ever need to know the @@ -4857,7 +4994,7 @@ ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count count = 2; return encoding; } - + case clang::Type::ObjCInterface: break; case clang::Type::Record: break; case clang::Type::Enum: return lldb::eEncodingSint; @@ -4866,13 +5003,13 @@ ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count case clang::Type::Auto: return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetEncoding(count); - + case clang::Type::Elaborated: return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count); - + case clang::Type::Paren: return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetEncoding(count); - + case clang::Type::DependentSizedArray: case clang::Type::DependentSizedExtVector: case clang::Type::UnresolvedUsing: @@ -4885,7 +5022,7 @@ ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count case clang::Type::DependentTemplateSpecialization: case clang::Type::PackExpansion: case clang::Type::ObjCObject: - + case clang::Type::TypeOfExpr: case clang::Type::TypeOf: case clang::Type::Decltype: @@ -4894,7 +5031,7 @@ ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count case clang::Type::Adjusted: case clang::Type::Pipe: break; - + // pointer type decayed from an array or function type. case clang::Type::Decayed: break; @@ -5213,7 +5350,7 @@ ClangASTContext::GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_em CompilerType ClangASTContext::GetBuiltinTypeByName (const ConstString &name) { - return GetBasicType (GetBasicTypeEnumeration (name)); + return GetBasicType(GetBasicTypeEnumeration(name)); } lldb::BasicType @@ -5817,7 +5954,8 @@ ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, return GetVirtualBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr); case clang::Type::Paren: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, bit_offset_ptr); + return GetVirtualBaseClassAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, + bit_offset_ptr); default: break; @@ -5848,12 +5986,24 @@ ClangASTContext::GetNumPointeeChildren (clang::QualType type) case clang::BuiltinType::Void: case clang::BuiltinType::NullPtr: case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1d: - case clang::BuiltinType::OCLImage1dArray: - case clang::BuiltinType::OCLImage1dBuffer: - case clang::BuiltinType::OCLImage2d: - case clang::BuiltinType::OCLImage2dArray: - case clang::BuiltinType::OCLImage3d: + case clang::BuiltinType::OCLImage1dRO: + case clang::BuiltinType::OCLImage1dWO: + case clang::BuiltinType::OCLImage1dRW: + case clang::BuiltinType::OCLImage1dArrayRO: + case clang::BuiltinType::OCLImage1dArrayWO: + case clang::BuiltinType::OCLImage1dArrayRW: + case clang::BuiltinType::OCLImage1dBufferRO: + case clang::BuiltinType::OCLImage1dBufferWO: + case clang::BuiltinType::OCLImage1dBufferRW: + case clang::BuiltinType::OCLImage2dRO: + case clang::BuiltinType::OCLImage2dWO: + case clang::BuiltinType::OCLImage2dRW: + case clang::BuiltinType::OCLImage2dArrayRO: + case clang::BuiltinType::OCLImage2dArrayWO: + case clang::BuiltinType::OCLImage2dArrayRW: + case clang::BuiltinType::OCLImage3dRO: + case clang::BuiltinType::OCLImage3dWO: + case clang::BuiltinType::OCLImage3dRW: case clang::BuiltinType::OCLSampler: return 0; case clang::BuiltinType::Bool: @@ -6070,8 +6220,9 @@ ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type, { clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl); const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity(); - const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); - if (base_offset != UINT32_MAX) + const uint32_t base_offset_size = process->GetAddressByteSize(); + const uint64_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, base_offset_size, UINT32_MAX, err); + if (base_offset < UINT32_MAX) { handled = true; bit_offset = base_offset * 8; @@ -6123,12 +6274,20 @@ ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type, CompilerType field_clang_type (getASTContext(), field->getType()); assert(field_idx < record_layout.getFieldCount()); child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + const uint32_t child_bit_size = child_byte_size * 8; // Figure out the field offset within the current struct/union/class type bit_offset = record_layout.getFieldOffset (field_idx); - child_byte_offset = bit_offset / 8; if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, child_bitfield_bit_size)) - child_bitfield_bit_offset = bit_offset % 8; + { + child_bitfield_bit_offset = bit_offset % child_bit_size; + const uint32_t child_bit_offset = bit_offset - child_bitfield_bit_offset; + child_byte_offset = child_bit_offset / 8; + } + else + { + child_byte_offset = bit_offset / 8; + } return field_clang_type; } @@ -7216,7 +7375,7 @@ CompilerType ClangASTContext::GetTypeForFormatters (void* type) { if (type) - return RemoveFastQualifiers(CompilerType(this, type)); + return ClangUtil::RemoveFastQualifiers(CompilerType(this, type)); return CompilerType(); } @@ -7439,7 +7598,7 @@ IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind) clang::EnumDecl * ClangASTContext::GetAsEnumDecl (const CompilerType& type) { - const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); + const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type)); if (enutype) return enutype->getDecl(); return NULL; @@ -7448,7 +7607,7 @@ ClangASTContext::GetAsEnumDecl (const CompilerType& type) clang::RecordDecl * ClangASTContext::GetAsRecordDecl (const CompilerType& type) { - const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(GetCanonicalQualType(type)); + const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type)); if (record_type) return record_type->getDecl(); return nullptr; @@ -7457,7 +7616,7 @@ ClangASTContext::GetAsRecordDecl (const CompilerType& type) clang::TagDecl * ClangASTContext::GetAsTagDecl (const CompilerType& type) { - clang::QualType qual_type = GetCanonicalQualType(type); + clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type); if (qual_type.isNull()) return nullptr; else @@ -7473,7 +7632,8 @@ ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type) clang::ObjCInterfaceDecl * ClangASTContext::GetAsObjCInterfaceDecl (const CompilerType& type) { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(GetCanonicalQualType(type)); + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(ClangUtil::GetCanonicalQualType(type)); if (objc_class_type) return objc_class_type->getInterface(); return nullptr; @@ -7504,17 +7664,14 @@ ClangASTContext::AddFieldToRecordType (const CompilerType& type, const char *nam clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); if (record_decl) { - field = clang::FieldDecl::Create (*clang_ast, - record_decl, - clang::SourceLocation(), - clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - GetQualType(field_clang_type), // Field type - nullptr, // TInfo * - bit_width, // BitWidth - false, // Mutable - clang::ICIS_NoInit); // HasInit - + field = clang::FieldDecl::Create(*clang_ast, record_decl, clang::SourceLocation(), clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TInfo * + bit_width, // BitWidth + false, // Mutable + clang::ICIS_NoInit); // HasInit + if (!name) { // Determine whether this field corresponds to an anonymous @@ -7549,18 +7706,14 @@ ClangASTContext::AddFieldToRecordType (const CompilerType& type, const char *nam const bool is_synthesized = false; field_clang_type.GetCompleteType(); - - field = clang::ObjCIvarDecl::Create (*clang_ast, - class_interface_decl, - clang::SourceLocation(), - clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - GetQualType(field_clang_type), // Field type - nullptr, // TypeSourceInfo * - ConvertAccessTypeToObjCIvarAccessControl (access), - bit_width, - is_synthesized); - + + field = clang::ObjCIvarDecl::Create( + *clang_ast, class_interface_decl, clang::SourceLocation(), clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TypeSourceInfo * + ConvertAccessTypeToObjCIvarAccessControl(access), bit_width, is_synthesized); + if (field) { class_interface_decl->addDecl(field); @@ -7625,8 +7778,7 @@ ClangASTContext::BuildIndirectFields (const CompilerType& type) clang::SourceLocation(), nested_field_decl->getIdentifier(), nested_field_decl->getType(), - chain, - 2); + {chain, 2}); indirect_field->setImplicit(); @@ -7637,7 +7789,7 @@ ClangASTContext::BuildIndirectFields (const CompilerType& type) } else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) { - int nested_chain_size = nested_indirect_field_decl->getChainingSize(); + size_t nested_chain_size = nested_indirect_field_decl->getChainingSize(); clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[nested_chain_size + 1]; chain[0] = *field_pos; @@ -7656,8 +7808,7 @@ ClangASTContext::BuildIndirectFields (const CompilerType& type) clang::SourceLocation(), nested_indirect_field_decl->getIdentifier(), nested_indirect_field_decl->getType(), - chain, - nested_chain_size + 1); + {chain, nested_chain_size + 1}); indirect_field->setImplicit(); @@ -7720,14 +7871,15 @@ ClangASTContext::AddVariableToRecordType (const CompilerType& type, const char * clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); if (record_decl) { - var_decl = clang::VarDecl::Create (*ast->getASTContext(), // ASTContext & - record_decl, // DeclContext * - clang::SourceLocation(), // clang::SourceLocation StartLoc - clang::SourceLocation(), // clang::SourceLocation IdLoc - name ? &ast->getASTContext()->Idents.get(name) : nullptr, // clang::IdentifierInfo * - GetQualType(var_type), // Variable clang::QualType - nullptr, // TypeSourceInfo * - clang::SC_Static); // StorageClass + var_decl = + clang::VarDecl::Create(*ast->getASTContext(), // ASTContext & + record_decl, // DeclContext * + clang::SourceLocation(), // clang::SourceLocation StartLoc + clang::SourceLocation(), // clang::SourceLocation IdLoc + name ? &ast->getASTContext()->Idents.get(name) : nullptr, // clang::IdentifierInfo * + ClangUtil::GetQualType(var_type), // Variable clang::QualType + nullptr, // TypeSourceInfo * + clang::SC_Static); // StorageClass if (var_decl) { var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); @@ -7762,9 +7914,9 @@ ClangASTContext::AddMethodToCXXRecordType (lldb::opaque_compiler_type_t type, co if (cxx_record_decl == nullptr) return nullptr; - - clang::QualType method_qual_type (GetQualType(method_clang_type)); - + + clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); + clang::CXXMethodDecl *cxx_method_decl = nullptr; clang::DeclarationName decl_name (&getASTContext()->Idents.get(name)); @@ -8048,17 +8200,16 @@ ClangASTContext::AddObjCClassProperty (const CompilerType& type, if (ivar_decl) prop_type_source = clang_ast->getTrivialTypeSourceInfo (ivar_decl->getType()); else - prop_type_source = clang_ast->getTrivialTypeSourceInfo (GetQualType(property_clang_type)); - - clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*clang_ast, - class_interface_decl, - clang::SourceLocation(), // Source Location - &clang_ast->Idents.get(property_name), - clang::SourceLocation(), //Source Location for AT - clang::SourceLocation(), //Source location for ( - ivar_decl ? ivar_decl->getType() : ClangASTContext::GetQualType(property_clang_type), - prop_type_source); - + prop_type_source = clang_ast->getTrivialTypeSourceInfo(ClangUtil::GetQualType(property_clang_type)); + + clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create( + *clang_ast, class_interface_decl, + clang::SourceLocation(), // Source Location + &clang_ast->Idents.get(property_name), + clang::SourceLocation(), // Source Location for AT + clang::SourceLocation(), // Source location for ( + ivar_decl ? ivar_decl->getType() : ClangUtil::GetQualType(property_clang_type), prop_type_source); + if (property_decl) { if (metadata) @@ -8113,32 +8264,32 @@ ClangASTContext::AddObjCClassProperty (const CompilerType& type, property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy); if (property_attributes & DW_APPLE_PROPERTY_nonatomic) property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic); - - if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel)) + if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_nullability) + property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_nullability); + if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_null_resettable) + property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_null_resettable); + if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) + property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_class); + + const bool isInstance = (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) == 0; + + if (!getter_sel.isNull() && + !(isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel) + : class_interface_decl->lookupClassMethod(getter_sel))) { - const bool isInstance = true; const bool isVariadic = false; const bool isSynthesized = false; const bool isImplicitlyDeclared = true; const bool isDefined = false; const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; const bool HasRelatedResultType = false; - - clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*clang_ast, - clang::SourceLocation(), - clang::SourceLocation(), - getter_sel, - GetQualType(property_clang_type_to_access), - nullptr, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - + + clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create( + *clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel, + ClangUtil::GetQualType(property_clang_type_to_access), nullptr, class_interface_decl, + isInstance, isVariadic, isSynthesized, isImplicitlyDeclared, isDefined, impControl, + HasRelatedResultType); + if (getter && metadata) ClangASTContext::SetMetadata(clang_ast, getter, *metadata); @@ -8149,12 +8300,12 @@ ClangASTContext::AddObjCClassProperty (const CompilerType& type, class_interface_decl->addDecl(getter); } } - - if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) + + if (!setter_sel.isNull() && + !(isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel) + : class_interface_decl->lookupClassMethod(setter_sel))) { clang::QualType result_type = clang_ast->VoidTy; - - const bool isInstance = true; const bool isVariadic = false; const bool isSynthesized = false; const bool isImplicitlyDeclared = true; @@ -8181,17 +8332,12 @@ ClangASTContext::AddObjCClassProperty (const CompilerType& type, ClangASTContext::SetMetadata(clang_ast, setter, *metadata); llvm::SmallVector<clang::ParmVarDecl *, 1> params; - - params.push_back (clang::ParmVarDecl::Create (*clang_ast, - setter, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - GetQualType(property_clang_type_to_access), - nullptr, - clang::SC_Auto, - nullptr)); - + + params.push_back(clang::ParmVarDecl::Create( + *clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(), + nullptr, // anonymous + ClangUtil::GetQualType(property_clang_type_to_access), nullptr, clang::SC_Auto, nullptr)); + if (setter) { setter->setMethodParams(*clang_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>()); @@ -8222,7 +8368,8 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, const char *name, // the full symbol name as seen in the symbol table (lldb::opaque_compiler_type_t type, "-[NString stringWithCString:]") const CompilerType &method_clang_type, lldb::AccessType access, - bool is_artificial) + bool is_artificial, + bool is_variadic) { if (!type || !method_clang_type.IsValid()) return nullptr; @@ -8267,9 +8414,9 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, clang::Selector method_selector = ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0, selector_idents.data()); - - clang::QualType method_qual_type (GetQualType(method_clang_type)); - + + clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); + // Populate the method decl with parameter decls const clang::Type *method_type(method_qual_type.getTypePtr()); @@ -8282,7 +8429,6 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, return nullptr; - bool is_variadic = false; bool is_synthesized = false; bool is_defined = false; clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None; @@ -8291,23 +8437,18 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, if (num_args != num_selectors_with_args) return nullptr; // some debug information is corrupt. We are not going to deal with it. - - clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*ast, - clang::SourceLocation(), // beginLoc, - clang::SourceLocation(), // endLoc, - method_selector, - method_function_prototype->getReturnType(), - nullptr, // TypeSourceInfo *ResultTInfo, - ClangASTContext::GetASTContext(ast)->GetDeclContextForType(GetQualType(type)), - name[0] == '-', - is_variadic, - is_synthesized, - true, // is_implicitly_declared; we force this to true because we don't have source locations - is_defined, - imp_control, - false /*has_related_result_type*/); - - + + clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create( + *ast, + clang::SourceLocation(), // beginLoc, + clang::SourceLocation(), // endLoc, + method_selector, method_function_prototype->getReturnType(), + nullptr, // TypeSourceInfo *ResultTInfo, + ClangASTContext::GetASTContext(ast)->GetDeclContextForType(ClangUtil::GetQualType(type)), name[0] == '-', + is_variadic, is_synthesized, + true, // is_implicitly_declared; we force this to true because we don't have source locations + is_defined, imp_control, false /*has_related_result_type*/); + if (objc_method_decl == nullptr) return nullptr; @@ -8343,10 +8484,10 @@ ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, bool ClangASTContext::GetHasExternalStorage (const CompilerType &type) { - if (IsClangType(type)) + if (ClangUtil::IsClangType(type)) return false; - clang::QualType qual_type (GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) @@ -8474,158 +8615,12 @@ ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool } -bool -ClangASTContext::CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer) -{ - if (IsClangType(type)) - { - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL)) - return true; - } - } - break; - - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL)) - return true; - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL)) - return true; - } - } - } - break; - - - case clang::Type::Typedef: - return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer); - - case clang::Type::Auto: - return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()), importer); - - case clang::Type::Elaborated: - return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer); - - case clang::Type::Paren: - return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer); - - default: - break; - } - } - return false; -} -bool -ClangASTContext::Import (const CompilerType &type, lldb_private::ClangASTImporter &importer) -{ - if (IsClangType(type)) - { - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL)) - return importer.CompleteAndFetchChildren(qual_type); - } - } - break; - - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL)) - return importer.CompleteAndFetchChildren(qual_type); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL)) - return importer.CompleteAndFetchChildren(qual_type); - } - } - } - break; - - - case clang::Type::Typedef: - return Import (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer); - - case clang::Type::Auto: - return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()), importer); - - case clang::Type::Elaborated: - return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer); - - case clang::Type::Paren: - return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer); - - default: - break; - } - } - return false; -} - - #pragma mark TagDecl bool ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type) { - clang::QualType qual_type (ClangASTContext::GetQualType(type)); + clang::QualType qual_type(ClangUtil::GetQualType(type)); if (!qual_type.isNull()) { const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); @@ -8656,21 +8651,31 @@ ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type) bool ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type) { - clang::QualType qual_type (ClangASTContext::GetQualType(type)); + clang::QualType qual_type(ClangUtil::GetQualType(type)); if (!qual_type.isNull()) { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl) + // Make sure we use the same methodology as ClangASTContext::StartTagDeclarationDefinition() + // as to how we start/end the definition. Previously we were calling + const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); + if (tag_type) { - if (!cxx_record_decl->isCompleteDefinition()) - cxx_record_decl->completeDefinition(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); - cxx_record_decl->setHasExternalLexicalStorage (false); - cxx_record_decl->setHasExternalVisibleStorage (false); - return true; + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + { + clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(tag_decl); + + if (cxx_record_decl) + { + if (!cxx_record_decl->isCompleteDefinition()) + cxx_record_decl->completeDefinition(); + cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); + cxx_record_decl->setHasExternalLexicalStorage (false); + cxx_record_decl->setHasExternalVisibleStorage (false); + return true; + } + } } - + const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>(); if (enutype) @@ -8687,24 +8692,28 @@ ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type) clang::ASTContext *ast = lldb_ast->getASTContext(); /// TODO This really needs to be fixed. - - unsigned NumPositiveBits = 1; - unsigned NumNegativeBits = 0; - - clang::QualType promotion_qual_type; - // If the enum integer type is less than an integer in bit width, - // then we must promote it to an integer size. - if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy)) + + QualType integer_type(enum_decl->getIntegerType()); + if (!integer_type.isNull()) { - if (enum_decl->getIntegerType()->isSignedIntegerType()) - promotion_qual_type = ast->IntTy; + unsigned NumPositiveBits = 1; + unsigned NumNegativeBits = 0; + + clang::QualType promotion_qual_type; + // If the enum integer type is less than an integer in bit width, + // then we must promote it to an integer size. + if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy)) + { + if (enum_decl->getIntegerType()->isSignedIntegerType()) + promotion_qual_type = ast->IntTy; + else + promotion_qual_type = ast->UnsignedIntTy; + } else - promotion_qual_type = ast->UnsignedIntTy; + promotion_qual_type = enum_decl->getIntegerType(); + + enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); } - else - promotion_qual_type = enum_decl->getIntegerType(); - - enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); } return true; } @@ -8736,15 +8745,11 @@ ClangASTContext::AddEnumerationValueToEnumerationType (lldb::opaque_compiler_typ { llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); enum_llvm_apsint = enum_value; - clang::EnumConstantDecl *enumerator_decl = - clang::EnumConstantDecl::Create (*getASTContext(), - enutype->getDecl(), - clang::SourceLocation(), - name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier - GetQualType(enumerator_clang_type), - nullptr, - enum_llvm_apsint); - + clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create( + *getASTContext(), enutype->getDecl(), clang::SourceLocation(), + name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier + ClangUtil::GetQualType(enumerator_clang_type), nullptr, enum_llvm_apsint); + if (enumerator_decl) { enutype->getDecl()->addDecl(enumerator_decl); @@ -8787,9 +8792,9 @@ ClangASTContext::CreateMemberPointerType (const CompilerType& type, const Compil ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); if (!ast) return CompilerType(); - return CompilerType (ast->getASTContext(), - ast->getASTContext()->getMemberPointerType (GetQualType(pointee_type), - GetQualType(type).getTypePtr())); + return CompilerType(ast->getASTContext(), + ast->getASTContext()->getMemberPointerType(ClangUtil::GetQualType(pointee_type), + ClangUtil::GetQualType(type).getTypePtr())); } return CompilerType(); } @@ -8816,18 +8821,10 @@ ClangASTContext::ConvertStringToFloatValue (lldb::opaque_compiler_type_t type, c const uint64_t byte_size = bit_size / 8; if (dst_size >= byte_size) { - if (bit_size == sizeof(float)*8) - { - float float32 = ap_float.convertToFloat(); - ::memcpy (dst, &float32, byte_size); - return byte_size; - } - else if (bit_size >= 64) - { - llvm::APInt ap_int(ap_float.bitcastToAPInt()); - ::memcpy (dst, ap_int.getRawData(), byte_size); + Scalar scalar = ap_float.bitcastToAPInt().zextOrTrunc(llvm::NextPowerOf2(byte_size) * 8); + lldb_private::Error get_data_error; + if (scalar.GetAsMemoryData(dst, byte_size, lldb_private::endian::InlHostByteOrder(), get_data_error)) return byte_size; - } } } } @@ -9281,6 +9278,7 @@ ClangASTContext::DumpTypeValue (lldb::opaque_compiler_type_t type, Stream *s, return true; } // format was not enum, just fall through and dump the value as requested.... + LLVM_FALLTHROUGH; default: // We are down to a scalar type that we just need to display. @@ -9519,9 +9517,9 @@ ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream void ClangASTContext::DumpTypeName (const CompilerType &type) { - if (IsClangType(type)) + if (ClangUtil::IsClangType(type)) { - clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type))); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) @@ -9633,15 +9631,21 @@ ClangASTContext::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDec } } - DWARFASTParser * -ClangASTContext::GetDWARFParser () +ClangASTContext::GetDWARFParser() { if (!m_dwarf_ast_parser_ap) m_dwarf_ast_parser_ap.reset(new DWARFASTParserClang(*this)); return m_dwarf_ast_parser_ap.get(); } +PDBASTParser * +ClangASTContext::GetPDBParser() +{ + if (!m_pdb_ast_parser_ap) + m_pdb_ast_parser_ap.reset(new PDBASTParser(*this)); + return m_pdb_ast_parser_ap.get(); +} bool ClangASTContext::LayoutRecordType(void *baton, @@ -9654,30 +9658,13 @@ ClangASTContext::LayoutRecordType(void *baton, { ClangASTContext *ast = (ClangASTContext *)baton; DWARFASTParserClang *dwarf_ast_parser = (DWARFASTParserClang *)ast->GetDWARFParser(); - return dwarf_ast_parser->LayoutRecordType(record_decl, bit_size, alignment, field_offsets, base_offsets, vbase_offsets); + return dwarf_ast_parser->GetClangASTImporter().LayoutRecordType(record_decl, bit_size, alignment, field_offsets, + base_offsets, vbase_offsets); } //---------------------------------------------------------------------- // CompilerDecl override functions //---------------------------------------------------------------------- -lldb::VariableSP -ClangASTContext::DeclGetVariable (void *opaque_decl) -{ - if (llvm::dyn_cast<clang::VarDecl>((clang::Decl *)opaque_decl)) - { - auto decl_search_it = m_decl_objects.find(opaque_decl); - if (decl_search_it != m_decl_objects.end()) - return std::static_pointer_cast<Variable>(decl_search_it->second); - } - return VariableSP(); -} - -void -ClangASTContext::DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) -{ - if (m_decl_objects.find(opaque_decl) == m_decl_objects.end()) - m_decl_objects.insert(std::make_pair(opaque_decl, object)); -} ConstString ClangASTContext::DeclGetName (void *opaque_decl) @@ -9750,7 +9737,7 @@ ClangASTContext::DeclGetFunctionNumArguments(void *opaque_decl) if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl)) return func_decl->param_size(); if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl)) - return objc_method->param_size(); + return objc_method->param_size(); else return 0; } @@ -9764,7 +9751,7 @@ ClangASTContext::DeclGetFunctionArgumentType (void *opaque_decl, size_t idx) { ParmVarDecl *var_decl = func_decl->getParamDecl(idx); if (var_decl) - return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr()); + return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr()); } } else if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl)) @@ -9780,7 +9767,9 @@ ClangASTContext::DeclGetFunctionArgumentType (void *opaque_decl, size_t idx) //---------------------------------------------------------------------- std::vector<CompilerDecl> -ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name) +ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, + ConstString name, + const bool ignore_using_decls) { std::vector<CompilerDecl> found_decls; if (opaque_decl_ctx) @@ -9804,12 +9793,16 @@ ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString na { if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) { + if (ignore_using_decls) + continue; clang::DeclContext *from = ud->getCommonAncestor(); if (searched.find(ud->getNominatedNamespace()) == searched.end()) search_queue.insert(std::make_pair(from, ud->getNominatedNamespace())); } else if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child)) { + if (ignore_using_decls) + continue; for (clang::UsingShadowDecl *usd : ud->shadows()) { clang::Decl *target = usd->getTargetDecl(); @@ -9902,6 +9895,15 @@ ClangASTContext::CountDeclLevels (clang::DeclContext *frame_decl_ctx, { if (searched.find(it->second) != searched.end()) continue; + + // Currently DWARF has one shared translation unit for all Decls at top level, so this + // would erroneously find using statements anywhere. So don't look at the top-level + // translation unit. + // TODO fix this and add a testcase that depends on it. + + if (llvm::isa<clang::TranslationUnitDecl>(it->second)) + continue; + searched.insert(it->second); symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second)); diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp index 141937072c73..6be10602d998 100644 --- a/source/Symbol/ClangASTImporter.cpp +++ b/source/Symbol/ClangASTImporter.cpp @@ -7,16 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "llvm/Support/raw_ostream.h" +#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Utility/LLDBAssert.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "llvm/Support/raw_ostream.h" using namespace lldb_private; using namespace clang; @@ -347,6 +348,211 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx, return result; } +bool +ClangASTImporter::CanImport(const CompilerType &type) +{ + if (!ClangUtil::IsClangType(type)) + return false; + + // TODO: remove external completion BOOL + // CompleteAndFetchChildren should get the Decl out and check for the + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + return true; + } + } + break; + + case clang::Type::Enum: + { + clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) + { + if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + return true; + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) + { + if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + return true; + } + } + } + break; + + case clang::Type::Typedef: + return CanImport(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); + + case clang::Type::Auto: + return CanImport(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); + + case clang::Type::Elaborated: + return CanImport(CompilerType( + type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); + + case clang::Type::Paren: + return CanImport(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + + return false; +} + +bool +ClangASTImporter::Import(const CompilerType &type) +{ + if (!ClangUtil::IsClangType(type)) + return false; + // TODO: remove external completion BOOL + // CompleteAndFetchChildren should get the Decl out and check for the + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + { + const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + { + if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); + } + } + break; + + case clang::Type::Enum: + { + clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) + { + if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) + { + if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); + } + } + } + break; + + case clang::Type::Typedef: + return Import(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); + + case clang::Type::Auto: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); + + case clang::Type::Elaborated: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); + + case clang::Type::Paren: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + return false; +} + +bool +ClangASTImporter::CompleteType(const CompilerType &compiler_type) +{ + if (!CanImport(compiler_type)) + return false; + + if (Import(compiler_type)) + { + ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); + return true; + } + + ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), false); + return false; +} + +bool +ClangASTImporter::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; +} + +void +ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout) +{ + m_record_decl_to_layout_map.insert(std::make_pair(decl, layout)); +} + void ClangASTImporter::CompleteDecl (clang::Decl *decl) { @@ -729,16 +935,21 @@ ClangASTImporter::Minion::ExecuteDeportWorkQueues () if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) { if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) + { if (original_tag_decl->isCompleteDefinition()) + { ImportDefinitionTo(tag_decl, original_tag_decl); + tag_decl->setCompleteDefinition(true); + } + } tag_decl->setHasExternalLexicalStorage(false); tag_decl->setHasExternalVisibleStorage(false); } - else if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) + else if (ObjCContainerDecl *container_decl = dyn_cast<ObjCContainerDecl>(decl)) { - interface_decl->setHasExternalLexicalStorage(false); - interface_decl->setHasExternalVisibleStorage(false); + container_decl->setHasExternalLexicalStorage(false); + container_decl->setHasExternalVisibleStorage(false); } to_context_md->m_origins.erase(decl); @@ -753,8 +964,6 @@ ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from { ASTImporter::Imported(from, to); - ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to); - /* if (to_objc_interface) to_objc_interface->startDefinition(); @@ -766,12 +975,20 @@ ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from */ ImportDefinition(from); + + if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) + { + if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) + { + to_tag->setCompleteDefinition(from_tag->isCompleteDefinition()); + } + } // If we're dealing with an Objective-C class, ensure that the inheritance has // been set up correctly. The ASTImporter may not do this correctly if the // class was originally sourced from symbols. - if (to_objc_interface) + if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) { do { @@ -949,20 +1166,32 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to) to_namespace_decl->setHasExternalVisibleStorage(); } - if (isa<ObjCInterfaceDecl>(from)) + if (isa<ObjCContainerDecl>(from)) { - ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to); + ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to); - to_interface_decl->setHasExternalLexicalStorage(); - to_interface_decl->setHasExternalVisibleStorage(); + to_container_decl->setHasExternalLexicalStorage(); + to_container_decl->setHasExternalVisibleStorage(); /*to_interface_decl->setExternallyCompleted();*/ if (log) - log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s", - (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); + { + if (ObjCInterfaceDecl *to_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) + { + log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s", + (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), + (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); + } + else + { + log->Printf(" [ClangASTImporter] To is an %sDecl - attributes %s%s", + ((Decl*)to_container_decl)->getDeclKindName(), + (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); + } + } } return clang::ASTImporter::Imported(from, to); diff --git a/source/Symbol/ClangExternalASTSourceCommon.cpp b/source/Symbol/ClangExternalASTSourceCommon.cpp index 79cc9a91355a..77aea1eafc4f 100644 --- a/source/Symbol/ClangExternalASTSourceCommon.cpp +++ b/source/Symbol/ClangExternalASTSourceCommon.cpp @@ -9,7 +9,6 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Core/Stream.h" -#include "lldb/Host/Mutex.h" using namespace lldb_private; @@ -19,8 +18,9 @@ typedef llvm::DenseMap<clang::ExternalASTSource *, ClangExternalASTSourceCommon static ASTSourceMap &GetSourceMap() { - static ASTSourceMap s_source_map; - return s_source_map; + // Intentionally leaked to avoid problems with global destructors. + static ASTSourceMap *s_source_map = new ASTSourceMap; + return *s_source_map; } ClangExternalASTSourceCommon * diff --git a/source/Symbol/ClangUtil.cpp b/source/Symbol/ClangUtil.cpp new file mode 100644 index 000000000000..76d621e9ce44 --- /dev/null +++ b/source/Symbol/ClangUtil.cpp @@ -0,0 +1,58 @@ +//===-- ClangUtil.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// A collection of helper methods and data structures for manipulating clang +// types and decls. +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/ClangUtil.h" +#include "lldb/Symbol/ClangASTContext.h" + +using namespace clang; +using namespace lldb_private; + +bool +ClangUtil::IsClangType(const CompilerType &ct) +{ + if (llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) == nullptr) + return false; + + if (!ct.GetOpaqueQualType()) + return false; + + return true; +} + +QualType +ClangUtil::GetQualType(const CompilerType &ct) +{ + // Make sure we have a clang type before making a clang::QualType + if (!IsClangType(ct)) + return QualType(); + + return QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); +} + +QualType +ClangUtil::GetCanonicalQualType(const CompilerType &ct) +{ + if (!IsClangType(ct)) + return QualType(); + + return GetQualType(ct).getCanonicalType(); +} + +CompilerType +ClangUtil::RemoveFastQualifiers(const CompilerType &ct) +{ + if (!IsClangType(ct)) + return ct; + + QualType qual_type(GetQualType(ct)); + qual_type.removeLocalFastQualifiers(); + return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr()); +} diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp index 233ca91ec8d8..105c3c242c0f 100644 --- a/source/Symbol/CompactUnwindInfo.cpp +++ b/source/Symbol/CompactUnwindInfo.cpp @@ -101,6 +101,52 @@ namespace lldb_private { UNWIND_X86_64_REG_R15 = 5, UNWIND_X86_64_REG_RBP = 6, }; + + FLAGS_ANONYMOUS_ENUM() + { + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + + FLAGS_ANONYMOUS_ENUM() + { + UNWIND_ARM_MODE_MASK = 0x0F000000, + UNWIND_ARM_MODE_FRAME = 0x01000000, + UNWIND_ARM_MODE_FRAME_D = 0x02000000, + UNWIND_ARM_MODE_DWARF = 0x04000000, + + UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, + + UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, + UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, + UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, + + UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, + UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, + UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, + UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, + UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, + + UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, + + UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + } @@ -127,22 +173,20 @@ namespace lldb_private { //---------------------- -// constructor +// constructor //---------------------- - -CompactUnwindInfo::CompactUnwindInfo(ObjectFile& objfile, SectionSP& section_sp) : - m_objfile (objfile), - m_section_sp (section_sp), - m_section_contents_if_encrypted (), - m_mutex (), - m_indexes (), - m_indexes_computed (eLazyBoolCalculate), - m_unwindinfo_data (), - m_unwindinfo_data_computed (false), - m_unwind_header () +CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP §ion_sp) + : m_objfile(objfile), + m_section_sp(section_sp), + m_section_contents_if_encrypted(), + m_mutex(), + m_indexes(), + m_indexes_computed(eLazyBoolCalculate), + m_unwindinfo_data(), + m_unwindinfo_data_computed(false), + m_unwind_header() { - } //---------------------- @@ -175,7 +219,7 @@ CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwi if (log && log->GetVerbose()) { StreamString strm; - addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); + addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData()); } @@ -184,7 +228,7 @@ CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwi SectionList *sl = m_objfile.GetSectionList (); if (sl) { - addr_t func_range_start_file_addr = + addr_t func_range_start_file_addr = function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress(); AddressRange func_range (func_range_start_file_addr, function_info.valid_range_offset_end - function_info.valid_range_offset_start, @@ -197,10 +241,18 @@ CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwi { return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr); } + if (arch.GetTriple().getArch() == llvm::Triple::aarch64) + { + return CreateUnwindPlan_arm64 (target, function_info, unwind_plan, addr); + } if (arch.GetTriple().getArch() == llvm::Triple::x86) { return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr); } + if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) + { + return CreateUnwindPlan_armv7 (target, function_info, unwind_plan, addr); + } } } return false; @@ -223,7 +275,7 @@ CompactUnwindInfo::IsValid (const ProcessSP &process_sp) void CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) { - Mutex::Locker locker(m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) return; @@ -248,8 +300,8 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0)); Error error; if (process_sp->ReadMemory ( - m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()), - m_section_contents_if_encrypted->GetBytes(), + m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()), + m_section_contents_if_encrypted->GetBytes(), m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success()) { m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); @@ -279,7 +331,7 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) // uint32_t personalityArrayCount; // uint32_t indexSectionOffset; // uint32_t indexCount; - + m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset); m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset); @@ -305,13 +357,21 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) // Parse the basic information from the indexes // We wait to scan the second level page info until it's needed - // struct unwind_info_section_header_index_entry + // struct unwind_info_section_header_index_entry // { // uint32_t functionOffset; // uint32_t secondLevelPagesSectionOffset; // uint32_t lsdaIndexArraySectionOffset; // }; + bool clear_address_zeroth_bit = false; + ArchSpec arch; + if (m_objfile.GetArchitecture (arch)) + { + if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) + clear_address_zeroth_bit = true; + } + offset = indexSectionOffset; for (uint32_t idx = 0; idx < indexCount; idx++) { @@ -324,8 +384,11 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) m_indexes_computed = eLazyBoolNo; } + if (clear_address_zeroth_bit) + function_offset &= ~1ull; + UnwindIndex this_index; - this_index.function_offset = function_offset; // + this_index.function_offset = function_offset; this_index.second_level = second_level_offset; this_index.lsda_array_start = lsda_offset; @@ -352,7 +415,7 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset) { - // struct unwind_info_section_header_lsda_index_entry + // struct unwind_info_section_header_lsda_index_entry // { // uint32_t functionOffset; // uint32_t lsdaOffset; @@ -387,7 +450,7 @@ lldb::offset_t CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) { // typedef uint32_t compact_unwind_encoding_t; - // struct unwind_info_regular_second_level_entry + // struct unwind_info_regular_second_level_entry // { // uint32_t functionOffset; // compact_unwind_encoding_t encoding; @@ -502,10 +565,10 @@ CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address addr return false; addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); - + UnwindIndex key; key.function_offset = function_offset; - + std::vector<UnwindIndex>::const_iterator it; it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key); if (it == m_indexes.end()) @@ -527,7 +590,7 @@ CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address addr auto next_it = it + 1; if (next_it != m_indexes.end()) { - // initialize the function offset end range to be the start of the + // initialize the function offset end range to be the start of the // next index offset. If we find an entry which is at the end of // the index table, this will establish the range end. unwind_info.valid_range_offset_end = next_it->function_offset; @@ -549,7 +612,7 @@ CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address addr // uint16_t entryCount; // typedef uint32_t compact_unwind_encoding_t; - // struct unwind_info_regular_second_level_entry + // struct unwind_info_regular_second_level_entry // { // uint32_t functionOffset; // compact_unwind_encoding_t encoding; @@ -604,9 +667,9 @@ CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address addr // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED // uint16_t entryPageOffset; // offset from this 2nd lvl page idx to array of entries // // (an entry has a function offset and index into the encodings) - // // NB function offset from the entry in the compressed page + // // NB function offset from the entry in the compressed page // // must be added to the index's functionOffset value. - // uint16_t entryCount; + // uint16_t entryCount; // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings // uint16_t encodingsCount; @@ -626,7 +689,7 @@ CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address addr offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t)); encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the commonEncodingsArray } - else + else { uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count; offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t)); @@ -742,7 +805,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true); row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); - + uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); @@ -775,7 +838,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi case UNWIND_X86_64_MODE_STACK_IND: { // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this - // style of unwind. It was fixed in llvm r217020. + // style of unwind. It was fixed in llvm r217020. // The clang in Xcode 7 has this fixed. return false; } @@ -838,7 +901,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi // We need to include (up to) 6 registers in 10 bits. // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. + // the order they're saved on the stack. // // This is done with Lehmer code permutation, e.g. see // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms @@ -848,7 +911,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi // and gives us the Lehmer code sequence which can then // be decoded. - switch (register_count) + switch (register_count) { case 6: permunreg[0] = permutation/120; // 120 == 5! @@ -898,7 +961,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi permunreg[0] = permutation; break; } - + // Decode the Lehmer code for this permutation of // the registers v. http://en.wikipedia.org/wiki/Lehmer_code @@ -1025,7 +1088,7 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true); row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); - + uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); @@ -1106,13 +1169,13 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function row->SetOffset (0); row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); - + if (register_count > 0) { // We need to include (up to) 6 registers in 10 bits. // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. + // the order they're saved on the stack. // // This is done with Lehmer code permutation, e.g. see // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms @@ -1122,7 +1185,7 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function // and gives us the Lehmer code sequence which can then // be decoded. - switch (register_count) + switch (register_count) { case 6: permunreg[0] = permutation/120; // 120 == 5! @@ -1172,7 +1235,7 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function permunreg[0] = permutation; break; } - + // Decode the Lehmer code for this permutation of // the registers v. http://en.wikipedia.org/wiki/Lehmer_code @@ -1231,3 +1294,380 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function } return false; } + + + +// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" doc by ARM + +enum arm64_eh_regnum { + x19 = 19, + x20 = 20, + x21 = 21, + x22 = 22, + x23 = 23, + x24 = 24, + x25 = 25, + x26 = 26, + x27 = 27, + x28 = 28, + + fp = 29, + ra = 30, + sp = 31, + pc = 32, + + // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s for the 64-bit + // fp regs. Normally in DWARF it's context sensitive - so it knows it is fetching a + // 32- or 64-bit quantity from reg v8 to indicate s0 or d0 - but the unwinder is operating + // at a lower level and we'd try to fetch 128 bits if we were told that v8 were stored on + // the stack... + v8 = 72, + v9 = 73, + v10 = 74, + v11 = 75, + v12 = 76, + v13 = 77, + v14 = 78, + v15 = 79, +}; + +enum arm_eh_regnum { + arm_r0 = 0, + arm_r1 = 1, + arm_r2 = 2, + arm_r3 = 3, + arm_r4 = 4, + arm_r5 = 5, + arm_r6 = 6, + arm_r7 = 7, + arm_r8 = 8, + arm_r9 = 9, + arm_r10 = 10, + arm_r11 = 11, + arm_r12 = 12, + + arm_sp = 13, + arm_lr = 14, + arm_pc = 15, + + arm_d0 = 256, + arm_d1 = 257, + arm_d2 = 258, + arm_d3 = 259, + arm_d4 = 260, + arm_d5 = 261, + arm_d6 = 262, + arm_d7 = 263, + arm_d8 = 264, + arm_d9 = 265, + arm_d10 = 266, + arm_d11 = 267, + arm_d12 = 268, + arm_d13 = 269, + arm_d14 = 270, +}; + + + +bool +CompactUnwindInfo::CreateUnwindPlan_arm64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) +{ + unwind_plan.SetSourceName ("compact unwind info"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetRegisterKind (eRegisterKindEHFrame); + + unwind_plan.SetLSDAAddress (function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); + + UnwindPlan::RowSP row (new UnwindPlan::Row); + + const int wordsize = 8; + int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; + + if (mode == UNWIND_ARM64_MODE_DWARF) + return false; + + if (mode == UNWIND_ARM64_MODE_FRAMELESS) + { + row->SetOffset (0); + + uint32_t stack_size = (EXTRACT_BITS (function_info.encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 16; + + // Our previous Call Frame Address is the stack pointer plus the stack size + row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::sp, stack_size); + + // Our previous PC is in the LR + row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, true); + + unwind_plan.AppendRow (row); + return true; + } + + // Should not be possible + if (mode != UNWIND_ARM64_MODE_FRAME) + return false; + + + // mode == UNWIND_ARM64_MODE_FRAME + + row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::fp , 2 * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::fp, wordsize * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::pc, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (arm64_eh_regnum::sp, 0, true); + + int reg_pairs_saved_count = 1; + + uint32_t saved_register_bits = function_info.encoding & 0xfff; + + if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) + { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x19, cfa_offset, true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x20, cfa_offset, true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) + { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x21, cfa_offset, true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x22, cfa_offset, true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) + { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x23, cfa_offset, true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x24, cfa_offset, true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) + { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x25, cfa_offset, true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x26, cfa_offset, true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) + { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x27, cfa_offset, true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x28, cfa_offset, true); + reg_pairs_saved_count++; + } + + // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits off the stack; + // not sure if we have a good way to represent the 64-bitness of these saves. + + if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) + { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) + { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) + { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) + { + reg_pairs_saved_count++; + } + + unwind_plan.AppendRow (row); + return true; +} + +bool +CompactUnwindInfo::CreateUnwindPlan_armv7 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) +{ + unwind_plan.SetSourceName ("compact unwind info"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + unwind_plan.SetRegisterKind (eRegisterKindEHFrame); + + unwind_plan.SetLSDAAddress (function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); + + UnwindPlan::RowSP row (new UnwindPlan::Row); + + const int wordsize = 4; + int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; + + if (mode == UNWIND_ARM_MODE_DWARF) + return false; + + uint32_t stack_adjust = (EXTRACT_BITS (function_info.encoding, UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * wordsize; + + row->GetCFAValue().SetIsRegisterPlusOffset (arm_r7 , (2 * wordsize) + stack_adjust); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (arm_r7, (wordsize * -2) - stack_adjust, true); + row->SetRegisterLocationToAtCFAPlusOffset (arm_pc, (wordsize * -1) - stack_adjust, true); + row->SetRegisterLocationToIsCFAPlusOffset (arm_sp, 0, true); + + int cfa_offset = -stack_adjust - (2 * wordsize); + + uint32_t saved_register_bits = function_info.encoding & 0xff; + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r6, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r5, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r4, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r12, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r11, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r10, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r9, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) + { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset (arm_r8, cfa_offset, true); + } + + + if (mode == UNWIND_ARM_MODE_FRAME_D) + { + uint32_t d_reg_bits = EXTRACT_BITS (function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); + switch (d_reg_bits) + { + case 0: + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); + break; + case 1: + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); + break; + case 2: + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); + break; + case 3: + // vpush {d14} + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); + break; + case 4: + // vpush {d14} + // vpush {d12} + // sp = (sp - 24) & (-16); + // vst {d8, d9, d10} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); + + // FIXME we don't have a way to represent reg saves at an specific alignment short of + // coming up with some DWARF location description. + + break; + case 5: + // vpush {d14} + // sp = (sp - 40) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12} + + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); + + // FIXME we don't have a way to represent reg saves at an specific alignment short of + // coming up with some DWARF location description. + + break; + case 6: + // sp = (sp - 56) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14} + + // FIXME we don't have a way to represent reg saves at an specific alignment short of + // coming up with some DWARF location description. + + break; + case 7: + // sp = (sp - 64) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14, d15} + + // FIXME we don't have a way to represent reg saves at an specific alignment short of + // coming up with some DWARF location description. + + break; + } + } + + unwind_plan.AppendRow (row); + return true; +} + + diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp index 50eda8806375..259a450b7165 100644 --- a/source/Symbol/CompileUnit.cpp +++ b/source/Symbol/CompileUnit.cpp @@ -17,36 +17,40 @@ using namespace lldb; using namespace lldb_private; -CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) : - ModuleChild(module_sp), - FileSpec (pathname, false), - UserID(cu_sym_id), - m_user_data (user_data), - m_language (language), - m_flags (0), - m_functions (), - m_support_files (), - m_line_table_ap (), - m_variables(), - m_is_optimized (is_optimized) +CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, + const lldb::user_id_t cu_sym_id, lldb::LanguageType language, + lldb_private::LazyBool is_optimized) + : ModuleChild(module_sp), + FileSpec(pathname, false), + UserID(cu_sym_id), + m_user_data(user_data), + m_language(language), + m_flags(0), + m_functions(), + m_support_files(), + m_line_table_ap(), + m_variables(), + m_is_optimized(is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); assert(module_sp); } -CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) : - ModuleChild(module_sp), - FileSpec (fspec), - UserID(cu_sym_id), - m_user_data (user_data), - m_language (language), - m_flags (0), - m_functions (), - m_support_files (), - m_line_table_ap (), - m_variables(), - m_is_optimized (is_optimized) +CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, + const lldb::user_id_t cu_sym_id, lldb::LanguageType language, + lldb_private::LazyBool is_optimized) + : ModuleChild(module_sp), + FileSpec(fspec), + UserID(cu_sym_id), + m_user_data(user_data), + m_language(language), + m_flags(0), + m_functions(), + m_support_files(), + m_line_table_ap(), + m_variables(), + m_is_optimized(is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); @@ -468,6 +472,17 @@ CompileUnit::ResolveSymbolContext bool CompileUnit::GetIsOptimized () { + if (m_is_optimized == eLazyBoolCalculate) + { + m_is_optimized = eLazyBoolNo; + if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) + { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (symbol_vendor->ParseCompileUnitIsOptimized(sc)) + m_is_optimized = eLazyBoolYes; + } + } return m_is_optimized; } diff --git a/source/Symbol/CompilerDecl.cpp b/source/Symbol/CompilerDecl.cpp index 42e5fb081071..98eef060df0e 100644 --- a/source/Symbol/CompilerDecl.cpp +++ b/source/Symbol/CompilerDecl.cpp @@ -31,12 +31,6 @@ CompilerDecl::GetMangledName () const return m_type_system->DeclGetMangledName(m_opaque_decl); } -lldb::VariableSP -CompilerDecl::GetAsVariable () -{ - return m_type_system->DeclGetVariable(m_opaque_decl); -} - CompilerDeclContext CompilerDecl::GetDeclContext() const { diff --git a/source/Symbol/CompilerDeclContext.cpp b/source/Symbol/CompilerDeclContext.cpp index 8bee1b48753a..10a70d97f231 100644 --- a/source/Symbol/CompilerDeclContext.cpp +++ b/source/Symbol/CompilerDeclContext.cpp @@ -15,10 +15,11 @@ using namespace lldb_private; std::vector<CompilerDecl> -CompilerDeclContext::FindDeclByName (ConstString name) +CompilerDeclContext::FindDeclByName (ConstString name, const bool ignore_using_decls) { if (IsValid()) - return m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name); + return m_type_system->DeclContextFindDeclByName( + m_opaque_decl_ctx, name, ignore_using_decls); else return std::vector<CompilerDecl>(); } diff --git a/source/Symbol/CompilerType.cpp b/source/Symbol/CompilerType.cpp index 000a949626c5..2b06c93c3f0d 100644 --- a/source/Symbol/CompilerType.cpp +++ b/source/Symbol/CompilerType.cpp @@ -177,7 +177,14 @@ CompilerType::IsFunctionPointerType () const if (IsValid()) return m_type_system->IsFunctionPointerType(m_type); return false; +} +bool +CompilerType::IsBlockPointerType (CompilerType *function_pointer_type_ptr) const +{ + if (IsValid()) + return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); + return 0; } bool @@ -189,6 +196,20 @@ CompilerType::IsIntegerType (bool &is_signed) const } bool +CompilerType::IsEnumerationType (bool &is_signed) const +{ + if (IsValid()) + return m_type_system->IsEnumerationType(m_type, is_signed); + return false; +} + +bool +CompilerType::IsIntegerOrEnumerationType (bool &is_signed) const +{ + return IsIntegerType(is_signed) || IsEnumerationType(is_signed); +} + +bool CompilerType::IsPointerType (CompilerType *pointee_type) const { if (IsValid()) diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp index c357a5001690..6a4004bb7902 100644 --- a/source/Symbol/DWARFCallFrameInfo.cpp +++ b/source/Symbol/DWARFCallFrameInfo.cpp @@ -308,14 +308,22 @@ DWARFCallFrameInfo::GetFDEIndex () if (m_fde_index_initialized) return; - - Mutex::Locker locker(m_fde_index_mutex); - + + std::lock_guard<std::mutex> guard(m_fde_index_mutex); + if (m_fde_index_initialized) // if two threads hit the locker return; Timer scoped_timer (__PRETTY_FUNCTION__, "%s - %s", __PRETTY_FUNCTION__, m_objfile.GetFileSpec().GetFilename().AsCString("")); + bool clear_address_zeroth_bit = false; + ArchSpec arch; + if (m_objfile.GetArchitecture (arch)) + { + if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) + clear_address_zeroth_bit = true; + } + lldb::offset_t offset = 0; if (m_cfi_data_initialized == false) GetCFIData(); @@ -376,6 +384,9 @@ DWARFCallFrameInfo::GetFDEIndex () const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); + if (clear_address_zeroth_bit) + addr &= ~1ull; + lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); FDEEntryMap::Entry fde (addr, length, current_entry); m_fde_index.Append(fde); @@ -397,6 +408,7 @@ DWARFCallFrameInfo::GetFDEIndex () bool DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr, UnwindPlan& unwind_plan) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND); lldb::offset_t offset = dwarf_offset; lldb::offset_t current_entry = offset; @@ -637,6 +649,15 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr // the stack and place them in the current row. (This operation is // useful for compilers that move epilogue code into the body of a // function.) + if (stack.empty()) + { + if (log) + log->Printf( + "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 ", startaddr: %" PRIx64 + " encountered DW_CFA_restore_state but state stack is empty. Corrupt unwind info?", + __FUNCTION__, dwarf_offset, startaddr.GetFileAddress()); + break; + } lldb::addr_t offset = row->GetOffset (); row = stack.back (); stack.pop_back (); @@ -644,6 +665,17 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr break; } + case DW_CFA_GNU_args_size: // 0x2e + { + // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand + // representing an argument size. This instruction specifies the total of + // the size of the arguments which have been pushed onto the stack. + + // TODO: Figure out how we should handle this. + m_cfi_data.GetULEB128(&offset); + break; + } + case DW_CFA_val_offset : // 0x14 case DW_CFA_val_offset_sf : // 0x15 default: @@ -899,3 +931,17 @@ DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode, } return false; } + +void +DWARFCallFrameInfo::ForEachFDEEntries( + const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)>& callback) +{ + GetFDEIndex(); + + for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) + { + const FDEEntryMap::Entry& entry = m_fde_index.GetEntryRef(i); + if (!callback(entry.base, entry.size, entry.data)) + break; + } +} diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp index 4c96b1a2bb1b..2fa41b84cb25 100644 --- a/source/Symbol/FuncUnwinders.cpp +++ b/source/Symbol/FuncUnwinders.cpp @@ -22,6 +22,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnwindAssembly.h" +#include "lldb/Utility/RegisterNumber.h" using namespace lldb; using namespace lldb_private; @@ -30,27 +31,27 @@ using namespace lldb_private; /// constructor //------------------------------------------------ -FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) : - m_unwind_table (unwind_table), - m_range (range), - m_mutex (Mutex::eMutexTypeRecursive), - m_unwind_plan_assembly_sp (), - m_unwind_plan_eh_frame_sp (), - m_unwind_plan_eh_frame_augmented_sp (), - m_unwind_plan_compact_unwind (), - m_unwind_plan_arm_unwind_sp (), - m_unwind_plan_fast_sp (), - m_unwind_plan_arch_default_sp (), - m_unwind_plan_arch_default_at_func_entry_sp (), - m_tried_unwind_plan_assembly (false), - m_tried_unwind_plan_eh_frame (false), - m_tried_unwind_plan_eh_frame_augmented (false), - m_tried_unwind_plan_compact_unwind (false), - m_tried_unwind_plan_arm_unwind (false), - m_tried_unwind_fast (false), - m_tried_unwind_arch_default (false), - m_tried_unwind_arch_default_at_func_entry (false), - m_first_non_prologue_insn () +FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) + : m_unwind_table(unwind_table), + m_range(range), + m_mutex(), + m_unwind_plan_assembly_sp(), + m_unwind_plan_eh_frame_sp(), + m_unwind_plan_eh_frame_augmented_sp(), + m_unwind_plan_compact_unwind(), + m_unwind_plan_arm_unwind_sp(), + m_unwind_plan_fast_sp(), + m_unwind_plan_arch_default_sp(), + m_unwind_plan_arch_default_at_func_entry_sp(), + m_tried_unwind_plan_assembly(false), + m_tried_unwind_plan_eh_frame(false), + m_tried_unwind_plan_eh_frame_augmented(false), + m_tried_unwind_plan_compact_unwind(false), + m_tried_unwind_plan_arm_unwind(false), + m_tried_unwind_fast(false), + m_tried_unwind_arch_default(false), + m_tried_unwind_arch_default_at_func_entry(false), + m_first_non_prologue_insn() { } @@ -65,7 +66,7 @@ FuncUnwinders::~FuncUnwinders () UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset); if (unwind_plan_sp) @@ -90,7 +91,7 @@ FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset) if (m_tried_unwind_plan_compact_unwind) return UnwindPlanSP(); - Mutex::Locker lock (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_plan_compact_unwind = true; if (m_range.GetBaseAddress().IsValid()) { @@ -117,7 +118,7 @@ FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset) if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) return m_unwind_plan_eh_frame_sp; - Mutex::Locker lock (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_plan_eh_frame = true; if (m_range.GetBaseAddress().IsValid()) { @@ -141,7 +142,7 @@ FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset) if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) return m_unwind_plan_arm_unwind_sp; - Mutex::Locker lock (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_plan_arm_unwind = true; if (m_range.GetBaseAddress().IsValid()) { @@ -175,7 +176,7 @@ FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, in return m_unwind_plan_eh_frame_augmented_sp; } - Mutex::Locker lock (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_plan_eh_frame_augmented = true; UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan (target, current_offset); @@ -206,10 +207,14 @@ FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, in UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset) { - if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly) + if (m_unwind_plan_assembly_sp.get() + || m_tried_unwind_plan_assembly + || m_unwind_table.GetAllowAssemblyEmulationUnwindPlans () == false) + { return m_unwind_plan_assembly_sp; + } - Mutex::Locker lock (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_plan_assembly = true; UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); @@ -224,16 +229,81 @@ FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int curren return m_unwind_plan_assembly_sp; } +// This method compares the pc unwind rule in the first row of two UnwindPlans. +// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is sp"), +// then it will return LazyBoolTrue. +LazyBool +FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation (Thread& thread, const UnwindPlanSP &a, const UnwindPlanSP &b) +{ + LazyBool plans_are_identical = eLazyBoolCalculate; + + RegisterNumber pc_reg (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind (eRegisterKindLLDB); + + if (a.get() && b.get()) + { + UnwindPlan::RowSP a_first_row = a->GetRowAtIndex (0); + UnwindPlan::RowSP b_first_row = b->GetRowAtIndex (0); + + if (a_first_row.get() && b_first_row.get()) + { + UnwindPlan::Row::RegisterLocation a_pc_regloc; + UnwindPlan::Row::RegisterLocation b_pc_regloc; + + a_first_row->GetRegisterInfo (pc_reg_lldb_regnum, a_pc_regloc); + b_first_row->GetRegisterInfo (pc_reg_lldb_regnum, b_pc_regloc); + + plans_are_identical = eLazyBoolYes; + + if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) + { + plans_are_identical = eLazyBoolNo; + } + if (a_pc_regloc != b_pc_regloc) + { + plans_are_identical = eLazyBoolNo; + } + } + } + return plans_are_identical; +} UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) { - UnwindPlanSP non_call_site_unwindplan_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset); - if (non_call_site_unwindplan_sp.get() == nullptr) + UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan (target, current_offset); + UnwindPlanSP arch_default_at_entry_sp = GetUnwindPlanArchitectureDefaultAtFunctionEntry (thread); + UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault (thread); + UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan (target, thread, current_offset); + + // This point of this code is to detect when a function is using a non-standard ABI, and the eh_frame + // correctly describes that alternate ABI. This is addressing a specific situation on x86_64 linux + // systems where one function in a library pushes a value on the stack and jumps to another function. + // So using an assembly instruction based unwind will not work when you're in the second function - + // the stack has been modified in a non-ABI way. But we have eh_frame that correctly describes how to + // unwind from this location. So we're looking to see if the initial pc register save location from + // the eh_frame is different from the assembly unwind, the arch default unwind, and the arch default at + // initial function entry. + // + // We may have eh_frame that describes the entire function -- or we may have eh_frame that only describes + // the unwind after the prologue has executed -- so we need to check both the arch default (once the prologue + // has executed) and the arch default at initial function entry. And we may be running on a target where + // we have only some of the assembly/arch default unwind plans available. + + if (CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo + && CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo + && CompareUnwindPlansForIdenticalInitialPCLocation (thread, assembly_sp, arch_default_sp) == eLazyBoolNo) { - non_call_site_unwindplan_sp = GetAssemblyUnwindPlan (target, thread, current_offset); + return eh_frame_sp; } - return non_call_site_unwindplan_sp; + + UnwindPlanSP eh_frame_augmented_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset); + if (eh_frame_augmented_sp) + { + return eh_frame_augmented_sp; + } + + return assembly_sp; } UnwindPlanSP @@ -242,7 +312,7 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Target& target, Thread& thread) if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) return m_unwind_plan_fast_sp; - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_fast = true; UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); @@ -263,7 +333,7 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) return m_unwind_plan_arch_default_sp; - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_arch_default = true; Address current_pc; @@ -290,7 +360,7 @@ FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry) return m_unwind_plan_arch_default_at_func_entry_sp; - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_arch_default_at_func_entry = true; Address current_pc; @@ -318,7 +388,7 @@ FuncUnwinders::GetFirstNonPrologueInsn (Target& target) if (m_first_non_prologue_insn.IsValid()) return m_first_non_prologue_insn; - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); ExecutionContext exe_ctx (target.shared_from_this(), false); UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp index 33cc0c4e264c..598af270bddf 100644 --- a/source/Symbol/Function.cpp +++ b/source/Symbol/Function.cpp @@ -570,6 +570,8 @@ Function::GetPrologueByteSize () { m_flags.Set(flagsCalculatedPrologueSize); LineTable* line_table = m_comp_unit->GetLineTable (); + uint32_t prologue_end_line_idx = 0; + if (line_table) { LineEntry first_line_entry; @@ -578,9 +580,12 @@ Function::GetPrologueByteSize () { // Make sure the first line entry isn't already the end of the prologue addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; + addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS; + if (first_line_entry.is_prologue_end) { prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = first_line_entry_idx; } else { @@ -595,6 +600,7 @@ Function::GetPrologueByteSize () if (line_entry.is_prologue_end) { prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = idx; break; } } @@ -607,7 +613,7 @@ Function::GetPrologueByteSize () { // Check the first few instructions and look for one that has // a line number that's different than the first entry. - const uint32_t last_line_entry_idx = first_line_entry_idx + 6; + uint32_t last_line_entry_idx = first_line_entry_idx + 6; for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) { LineEntry line_entry; @@ -616,6 +622,7 @@ Function::GetPrologueByteSize () if (line_entry.line != first_line_entry.line) { prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = idx; break; } } @@ -624,10 +631,37 @@ Function::GetPrologueByteSize () if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); + prologue_end_line_idx = first_line_entry_idx; } } + const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize(); + + // Now calculate the offset to pass the subsequent line 0 entries. + uint32_t first_non_zero_line = prologue_end_line_idx; + while (1) + { + LineEntry line_entry; + if (line_table->GetLineEntryAtIndex(first_non_zero_line, line_entry)) + { + if (line_entry.line != 0) + break; + } + if (line_entry.range.GetBaseAddress().GetFileAddress() >= func_end_file_addr) + break; + + first_non_zero_line++; + } + + if (first_non_zero_line > prologue_end_line_idx) + { + LineEntry first_non_zero_entry; + if (line_table->GetLineEntryAtIndex(first_non_zero_line, first_non_zero_entry)) + { + line_zero_end_file_addr = first_non_zero_entry.range.GetBaseAddress().GetFileAddress(); + } + } // Verify that this prologue end file address in the function's // address range just to be sure @@ -635,10 +669,16 @@ Function::GetPrologueByteSize () { m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr; } + + if (prologue_end_file_addr < line_zero_end_file_addr && line_zero_end_file_addr < func_end_file_addr) + { + m_prologue_byte_size += line_zero_end_file_addr - prologue_end_file_addr; + } } } } - return m_prologue_byte_size; + + return m_prologue_byte_size; } lldb::LanguageType diff --git a/source/Symbol/GoASTContext.cpp b/source/Symbol/GoASTContext.cpp index 1993f2331058..faca778f069c 100644 --- a/source/Symbol/GoASTContext.cpp +++ b/source/Symbol/GoASTContext.cpp @@ -538,6 +538,12 @@ GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) } bool +GoASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + return false; +} + +bool GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) { is_signed = false; diff --git a/source/Symbol/JavaASTContext.cpp b/source/Symbol/JavaASTContext.cpp new file mode 100644 index 000000000000..45cda8d5112b --- /dev/null +++ b/source/Symbol/JavaASTContext.cpp @@ -0,0 +1,1561 @@ +//===-- JavaASTContext.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <sstream> + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/JavaASTContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/Target.h" + +#include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h" + +using namespace lldb; +using namespace lldb_private; + +namespace lldb_private +{ + +class JavaASTContext::JavaType +{ +public: + enum LLVMCastKind + { + eKindPrimitive, + eKindObject, + eKindReference, + eKindArray, + kNumKinds + }; + + JavaType(LLVMCastKind kind) : m_kind(kind) {} + + virtual ~JavaType() = default; + + virtual ConstString + GetName() = 0; + + virtual void + Dump(Stream *s) = 0; + + virtual bool + IsCompleteType() = 0; + + LLVMCastKind + getKind() const + { + return m_kind; + } + +private: + LLVMCastKind m_kind; +}; + +} // end of namespace lldb_private + +namespace +{ + +class JavaPrimitiveType : public JavaASTContext::JavaType +{ +public: + enum TypeKind + { + eTypeByte, + eTypeShort, + eTypeInt, + eTypeLong, + eTypeFloat, + eTypeDouble, + eTypeBoolean, + eTypeChar, + }; + + JavaPrimitiveType(TypeKind type_kind) : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {} + + ConstString + GetName() override + { + switch (m_type_kind) + { + case eTypeByte: + return ConstString("byte"); + case eTypeShort: + return ConstString("short"); + case eTypeInt: + return ConstString("int"); + case eTypeLong: + return ConstString("long"); + case eTypeFloat: + return ConstString("float"); + case eTypeDouble: + return ConstString("double"); + case eTypeBoolean: + return ConstString("boolean"); + case eTypeChar: + return ConstString("char"); + } + return ConstString(); + } + + TypeKind + GetTypeKind() + { + return m_type_kind; + } + + void + Dump(Stream *s) override + { + s->Printf("%s\n", GetName().GetCString()); + } + + bool + IsCompleteType() override + { + return true; + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindPrimitive; + } + +private: + const TypeKind m_type_kind; +}; + +class JavaDynamicType : public JavaASTContext::JavaType +{ +public: + JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) : + JavaType(kind), + m_linkage_name(linkage_name), + m_dynamic_type_id(nullptr) + { + } + + ConstString + GetLinkageName() const + { + return m_linkage_name; + } + + void + SetDynamicTypeId(const DWARFExpression &type_id) + { + m_dynamic_type_id = type_id; + } + + uint64_t + CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj) + { + if (!m_dynamic_type_id.IsValid()) + return UINT64_MAX; + + Value obj_load_address = value_obj.GetValue(); + obj_load_address.ResolveValue(exe_ctx); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address, + nullptr, result, nullptr)) + { + Error error; + + lldb::addr_t type_id_addr = result.GetScalar().UInt(); + lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); + if (process_sp) + return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(), + UINT64_MAX, error); + } + + return UINT64_MAX; + } + +public: + ConstString m_linkage_name; + DWARFExpression m_dynamic_type_id; +}; + +class JavaObjectType : public JavaDynamicType +{ +public: + struct Field + { + ConstString m_name; + CompilerType m_type; + uint32_t m_offset; + }; + + JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) + : JavaDynamicType(JavaType::eKindObject, linkage_name), + m_name(name), + m_byte_size(byte_size), + m_base_class_offset(0), + m_is_complete(false) + { + } + + ConstString + GetName() override + { + return m_name; + } + + uint32_t + GetByteSize() const + { + return m_byte_size; + } + + uint32_t + GetNumFields() + { + return m_fields.size(); + } + + void + Dump(Stream *s) override + { + if (m_base_class.IsValid()) + s->Printf("%s : %s\n", GetName().GetCString(), m_base_class.GetTypeName().GetCString()); + else + s->Printf("%s\n", GetName().GetCString()); + + s->IndentMore(); + for (const Field &f : m_fields) + s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(), f.m_name.GetCString()); + s->IndentLess(); + } + + Field * + GetFieldAtIndex(size_t idx) + { + if (idx < m_fields.size()) + return &m_fields[idx]; + return nullptr; + } + + CompilerType + GetBaseClass() + { + return m_base_class; + } + + uint32_t + GetBaseClassOffset() + { + return m_base_class_offset; + } + + uint32_t + GetNumInterfaces() + { + return m_interfaces.size(); + } + + CompilerType + GetInterfaceAtIndex(uint32_t idx) + { + if (m_interfaces.size() < idx) + return m_interfaces[idx]; + return CompilerType(); + } + + bool + IsCompleteType() override + { + return m_is_complete; + } + + void + SetCompleteType(bool is_complete) + { + m_is_complete = is_complete; + if (m_byte_size == 0) + { + // Try to calcualte the size of the object based on it's values + for (const Field &field : m_fields) + { + uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr); + if (field_end > m_byte_size) + m_byte_size = field_end; + } + } + } + + void + AddBaseClass(const CompilerType &type, uint32_t offset) + { + // TODO: Check if type is an interface and add it to the interface list in that case + m_base_class = type; + m_base_class_offset = offset; + } + + void + AddField(const ConstString &name, const CompilerType &type, uint32_t offset) + { + m_fields.push_back({name, type, offset}); + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindObject; + } + +private: + ConstString m_name; + uint32_t m_byte_size; + CompilerType m_base_class; + uint32_t m_base_class_offset; + std::vector<CompilerType> m_interfaces; + std::vector<Field> m_fields; + bool m_is_complete; +}; + +class JavaReferenceType : public JavaASTContext::JavaType +{ +public: + JavaReferenceType(CompilerType pointee_type) : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {} + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindReference; + } + + CompilerType + GetPointeeType() + { + return m_pointee_type; + } + + ConstString + GetName() override + { + ConstString pointee_type_name = static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType())->GetName(); + return ConstString(std::string(pointee_type_name.AsCString()) + "&"); + } + + void + Dump(Stream *s) override + { + static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s); + } + + bool + IsCompleteType() override + { + return m_pointee_type.IsCompleteType(); + } + +private: + CompilerType m_pointee_type; +}; + +class JavaArrayType : public JavaDynamicType +{ +public: + JavaArrayType(const ConstString& linkage_name, CompilerType element_type, const DWARFExpression &length_expression, + lldb::addr_t data_offset) + : JavaDynamicType(JavaType::eKindArray, linkage_name), + m_element_type(element_type), + m_length_expression(length_expression), + m_data_offset(data_offset) + { + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindArray; + } + + CompilerType + GetElementType() + { + return m_element_type; + } + + ConstString + GetName() override + { + ConstString element_type_name = static_cast<JavaType *>(GetElementType().GetOpaqueQualType())->GetName(); + return ConstString(std::string(element_type_name.AsCString()) + "[]"); + } + + void + Dump(Stream *s) override + { + s->Printf("%s\n", GetName().GetCString()); + } + + bool + IsCompleteType() override + { + return m_length_expression.IsValid(); + } + + uint32_t + GetNumElements(ValueObject *value_obj) + { + if (!m_length_expression.IsValid()) + return UINT32_MAX; + + Error error; + ValueObjectSP address_obj = value_obj->AddressOf(error); + if (error.Fail()) + return UINT32_MAX; + + Value obj_load_address = address_obj->GetValue(); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + ExecutionContextScope* exec_ctx_scope = value_obj->GetExecutionContextRef().Lock(true).GetBestExecutionContextScope(); + if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, nullptr, &obj_load_address, result, nullptr)) + return result.GetScalar().UInt(); + + return UINT32_MAX; + } + + uint64_t + GetElementOffset(size_t idx) + { + return m_data_offset + idx * m_element_type.GetByteSize(nullptr); + } + +private: + CompilerType m_element_type; + DWARFExpression m_length_expression; + lldb::addr_t m_data_offset; +}; + +} // end of anonymous namespace + +ConstString +JavaASTContext::GetPluginNameStatic() +{ + return ConstString("java"); +} + +ConstString +JavaASTContext::GetPluginName() +{ + return JavaASTContext::GetPluginNameStatic(); +} + +uint32_t +JavaASTContext::GetPluginVersion() +{ + return 1; +} + +lldb::TypeSystemSP +JavaASTContext::CreateInstance(lldb::LanguageType language, Module *module, Target *target) +{ + if (language == eLanguageTypeJava) + { + if (module) + return std::make_shared<JavaASTContext>(module->GetArchitecture()); + if (target) + return std::make_shared<JavaASTContext>(target->GetArchitecture()); + assert(false && "Either a module or a target has to be specifed to create a JavaASTContext"); + } + return lldb::TypeSystemSP(); +} + +void +JavaASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) +{ + static std::vector<lldb::LanguageType> s_languages_for_types({lldb::eLanguageTypeJava}); + static std::vector<lldb::LanguageType> s_languages_for_expressions({}); + + languages_for_types.insert(s_languages_for_types.begin(), s_languages_for_types.end()); + languages_for_expressions.insert(s_languages_for_expressions.begin(), s_languages_for_expressions.end()); +} + +void +JavaASTContext::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", CreateInstance, + EnumerateSupportedLanguages); +} + +void +JavaASTContext::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +JavaASTContext::JavaASTContext(const ArchSpec &arch) + : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) +{ +} + +JavaASTContext::~JavaASTContext() +{ +} + +uint32_t +JavaASTContext::GetPointerByteSize() +{ + return m_pointer_byte_size; +} + +DWARFASTParser * +JavaASTContext::GetDWARFParser() +{ + if (!m_dwarf_ast_parser_ap) + m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this)); + return m_dwarf_ast_parser_ap.get(); +} + +ConstString +JavaASTContext::DeclGetName(void *opaque_decl) +{ + return ConstString(); +} + +std::vector<CompilerDecl> +JavaASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) +{ + return std::vector<CompilerDecl>(); +} + +bool +JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) +{ + return false; +} + +ConstString +JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) +{ + return ConstString(); +} + +bool +JavaASTContext::DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, ConstString *language_object_name_ptr) +{ + return false; +} + +bool +JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, + bool *is_incomplete) +{ + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + + if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) + { + if (element_type) + *element_type = array->GetElementType(); + return true; + } + return false; +} + +bool +JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) +{ + return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); +} + +bool +JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar; + return false; +} + +bool +JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) +{ + is_complex = true; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + count = 1; + return true; + default: + break; + } + } + + count = 0; + return false; +} + +bool +JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) +{ + if (is_variadic_ptr) + *is_variadic_ptr = false; + return false; +} + +size_t +JavaASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) +{ + return CompilerType(); +} + +bool +JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) +{ + return false; +} + +bool +JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + is_signed = true; + return true; + default: + break; + } + } + + is_signed = false; + return false; +} + +bool +JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type, + bool check_cplusplus, bool check_objc) +{ + return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)); +} + +bool +JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) +{ + if (pointee_type) + pointee_type->Clear(); + return false; +} + +bool +JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) +{ + if (is_rvalue) + *is_rvalue = false; + + if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + { + if (pointee_type) + *pointee_type = ref->GetPointeeType(); + return true; + } + + if (pointee_type) + pointee_type->Clear(); + return false; +} + +bool +JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) +{ + return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) || + llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)); +} + +bool +JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) +{ + return false; // TODO: Implement if we introduce the void type +} + +bool +JavaASTContext::SupportsLanguage(lldb::LanguageType language) +{ + return language == lldb::eLanguageTypeJava; +} + +bool +JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) +{ + return true; +} + +bool +JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) +{ + return IsPointerType(type, pointee_type) || IsReferenceType(type, pointee_type); +} + +bool +JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) +{ + return false; // TODO: Implement it if we need it for string literals +} + +bool +JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) +{ + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + return false; +} + +bool +JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) +{ + return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); +} + +uint32_t +JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) +{ + return false; +} + +bool +JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) +{ + return static_cast<JavaType *>(type)->IsCompleteType(); +} + +bool +JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) +{ + return type != nullptr; +} + +bool +JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) +{ + if (IsCompleteType(type)) + return true; + + if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) + return GetCompleteType(array->GetElementType().GetOpaqueQualType()); + + if (JavaReferenceType *reference = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType()); + + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + { + SymbolFile *symbol_file = GetSymbolFile(); + if (!symbol_file) + return false; + + CompilerType object_type(this, type); + return symbol_file->CompleteType(object_type); + } + return false; +} + +ConstString +JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) +{ + if (type) + return static_cast<JavaType *>(type)->GetName(); + return ConstString(); +} + +uint32_t +JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) +{ + if (pointee_or_element_compiler_type) + pointee_or_element_compiler_type->Clear(); + if (!type) + return 0; + + if (IsReferenceType(type, pointee_or_element_compiler_type)) + return eTypeHasChildren | eTypeHasValue | eTypeIsReference; + if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr)) + return eTypeHasChildren | eTypeIsArray; + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return eTypeHasChildren | eTypeIsClass; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat | eTypeIsSigned; + case JavaPrimitiveType::eTypeBoolean: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + case JavaPrimitiveType::eTypeChar: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + } + } + return 0; +} + +lldb::TypeClass +JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) +{ + if (!type) + return eTypeClassInvalid; + if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) + return eTypeClassReference; + if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) + return eTypeClassArray; + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return eTypeClassClass; + if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type))) + return eTypeClassBuiltin; + assert(false && "Java type with unhandled type class"); + return eTypeClassInvalid; +} + +lldb::LanguageType +JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) +{ + return lldb::eLanguageTypeJava; +} + +CompilerType +JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) +{ + if (stride) + *stride = 0; + + CompilerType element_type; + if (IsArrayType(type, &element_type, nullptr, nullptr)) + return element_type; + return CompilerType(); +} + +CompilerType +JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) +{ + CompilerType pointee_type; + if (IsPointerType(type, &pointee_type)) + return pointee_type; + return CompilerType(); +} + +CompilerType +JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); // No pointer types in java +} + +CompilerType +JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) +{ + CompilerType pointee_type; + if (IsReferenceType(type, &pointee_type)) + return pointee_type; + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) +{ + return CompilerType(); +} + +size_t +JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +lldb::BasicType +JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + return eBasicTypeOther; + case JavaPrimitiveType::eTypeShort: + return eBasicTypeShort; + case JavaPrimitiveType::eTypeInt: + return eBasicTypeInt; + case JavaPrimitiveType::eTypeLong: + return eBasicTypeLong; + case JavaPrimitiveType::eTypeFloat: + return eBasicTypeFloat; + case JavaPrimitiveType::eTypeDouble: + return eBasicTypeDouble; + case JavaPrimitiveType::eTypeBoolean: + return eBasicTypeBool; + case JavaPrimitiveType::eTypeChar: + return eBasicTypeChar; + } + } + return eBasicTypeInvalid; +} + +uint64_t +JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + return 8; + case JavaPrimitiveType::eTypeShort: + return 16; + case JavaPrimitiveType::eTypeInt: + return 32; + case JavaPrimitiveType::eTypeLong: + return 64; + case JavaPrimitiveType::eTypeFloat: + return 32; + case JavaPrimitiveType::eTypeDouble: + return 64; + case JavaPrimitiveType::eTypeBoolean: + return 1; + case JavaPrimitiveType::eTypeChar: + return 16; + } + } + else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) + { + return 32; // References are always 4 byte long in java + } + else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) + { + return 64; + } + else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + return obj->GetByteSize() * 8; + } + return 0; +} + +lldb::Encoding +JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) +{ + count = 1; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eEncodingSint; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eEncodingIEEE754; + case JavaPrimitiveType::eTypeBoolean: + case JavaPrimitiveType::eTypeChar: + return eEncodingUint; + } + } + if (IsReferenceType(type)) + return eEncodingUint; + return eEncodingInvalid; +} + +lldb::Format +JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eFormatDecimal; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eFormatFloat; + case JavaPrimitiveType::eTypeBoolean: + return eFormatBoolean; + case JavaPrimitiveType::eTypeChar: + return eFormatUnicode16; + } + } + if (IsReferenceType(type)) + return eFormatHex; + return eFormatDefault; +} + +unsigned +JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +size_t +JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, + size_t dst_size) +{ + assert(false && "Not implemented"); + return 0; +} + +size_t +JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) +{ + return CompilerType(); +} + +uint32_t +JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + return obj->GetNumFields(); + } + return 0; +} + +CompilerType +JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, + uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) +{ + if (bit_offset_ptr) + *bit_offset_ptr = 0; + if (bitfield_bit_size_ptr) + *bitfield_bit_size_ptr = 0; + if (is_bitfield_ptr) + *is_bitfield_ptr = false; + + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + name = field->m_name.AsCString(); + if (bit_offset_ptr) + *bit_offset_ptr = field->m_offset * 8; + return field->m_type; + } + return CompilerType(); +} + +uint32_t +JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) +{ + GetCompleteType(type); + + if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes); + + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return GetNumFields(type) + GetNumDirectBaseClasses(type); + + return 0; +} + +uint32_t +JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0); + } + return 0; +} + +uint32_t +JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + return obj->GetNumInterfaces(); + } + return 0; +} + +CompilerType +JavaASTContext::GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + + if (CompilerType base_class = obj->GetBaseClass()) + { + if (idx == 0) + return base_class; + else + --idx; + } + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); +} + +CompilerType +JavaASTContext::GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); +} + +void +JavaASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, + bool verbose, uint32_t depth) +{ + assert(false && "Not implemented"); +} + +bool +JavaASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) +{ + if (IsScalarType(type)) + { + return data.Dump(s, data_offset, format, data_byte_size, + 1, // count + UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); + } + return false; +} + +void +JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) +{ + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); +} + +void +JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) +{ + static_cast<JavaType *>(type)->Dump(s); +} + +void +JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size) +{ + assert(false && "Not implemented"); +} + +int +JavaASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); +} + +size_t +JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +TypeMemberFunctionImpl +JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) +{ + return TypeMemberFunctionImpl(); +} + +CompilerType +JavaASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) +{ + child_name.clear(); + child_byte_size = 0; + child_byte_offset = 0; + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + child_is_deref_of_parent = false; + language_flags = 0; + + ExecutionContextScope *exec_ctx_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + + if (CompilerType base_class = obj->GetBaseClass()) + { + if (idx == 0) + { + JavaType *base_class_type = static_cast<JavaType *>(base_class.GetOpaqueQualType()); + child_name = base_class_type->GetName().GetCString(); + child_byte_size = base_class.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + child_byte_offset = obj->GetBaseClassOffset(); + child_is_base_class = true; + return base_class; + } + idx -= 1; + } + + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + + child_name = field->m_name.AsCString(); + child_byte_size = field->m_type.GetByteSize(exec_ctx_scope); + child_byte_offset = field->m_offset; + return field->m_type; + } + else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + { + CompilerType pointee_type = ref->GetPointeeType(); + + if (transparent_pointers) + return pointee_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, + child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, valobj, language_flags); + + if (idx != 0) + return CompilerType(); + + if (valobj && valobj->GetName()) + child_name = valobj->GetName().GetCString(); + child_is_deref_of_parent = true; + child_byte_offset = 0; + child_byte_size = pointee_type.GetByteSize(exec_ctx_scope); + return pointee_type; + } + return CompilerType(); +} + +uint32_t +JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) + { + if (base_class.GetTypeName() == ConstString(name)) + return 0; + index_offset = 1; + } + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) + { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) + return i + index_offset; + } + } + else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + { + return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes); + } + return UINT_MAX; +} + +size_t +JavaASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) +{ + child_indexes.clear(); + + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) + { + GetCompleteType(type); + + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) + { + if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name, omit_empty_base_classes, + child_indexes) != 0) + { + child_indexes.insert(child_indexes.begin(), 0); + return child_indexes.size(); + } + index_offset = 1; + } + + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) + { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) + { + child_indexes.push_back(i + index_offset); + return child_indexes.size(); + } + } + } + else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + { + return GetIndexOfChildMemberWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes, + child_indexes); + } + return 0; +} + +CompilerType +JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) +{ + return CreateReferenceType(CompilerType(this, type)); +} + +ConstString +JavaASTContext::DeclContextGetScopeQualifiedName(lldb::opaque_compiler_type_t opaque_decl_ctx) +{ + return GetTypeName(opaque_decl_ctx); +} + +static void +AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map, JavaPrimitiveType::TypeKind type_kind) +{ + JavaPrimitiveType *type = new JavaPrimitiveType(type_kind); + type_map.emplace(type->GetName(), std::unique_ptr<JavaASTContext::JavaType>(type)); +} + +CompilerType +JavaASTContext::CreateBaseType(const ConstString &name) +{ + if (m_base_type_map.empty()) + { + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar); + } + auto it = m_base_type_map.find(name); + if (it != m_base_type_map.end()) + return CompilerType(this, it->second.get()); + return CompilerType(); +} + +CompilerType +JavaASTContext::CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) +{ + auto it = m_object_type_map.find(name); + if (it == m_object_type_map.end()) + { + std::unique_ptr<JavaType> object_type(new JavaObjectType(name, linkage_name, byte_size)); + it = m_object_type_map.emplace(name, std::move(object_type)).first; + } + return CompilerType(this, it->second.get()); +} + +CompilerType +JavaASTContext::CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type, + const DWARFExpression &length_expression, const lldb::addr_t data_offset) +{ + ConstString name = element_type.GetTypeName(); + auto it = m_array_type_map.find(name); + if (it == m_array_type_map.end()) + { + std::unique_ptr<JavaType> array_type(new JavaArrayType(linkage_name, element_type, length_expression, + data_offset)); + it = m_array_type_map.emplace(name, std::move(array_type)).first; + } + return CompilerType(this, it->second.get()); +} + +CompilerType +JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) +{ + ConstString name = pointee_type.GetTypeName(); + auto it = m_reference_type_map.find(name); + if (it == m_reference_type_map.end()) + it = m_reference_type_map.emplace(name, std::unique_ptr<JavaType>(new JavaReferenceType(pointee_type))).first; + return CompilerType(this, it->second.get()); +} + +void +JavaASTContext::CompleteObjectType(const CompilerType &object_type) +{ + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::CompleteObjectType called with not a JavaObjectType"); + obj->SetCompleteType(true); +} + +void +JavaASTContext::AddBaseClassToObject(const CompilerType &object_type, const CompilerType &member_type, + uint32_t member_offset) +{ + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddBaseClass(member_type, member_offset); +} + +void +JavaASTContext::AddMemberToObject(const CompilerType &object_type, const ConstString &name, + const CompilerType &member_type, uint32_t member_offset) +{ + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddField(name, member_type, member_offset); +} + +void +JavaASTContext::SetDynamicTypeId(const CompilerType &type, const DWARFExpression &type_id) +{ + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType"); + obj->SetDynamicTypeId(type_id); +} + +uint64_t +JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, const CompilerType &type, ValueObject &in_value) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) + return obj->CalculateDynamicTypeId(exe_ctx, in_value); + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->CalculateDynamicTypeId(exe_ctx, in_value); + return UINT64_MAX; +} + +uint32_t +JavaASTContext::CalculateArraySize(const CompilerType &type, ValueObject &in_value) +{ + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->GetNumElements(&in_value); + return UINT32_MAX; +} + +uint64_t +JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, size_t index) +{ + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->GetElementOffset(index); + return UINT64_MAX; +} + +ConstString +JavaASTContext::GetLinkageName(const CompilerType &type) +{ + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) + return obj->GetLinkageName(); + return ConstString(); +} diff --git a/source/Symbol/LineEntry.cpp b/source/Symbol/LineEntry.cpp index 815101368bd1..9b3a043f6cae 100644 --- a/source/Symbol/LineEntry.cpp +++ b/source/Symbol/LineEntry.cpp @@ -43,6 +43,7 @@ LineEntry::LineEntry ) : range(section_sp, section_offset, byte_size), file(_file), + original_file(_file), line(_line), column(_column), is_start_of_statement(_is_start_of_statement), @@ -58,6 +59,7 @@ LineEntry::Clear() { range.Clear(); file.Clear(); + original_file.Clear(); line = LLDB_INVALID_LINE_NUMBER; column = 0; is_start_of_statement = 0; @@ -260,7 +262,7 @@ LineEntry::GetSameLineContiguousAddressRange () const if (next_line_sc.line_entry.IsValid() && next_line_sc.line_entry.range.GetByteSize() > 0 - && file == next_line_sc.line_entry.file) + && original_file == next_line_sc.line_entry.original_file) { // Include any line 0 entries - they indicate that this is compiler-generated code // that does not correspond to user source code. @@ -283,3 +285,15 @@ LineEntry::GetSameLineContiguousAddressRange () const } return complete_line_range; } + +void +LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) +{ + if (target_sp) + { + // Apply any file remappings to our file + FileSpec new_file_spec; + if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec)) + file = new_file_spec; + } +} diff --git a/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp index f9a42a7d14af..965dd689981b 100644 --- a/source/Symbol/LineTable.cpp +++ b/source/Symbol/LineTable.cpp @@ -299,6 +299,7 @@ LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) line_entry.range.SetByteSize(0); line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); + line_entry.original_file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); line_entry.line = entry.line; line_entry.column = entry.column; line_entry.is_start_of_statement = entry.is_start_of_statement; @@ -462,9 +463,9 @@ LineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::D for (size_t idx = 0; idx < count; ++idx) { ConvertEntryAtIndexToLineEntry (idx, line_entry); - line_entry.Dump (s, target, prev_file != line_entry.file, style, fallback_style, show_line_ranges); + line_entry.Dump (s, target, prev_file != line_entry.original_file, style, fallback_style, show_line_ranges); s->EOL(); - prev_file = line_entry.file; + prev_file = line_entry.original_file; } } diff --git a/source/Symbol/Makefile b/source/Symbol/Makefile deleted file mode 100644 index ae0cef0e242a..000000000000 --- a/source/Symbol/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Symbol/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../.. -LIBRARYNAME := lldbSymbol -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp index 99f9236a2cd9..62cde26c702f 100644 --- a/source/Symbol/ObjectFile.cpp +++ b/source/Symbol/ObjectFile.cpp @@ -241,8 +241,7 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, lldb::offset_t file_offset, lldb::offset_t length, const lldb::DataBufferSP& data_sp, - lldb::offset_t data_offset -) : + lldb::offset_t data_offset) : ModuleChild (module_sp), m_file (), // This file could be different from the original module's file m_type (eTypeInvalid), @@ -254,7 +253,8 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_process_wp(), m_memory_addr (LLDB_INVALID_ADDRESS), m_sections_ap(), - m_symtab_ap () + m_symtab_ap (), + m_synthetic_symbol_idx (0) { if (file_spec_ptr) m_file = *file_spec_ptr; @@ -286,7 +286,8 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, m_process_wp (process_sp), m_memory_addr (header_addr), m_sections_ap(), - m_symtab_ap () + m_symtab_ap (), + m_synthetic_symbol_idx (0) { if (header_data_sp) m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize()); @@ -384,6 +385,11 @@ ObjectFile::GetAddressClass (addr_t file_addr) case eSectionTypeELFDynamicLinkInfo: case eSectionTypeOther: return eAddressClassUnknown; + case eSectionTypeAbsoluteAddress: + // In case of absolute sections decide the address class based on the symbol + // type because the section type isn't specify if it is a code or a data + // section. + break; } } } @@ -545,8 +551,6 @@ ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data // The object file now contains a full mmap'ed copy of the object file data, so just use this return MemoryMapSectionData (section, section_data); } - section_data.Clear(); - return 0; } size_t @@ -596,7 +600,7 @@ ObjectFile::ClearSymtab () ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p", @@ -616,7 +620,7 @@ ObjectFile::GetSectionList(bool update_module_section_list) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); CreateSections(*module_sp->GetUnifiedSectionList()); } } @@ -653,3 +657,13 @@ ObjectFile::GetSymbolTypeFromName (llvm::StringRef name, } return symbol_type_hint; } + +ConstString +ObjectFile::GetNextSyntheticSymbolName() +{ + StreamString ss; + ConstString file_name = GetModule()->GetFileSpec().GetFilename(); + ss.Printf("___lldb_unnamed_symbol%u$$%s", ++m_synthetic_symbol_idx, file_name.GetCString()); + return ConstString(ss.GetData()); +} + diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp index 5884fcaa551d..1fa792c9729d 100644 --- a/source/Symbol/Symbol.cpp +++ b/source/Symbol/Symbol.cpp @@ -737,3 +737,10 @@ Symbol::GetDisassembly (const ExecutionContext &exe_ctx, } return false; } + +bool +Symbol::ContainsFileAddress (lldb::addr_t file_addr) const +{ + return m_addr_range.ContainsFileAddress(file_addr); +} + diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp index 54db5e090b80..1e55ce652e0d 100644 --- a/source/Symbol/SymbolContext.cpp +++ b/source/Symbol/SymbolContext.cpp @@ -365,6 +365,10 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t s->PutCString("kind = local, "); break; + case eValueTypeVariableThreadLocal: + s->PutCString("kind = thread local, "); + break; + default: break; } @@ -595,6 +599,7 @@ SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc, next_frame_pc = range.GetBaseAddress(); next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile(); + next_frame_sc.line_entry.original_file = curr_inlined_block_inlined_info->GetCallSite().GetFile(); next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine(); next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn(); return true; @@ -857,6 +862,73 @@ SymbolContext::GetFunctionStartLineEntry () const return LineEntry(); } +bool +SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range, Error &error) +{ + if (!line_entry.IsValid()) + { + error.SetErrorString("Symbol context has no line table."); + return false; + } + + range = line_entry.range; + if (line_entry.line > end_line) + { + error.SetErrorStringWithFormat("end line option %d must be after the current line: %d", + end_line, + line_entry.line); + return false; + } + + uint32_t line_index = 0; + bool found = false; + while (1) + { + LineEntry this_line; + line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, false, &this_line); + if (line_index == UINT32_MAX) + break; + if (LineEntry::Compare(this_line, line_entry) == 0) + { + found = true; + break; + } + } + + LineEntry end_entry; + if (!found) + { + // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit. + error.SetErrorString("Can't find the current line entry in the CompUnit - can't process " + "the end-line option"); + return false; + } + + line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false, &end_entry); + if (line_index == UINT32_MAX) + { + error.SetErrorStringWithFormat("could not find a line table entry corresponding " + "to end line number %d", + end_line); + return false; + } + + Block *func_block = GetFunctionBlock(); + if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX) + { + error.SetErrorStringWithFormat("end line number %d is not contained within the current function.", + end_line); + return false; + } + + lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() + - range.GetBaseAddress().GetFileAddress(); + range.SetByteSize(range_size); + return true; +} + + + //---------------------------------------------------------------------- // // SymbolContextSpecifier diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp index 82bbceb9610a..808dfd3d06d6 100644 --- a/source/Symbol/SymbolFile.cpp +++ b/source/Symbol/SymbolFile.cpp @@ -141,7 +141,7 @@ SymbolFile::GetMangledNamesForFunction(const std::string &scope_qualified_name, } uint32_t -SymbolFile::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, TypeMap& types) +SymbolFile::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap& types) { if (!append) types.Clear(); diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp index b9ec9a1c8a79..c569943b3463 100644 --- a/source/Symbol/SymbolVendor.cpp +++ b/source/Symbol/SymbolVendor.cpp @@ -85,7 +85,7 @@ SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (objfile_sp) { m_objfile_sp = objfile_sp; @@ -100,7 +100,7 @@ SymbolVendor::SetCompileUnitAtIndex (size_t idx, const CompUnitSP &cu_sp) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); const size_t num_compile_units = GetNumCompileUnits(); if (idx < num_compile_units) { @@ -129,7 +129,7 @@ SymbolVendor::GetNumCompileUnits() ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_compile_units.empty()) { if (m_sym_file_ap.get()) @@ -151,7 +151,7 @@ SymbolVendor::ParseCompileUnitLanguage (const SymbolContext& sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseCompileUnitLanguage(sc); } @@ -165,7 +165,7 @@ SymbolVendor::ParseCompileUnitFunctions (const SymbolContext &sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseCompileUnitFunctions(sc); } @@ -178,7 +178,7 @@ SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseCompileUnitLineTable(sc); } @@ -191,7 +191,7 @@ SymbolVendor::ParseCompileUnitDebugMacros (const SymbolContext &sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseCompileUnitDebugMacros(sc); } @@ -203,7 +203,7 @@ SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecLis ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files); } @@ -211,13 +211,25 @@ SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecLis } bool -SymbolVendor::ParseImportedModules (const SymbolContext &sc, - std::vector<ConstString> &imported_modules) +SymbolVendor::ParseCompileUnitIsOptimized(const SymbolContext &sc) { ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitIsOptimized(sc); + } + return false; +} + +bool +SymbolVendor::ParseImportedModules(const SymbolContext &sc, std::vector<ConstString> &imported_modules) +{ + ModuleSP module_sp(GetModule()); + if (module_sp) + { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseImportedModules(sc, imported_modules); } @@ -231,7 +243,7 @@ SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseFunctionBlocks(sc); } @@ -244,7 +256,7 @@ SymbolVendor::ParseTypes (const SymbolContext &sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseTypes(sc); } @@ -257,7 +269,7 @@ SymbolVendor::ParseVariablesForContext (const SymbolContext& sc) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ParseVariablesForContext(sc); } @@ -270,7 +282,7 @@ SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ResolveTypeUID(type_uid); } @@ -284,7 +296,7 @@ SymbolVendor::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_sco ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc); } @@ -297,7 +309,7 @@ SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bo ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list); } @@ -310,7 +322,7 @@ SymbolVendor::FindGlobalVariables (const ConstString &name, const CompilerDeclCo ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables); } @@ -323,7 +335,7 @@ SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append, ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, variables); } @@ -336,7 +348,7 @@ SymbolVendor::FindFunctions(const ConstString &name, const CompilerDeclContext * ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list); } @@ -349,7 +361,7 @@ SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->FindFunctions(regex, include_inlines, append, sc_list); } @@ -358,14 +370,14 @@ SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines size_t -SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, TypeMap& types) +SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap& types) { ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) - return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append, max_matches, types); + return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append, max_matches, searched_symbol_files, types); } if (!append) types.Clear(); @@ -378,7 +390,7 @@ SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool appen ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->FindTypes(context, append, types); } @@ -395,7 +407,7 @@ SymbolVendor::GetTypes (SymbolContextScope *sc_scope, ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) return m_sym_file_ap->GetTypes (sc_scope, type_mask, type_list); } @@ -409,7 +421,7 @@ SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, co ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); if (m_sym_file_ap.get()) namespace_decl_ctx = m_sym_file_ap->FindNamespace (sc, name, parent_decl_ctx); } @@ -422,7 +434,7 @@ SymbolVendor::Dump(Stream *s) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); bool show_context = false; @@ -467,7 +479,7 @@ SymbolVendor::GetCompileUnitAtIndex(size_t idx) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); const size_t num_compile_units = GetNumCompileUnits(); if (idx < num_compile_units) { diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp index 709d899075a4..b11b731014d8 100644 --- a/source/Symbol/Symtab.cpp +++ b/source/Symbol/Symtab.cpp @@ -25,16 +25,14 @@ using namespace lldb; using namespace lldb_private; - - -Symtab::Symtab(ObjectFile *objfile) : - m_objfile (objfile), - m_symbols (), - m_file_addr_to_index (), - m_name_to_index (), - m_mutex (Mutex::eMutexTypeRecursive), - m_file_addr_to_index_computed (false), - m_name_indexes_computed (false) +Symtab::Symtab(ObjectFile *objfile) + : m_objfile(objfile), + m_symbols(), + m_file_addr_to_index(), + m_name_to_index(), + m_mutex(), + m_file_addr_to_index_computed(false), + m_name_indexes_computed(false) { } @@ -56,7 +54,7 @@ Symtab::Resize(size_t count) // Clients should grab the mutex from this symbol table and lock it manually // when calling this function to avoid performance issues. m_symbols.resize (count); - return &m_symbols[0]; + return m_symbols.empty() ? nullptr : &m_symbols[0]; } uint32_t @@ -76,7 +74,7 @@ Symtab::AddSymbol(const Symbol& symbol) size_t Symtab::GetNumSymbols() const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); return m_symbols.size(); } @@ -90,9 +88,9 @@ Symtab::SectionFileAddressesChanged () void Symtab::Dump (Stream *s, Target *target, SortOrder sort_order) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); -// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); s->Indent(); const FileSpec &file_spec = m_objfile->GetFileSpec(); const char * object_name = nullptr; @@ -171,7 +169,7 @@ Symtab::Dump (Stream *s, Target *target, SortOrder sort_order) void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); const size_t num_symbols = GetNumSymbols(); //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); @@ -224,7 +222,7 @@ CompareSymbolID (const void *key, const void *p) Symbol * Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, &m_symbols[0], @@ -474,7 +472,7 @@ Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes, if (add_demangled || add_mangled) { Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); // Create the name index vector to be able to quickly search by name NameToIndexMap::Entry entry; @@ -506,7 +504,7 @@ Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes, uint32_t Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -524,7 +522,7 @@ Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_ uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -542,7 +540,7 @@ Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32 uint32_t Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -632,7 +630,7 @@ namespace { void Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__); // No need to sort if we have zero or one items... @@ -657,7 +655,7 @@ Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_du uint32_t Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); if (symbol_name) @@ -674,7 +672,7 @@ Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector uint32_t Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); if (symbol_name) @@ -700,7 +698,7 @@ Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbo uint32_t Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { @@ -719,7 +717,7 @@ Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, Symb uint32_t Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0) { @@ -739,7 +737,7 @@ Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, Symb uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); uint32_t sym_end = m_symbols.size(); @@ -763,7 +761,7 @@ Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); uint32_t sym_end = m_symbols.size(); @@ -790,7 +788,7 @@ Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp Symbol * Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); const size_t count = m_symbols.size(); for (size_t idx = start_idx; idx < count; ++idx) @@ -810,7 +808,7 @@ Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Vis size_t Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); // Initialize all of the lookup by name indexes before converting NAME @@ -830,7 +828,7 @@ Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbo size_t Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); // Initialize all of the lookup by name indexes before converting NAME @@ -850,7 +848,7 @@ Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbo size_t Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); return symbol_indexes.size(); @@ -859,7 +857,7 @@ Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, Symb Symbol * Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); if (!m_name_indexes_computed) @@ -894,33 +892,39 @@ typedef struct addr_t match_offset; } SymbolSearchInfo; -static int -SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) +// Add all the section file start address & size to the RangeVector, +// recusively adding any children sections. +static void +AddSectionsToRangeMap (SectionList *sectlist, RangeVector<addr_t, addr_t> §ion_ranges) { - const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]); - if (symbol == nullptr) - return -1; - - const addr_t info_file_addr = info->file_addr; - if (symbol->ValueIsAddress()) + const int num_sections = sectlist->GetNumSections (0); + for (int i = 0; i < num_sections; i++) { - const addr_t curr_file_addr = symbol->GetAddressRef().GetFileAddress(); - if (info_file_addr < curr_file_addr) - return -1; - - // Since we are finding the closest symbol that is greater than or equal - // to 'info->file_addr' we set the symbol here. This will get set - // multiple times, but after the search is done it will contain the best - // symbol match - info->match_symbol = const_cast<Symbol *>(symbol); - info->match_index_ptr = index_ptr; - info->match_offset = info_file_addr - curr_file_addr; - - if (info_file_addr > curr_file_addr) - return +1; - return 0; + SectionSP sect_sp = sectlist->GetSectionAtIndex (i); + if (sect_sp) + { + SectionList &child_sectlist = sect_sp->GetChildren(); + + // If this section has children, add the children to the RangeVector. + // Else add this section to the RangeVector. + if (child_sectlist.GetNumSections (0) > 0) + { + AddSectionsToRangeMap (&child_sectlist, section_ranges); + } + else + { + size_t size = sect_sp->GetByteSize(); + if (size > 0) + { + addr_t base_addr = sect_sp->GetFileAddress(); + RangeVector<addr_t, addr_t>::Entry entry; + entry.SetRangeBase (base_addr); + entry.SetByteSize (size); + section_ranges.Append (entry); + } + } + } } - return -1; } void @@ -948,35 +952,69 @@ Symtab::InitAddressIndexes() if (num_entries > 0) { m_file_addr_to_index.Sort(); - m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges(); - - // Now our last symbols might not have had sizes because there - // was no subsequent symbol to calculate the size from. If this is - // the case, then calculate the size by capping it at the end of the - // section in which the symbol resides - for (int i = num_entries - 1; i >= 0; --i) + + // Create a RangeVector with the start & size of all the sections for + // this objfile. We'll need to check this for any FileRangeToIndexMap + // entries with an uninitialized size, which could potentially be a + // large number so reconstituting the weak pointer is busywork when it + // is invariant information. + SectionList *sectlist = m_objfile->GetSectionList(); + RangeVector<addr_t, addr_t> section_ranges; + if (sectlist) + { + AddSectionsToRangeMap (sectlist, section_ranges); + section_ranges.Sort(); + } + + // Iterate through the FileRangeToIndexMap and fill in the size for any + // entries that didn't already have a size from the Symbol (e.g. if we + // have a plain linker symbol with an address only, instead of debug info + // where we get an address and a size and a type, etc.) + for (size_t i = 0; i < num_entries; i++) { - const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i); - // As we iterate backwards, as soon as we find a symbol with a valid - // byte size, we are done - if (entry.GetByteSize() > 0) - break; - - // Cap the size to the end of the section in which the symbol resides - SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase())); - if (section_sp) + FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.GetMutableEntryAtIndex (i); + if (entry->GetByteSize() == 0) { - const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize(); - const lldb::addr_t symbol_file_addr = entry.GetRangeBase(); - if (end_section_file_addr > symbol_file_addr) + addr_t curr_base_addr = entry->GetRangeBase(); + const RangeVector<addr_t, addr_t>::Entry *containing_section = + section_ranges.FindEntryThatContains (curr_base_addr); + + // Use the end of the section as the default max size of the symbol + addr_t sym_size = 0; + if (containing_section) { - Symbol &symbol = m_symbols[entry.data]; + sym_size = containing_section->GetByteSize() - + (entry->GetRangeBase() - containing_section->GetRangeBase()); + } + + for (size_t j = i; j < num_entries; j++) + { + FileRangeToIndexMap::Entry *next_entry = m_file_addr_to_index.GetMutableEntryAtIndex (j); + addr_t next_base_addr = next_entry->GetRangeBase(); + if (next_base_addr > curr_base_addr) + { + addr_t size_to_next_symbol = next_base_addr - curr_base_addr; - symbol.SetByteSize(end_section_file_addr - symbol_file_addr); - symbol.SetSizeIsSynthesized(true); + // Take the difference between this symbol and the next one as its size, + // if it is less than the size of the section. + if (sym_size == 0 || size_to_next_symbol < sym_size) + { + sym_size = size_to_next_symbol; + } + break; + } + } + + if (sym_size > 0) + { + entry->SetByteSize (sym_size); + Symbol &symbol = m_symbols[entry->data]; + symbol.SetByteSize (sym_size); + symbol.SetSizeIsSynthesized (true); } } } + // Sort again in case the range size changes the ordering m_file_addr_to_index.Sort(); } @@ -986,7 +1024,7 @@ Symtab::InitAddressIndexes() void Symtab::CalculateSymbolSizes () { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); if (!m_symbols.empty()) { @@ -1018,40 +1056,18 @@ Symtab::CalculateSymbolSizes () } Symbol * -Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) +Symtab::FindSymbolAtFileAddress (addr_t file_addr) { - Mutex::Locker locker (m_mutex); - - - SymbolSearchInfo info = { this, file_addr, nullptr, nullptr, 0 }; - - ::bsearch (&info, - indexes, - num_indexes, - sizeof(uint32_t), - (ComparisonFunction)SymbolWithClosestFileAddress); + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); - if (info.match_symbol) + const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryStartsAt(file_addr); + if (entry) { - if (info.match_offset == 0) - { - // We found an exact match! - return info.match_symbol; - } - - const size_t symbol_byte_size = info.match_symbol->GetByteSize(); - - if (symbol_byte_size == 0) - { - // We weren't able to find the size of the symbol so lets just go - // with that match we found in our search... - return info.match_symbol; - } - - // We were able to figure out a symbol size so lets make sure our - // offset puts "file_addr" in the symbol's address range. - if (info.match_offset < symbol_byte_size) - return info.match_symbol; + Symbol* symbol = SymbolAtIndex(entry->data); + if (symbol->GetFileAddress() == file_addr) + return symbol; } return nullptr; } @@ -1059,21 +1075,25 @@ Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* index Symbol * Symtab::FindSymbolContainingFileAddress (addr_t file_addr) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); if (!m_file_addr_to_index_computed) InitAddressIndexes(); const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr); if (entry) - return SymbolAtIndex(entry->data); + { + Symbol* symbol = SymbolAtIndex(entry->data); + if (symbol->ContainsFileAddress(file_addr)) + return symbol; + } return nullptr; } void Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool(Symbol *)> const &callback) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); if (!m_file_addr_to_index_computed) InitAddressIndexes(); @@ -1085,8 +1105,12 @@ Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool( for (size_t i = 0; i < addr_match_count; ++i) { - if (!callback(SymbolAtIndex(all_addr_indexes[i]))) - break; + Symbol* symbol = SymbolAtIndex(all_addr_indexes[i]); + if (symbol->ContainsFileAddress(file_addr)) + { + if (!callback(symbol)) + break; + } } } @@ -1133,7 +1157,7 @@ Symtab::FindFunctionSymbols (const ConstString &name, unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); if (temp_symbol_indexes_size > 0) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { SymbolContext sym_ctx; diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 8061e016ca59..8b51d99ece38 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -559,8 +559,8 @@ Type::ResolveClangType (ResolveState compiler_type_resolve_state) break; case eEncodingIsTypedefUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().CreateTypedef(GetName().AsCString(), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); + m_compiler_type = encoding_type->GetForwardCompilerType ().CreateTypedef(m_name.AsCString("__lldb_invalid_typedef_name"), + GetSymbolFile()->GetDeclContextContainingUID(GetID())); m_name.Clear(); break; @@ -605,8 +605,8 @@ Type::ResolveClangType (ResolveState compiler_type_resolve_state) break; case eEncodingIsTypedefUID: - m_compiler_type = void_compiler_type.CreateTypedef(GetName().AsCString(), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); + m_compiler_type = void_compiler_type.CreateTypedef(m_name.AsCString("__lldb_invalid_typedef_name"), + GetSymbolFile()->GetDeclContextContainingUID(GetID())); break; case eEncodingIsPointerUID: diff --git a/source/Symbol/TypeSystem.cpp b/source/Symbol/TypeSystem.cpp index 5c2ab5cceab6..2cd82f221f91 100644 --- a/source/Symbol/TypeSystem.cpp +++ b/source/Symbol/TypeSystem.cpp @@ -153,7 +153,9 @@ TypeSystem::DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx) std::vector<CompilerDecl> -TypeSystem::DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) +TypeSystem::DeclContextFindDeclByName (void *opaque_decl_ctx, + ConstString name, + bool ignore_imported_decls) { return std::vector<CompilerDecl>(); } @@ -161,9 +163,7 @@ TypeSystem::DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) #pragma mark TypeSystemMap -TypeSystemMap::TypeSystemMap() : - m_mutex (), - m_map () +TypeSystemMap::TypeSystemMap() : m_mutex(), m_map(), m_clear_in_progress(false) { } @@ -174,15 +174,35 @@ TypeSystemMap::~TypeSystemMap() void TypeSystemMap::Clear () { - Mutex::Locker locker (m_mutex); - m_map.clear(); + collection map; + { + std::lock_guard<std::mutex> guard(m_mutex); + map = m_map; + m_clear_in_progress = true; + } + std::set<TypeSystem *> visited; + for (auto pair : map) + { + TypeSystem *type_system = pair.second.get(); + if (type_system && !visited.count(type_system)) + { + visited.insert(type_system); + type_system->Finalize(); + } + } + map.clear(); + { + std::lock_guard<std::mutex> guard(m_mutex); + m_map.clear(); + m_clear_in_progress = false; + } } void TypeSystemMap::ForEach (std::function <bool(TypeSystem *)> const &callback) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); // Use a std::set so we only call the callback once for each unique // TypeSystem instance std::set<TypeSystem *> visited; @@ -201,7 +221,7 @@ TypeSystemMap::ForEach (std::function <bool(TypeSystem *)> const &callback) TypeSystem * TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Module *module, bool can_create) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); collection::iterator pos = m_map.find(language); if (pos != m_map.end()) return pos->second.get(); @@ -212,7 +232,7 @@ TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Module *mo { // Add a new mapping for "language" to point to an already existing // TypeSystem that supports this language - m_map[language] = pair.second; + AddToMap(language, pair.second); return pair.second.get(); } } @@ -222,14 +242,14 @@ TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Module *mo // Cache even if we get a shared pointer that contains null type system back lldb::TypeSystemSP type_system_sp = TypeSystem::CreateInstance (language, module); - m_map[language] = type_system_sp; + AddToMap (language, type_system_sp); return type_system_sp.get(); } TypeSystem * TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Target *target, bool can_create) { - Mutex::Locker locker (m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); collection::iterator pos = m_map.find(language); if (pos != m_map.end()) return pos->second.get(); @@ -240,7 +260,8 @@ TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Target *ta { // Add a new mapping for "language" to point to an already existing // TypeSystem that supports this language - m_map[language] = pair.second; + + AddToMap(language, pair.second); return pair.second.get(); } } @@ -249,7 +270,17 @@ TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Target *ta return nullptr; // Cache even if we get a shared pointer that contains null type system back - lldb::TypeSystemSP type_system_sp = TypeSystem::CreateInstance (language, target); - m_map[language] = type_system_sp; + lldb::TypeSystemSP type_system_sp; + if (!m_clear_in_progress) + type_system_sp = TypeSystem::CreateInstance (language, target); + + AddToMap(language, type_system_sp); return type_system_sp.get(); } + +void +TypeSystemMap::AddToMap (lldb::LanguageType language, lldb::TypeSystemSP const &type_system_sp) +{ + if (!m_clear_in_progress) + m_map[language] = type_system_sp; +} diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp index 80c22c08ee4f..18f0cb7b9dbd 100644 --- a/source/Symbol/UnwindPlan.cpp +++ b/source/Symbol/UnwindPlan.cpp @@ -338,7 +338,7 @@ UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp) } void -UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp) +UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp, bool replace_existing) { collection::iterator it = m_row_list.begin(); while (it != m_row_list.end()) { @@ -349,6 +349,8 @@ UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp) } if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) m_row_list.insert(it, row_sp); + else if (replace_existing) + *it = row_sp; } UnwindPlan::RowSP @@ -383,16 +385,27 @@ UnwindPlan::IsValidRowIndex (uint32_t idx) const const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex (uint32_t idx) const { - // You must call IsValidRowIndex(idx) first before calling this!!! - assert (idx < m_row_list.size()); - return m_row_list[idx]; + if (idx < m_row_list.size()) + return m_row_list[idx]; + else + { + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf ("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index (number rows is %u)", idx, (uint32_t)m_row_list.size()); + return UnwindPlan::RowSP(); + } } const UnwindPlan::RowSP UnwindPlan::GetLastRow () const { - // You must call GetRowCount() first to make sure there is at least one row - assert (!m_row_list.empty()); + if (m_row_list.empty()) + { + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf ("UnwindPlan::GetLastRow() when rows are empty"); + return UnwindPlan::RowSP(); + } return m_row_list.back(); } diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp index ac7a9b0fda87..87c18d94b070 100644 --- a/source/Symbol/UnwindTable.cpp +++ b/source/Symbol/UnwindTable.cpp @@ -27,14 +27,14 @@ using namespace lldb; using namespace lldb_private; -UnwindTable::UnwindTable (ObjectFile& objfile) : - m_object_file (objfile), - m_unwinds (), - m_initialized (false), - m_mutex (), - m_eh_frame_up (), - m_compact_unwind_up (), - m_arm_unwind_up () +UnwindTable::UnwindTable(ObjectFile &objfile) + : m_object_file(objfile), + m_unwinds(), + m_initialized(false), + m_mutex(), + m_eh_frame_up(), + m_compact_unwind_up(), + m_arm_unwind_up() { } @@ -47,7 +47,7 @@ UnwindTable::Initialize () if (m_initialized) return; - Mutex::Locker locker(m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); if (m_initialized) // check again once we've acquired the lock return; @@ -90,7 +90,7 @@ UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolConte Initialize(); - Mutex::Locker locker(m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); // There is an UnwindTable per object file, so we can safely use file handles addr_t file_addr = addr.GetFileAddress(); @@ -152,7 +152,7 @@ UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, Sym void UnwindTable::Dump (Stream &s) { - Mutex::Locker locker(m_mutex); + std::lock_guard<std::mutex> guard(m_mutex); s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str()); const_iterator begin = m_unwinds.begin(); const_iterator end = m_unwinds.end(); @@ -189,3 +189,9 @@ UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch) { return m_object_file.GetArchitecture (arch); } + +bool +UnwindTable::GetAllowAssemblyEmulationUnwindPlans () +{ + return m_object_file.AllowAssemblyEmulationUnwindPlans (); +} diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp index 51d11b7ca8e9..dd27b1b5d802 100644 --- a/source/Symbol/Variable.cpp +++ b/source/Symbol/Variable.cpp @@ -43,6 +43,7 @@ Variable::Variable (lldb::user_id_t uid, const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, SymbolContextScope *context, + const RangeList& scope_range, Declaration* decl_ptr, const DWARFExpression& location, bool external, @@ -54,6 +55,7 @@ Variable::Variable (lldb::user_id_t uid, m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), + m_scope_range(scope_range), m_declaration(decl_ptr), m_location(location), m_external(external), @@ -155,8 +157,13 @@ Variable::Dump(Stream *s, bool show_context) const switch (m_scope) { case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break; - case eValueTypeVariableArgument: s->PutCString("parameter"); break; + case eValueTypeVariableArgument: + s->PutCString("parameter"); + break; case eValueTypeVariableLocal: s->PutCString("local"); break; + case eValueTypeVariableThreadLocal: + s->PutCString("thread local"); + break; default: *s << "??? (" << m_scope << ')'; } } @@ -242,17 +249,16 @@ CompilerDeclContext Variable::GetDeclContext () { Type *type = GetType(); - return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); + if (type) + return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); + return CompilerDeclContext(); } CompilerDecl Variable::GetDecl () { Type *type = GetType(); - CompilerDecl decl = type->GetSymbolFile()->GetDeclForUID(GetID()); - if (decl) - decl.GetTypeSystem()->DeclLinkToObject(decl.GetOpaqueDecl(), shared_from_this()); - return decl; + return type ? type->GetSymbolFile()->GetDeclForUID(GetID()) : CompilerDecl(); } void @@ -343,6 +349,7 @@ Variable::IsInScope (StackFrame *frame) case eValueTypeConstResult: case eValueTypeVariableGlobal: case eValueTypeVariableStatic: + case eValueTypeVariableThreadLocal: return true; case eValueTypeVariableArgument: @@ -356,14 +363,24 @@ Variable::IsInScope (StackFrame *frame) { SymbolContext variable_sc; CalculateSymbolContext (&variable_sc); + // Check for static or global variable defined at the compile unit // level that wasn't defined in a block if (variable_sc.block == nullptr) - return true; + return true; - if (variable_sc.block == deepest_frame_block) + // Check if the variable is valid in the current block + if (variable_sc.block != deepest_frame_block && + !variable_sc.block->Contains(deepest_frame_block)) + return false; + + // If no scope range is specified then it means that the scope is the same as the + // scope of the enclosing lexical block. + if (m_scope_range.IsEmpty()) return true; - return variable_sc.block->Contains (deepest_frame_block); + + addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress(); + return m_scope_range.FindEntryThatContains(file_address) != nullptr; } } break; @@ -816,6 +833,7 @@ PrivateAutoComplete (StackFrame *frame, word_complete); } } + break; default: break; } @@ -852,6 +870,7 @@ PrivateAutoComplete (StackFrame *frame, matches, word_complete); } + break; default: break; } |
