diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Symbol')
17 files changed, 2002 insertions, 204 deletions
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp index addff1ab3d5e..ad4337f5bd3e 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp @@ -11,6 +11,7 @@ // C Includes // C++ Includes +#include <mutex> #include <string> // Other libraries and framework includes @@ -62,6 +63,7 @@ #include "lldb/Core/Flags.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" @@ -79,13 +81,17 @@ using namespace lldb_private; using namespace llvm; using namespace clang; -typedef llvm::DenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap; +typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap; static ClangASTMap & GetASTMap() { - static ClangASTMap g_map; - return g_map; + static ClangASTMap *g_map_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins + }); + return *g_map_ptr; } @@ -303,7 +309,7 @@ ClangASTContext::~ClangASTContext() { if (m_ast_ap.get()) { - GetASTMap().erase(m_ast_ap.get()); + GetASTMap().Erase(m_ast_ap.get()); } m_builtins_ap.reset(); @@ -409,7 +415,7 @@ ClangASTContext::getASTContext() m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); - GetASTMap().insert(std::make_pair(m_ast_ap.get(), this)); + GetASTMap().Insert(m_ast_ap.get(), this); } return m_ast_ap.get(); } @@ -417,7 +423,7 @@ ClangASTContext::getASTContext() ClangASTContext* ClangASTContext::GetASTContext (clang::ASTContext* ast) { - ClangASTContext *clang_ast = GetASTMap().lookup(ast); + ClangASTContext *clang_ast = GetASTMap().Lookup(ast); return clang_ast; } @@ -883,6 +889,13 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name break; case DW_ATE_float: + if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) + return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); + if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) + return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr()); + if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) + return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr()); + // Fall back to not requring a name match if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) @@ -1119,6 +1132,16 @@ ClangASTContext::AreTypesSame (ClangASTType type1, return ast->hasSameType (type1_qual, type2_qual); } +ClangASTType +ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl) +{ + if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) + return GetTypeForDecl(interface_decl); + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) + return GetTypeForDecl(tag_decl); + return ClangASTType(); +} + ClangASTType ClangASTContext::GetTypeForDecl (TagDecl *decl) @@ -1126,7 +1149,7 @@ ClangASTContext::GetTypeForDecl (TagDecl *decl) // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... - ASTContext *ast = m_ast_ap.get(); + ASTContext *ast = &decl->getASTContext(); if (ast) return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr()); return ClangASTType(); @@ -1138,7 +1161,7 @@ ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl) // No need to call the getASTContext() accessor (which can create the AST // if it isn't created yet, because we can't have created a decl in this // AST if our AST didn't already exist... - ASTContext *ast = m_ast_ap.get(); + ASTContext *ast = &decl->getASTContext(); if (ast) return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr()); return ClangASTType(); @@ -1733,7 +1756,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, DeclarationName (&ast->Idents.get(name)), function_clang_type.GetQualType(), nullptr, - (FunctionDecl::StorageClass)storage, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); @@ -1747,7 +1770,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, DeclarationName (), function_clang_type.GetQualType(), nullptr, - (FunctionDecl::StorageClass)storage, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, isConstexprSpecified); @@ -1801,7 +1824,7 @@ ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTTyp name && name[0] ? &ast->Idents.get(name) : nullptr, param_type.GetQualType(), nullptr, - (VarDecl::StorageClass)storage, + (clang::StorageClass)storage, nullptr); } @@ -1851,7 +1874,23 @@ ClangASTContext::CreateArrayType (const ClangASTType &element_type, return ClangASTType(); } - +ClangASTType +ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, + const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields, + bool packed) +{ + ClangASTType type; + if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + return type; + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); + type.StartTagDeclarationDefinition(); + for (const auto& field : type_fields) + type.AddFieldToRecordType(field.first, field.second, lldb::eAccessPublic, 0); + if (packed) + type.SetIsPacked(); + type.CompleteTagDeclarationDefinition(); + return type; +} #pragma mark Enumeration Types @@ -2069,7 +2108,7 @@ ClangASTContext::SetMetadata (clang::ASTContext *ast, ClangASTMetadata &metadata) { ClangExternalASTSourceCommon *external_source = - static_cast<ClangExternalASTSourceCommon*>(ast->getExternalSource()); + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); if (external_source) external_source->SetMetadata(object, metadata); @@ -2080,7 +2119,7 @@ ClangASTContext::GetMetadata (clang::ASTContext *ast, const void *object) { ClangExternalASTSourceCommon *external_source = - static_cast<ClangExternalASTSourceCommon*>(ast->getExternalSource()); + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); if (external_source && external_source->HasMetadata(object)) return external_source->GetMetadata(object); diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp index 6579afb2f748..a925f808f858 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp @@ -86,7 +86,7 @@ ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast, if (log) { - lldb::user_id_t user_id; + lldb::user_id_t user_id = LLDB_INVALID_UID; ClangASTMetadata *metadata = GetDeclMetadata(decl); if (metadata) user_id = metadata->GetUserID(); diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp index f11daafe3d23..34976b1cee2e 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp @@ -47,6 +47,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include <iterator> #include <mutex> using namespace lldb; @@ -515,7 +516,7 @@ ClangASTType::GetNumberOfFunctionArguments () const } ClangASTType -ClangASTType::GetFunctionArgumentAtIndex (const size_t index) +ClangASTType::GetFunctionArgumentAtIndex (const size_t index) const { if (IsValid()) { @@ -1713,7 +1714,7 @@ ClangASTType::GetFunctionArgumentCount () const } ClangASTType -ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx) +ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx) const { if (IsValid()) { @@ -1741,6 +1742,199 @@ ClangASTType::GetFunctionReturnType () const return ClangASTType(); } +size_t +ClangASTType::GetNumMemberFunctions () const +{ + size_t num_functions = 0; + if (IsValid()) + { + clang::QualType qual_type(GetCanonicalQualType()); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (m_ast, qual_type)) + { + const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end()); + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType()) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType()) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); + } + } + break; + + + case clang::Type::Typedef: + return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); + + case clang::Type::Elaborated: + return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumMemberFunctions(); + + case clang::Type::Paren: + return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumMemberFunctions(); + + default: + break; + } + } + return num_functions; +} + +TypeMemberFunctionImpl +ClangASTType::GetMemberFunctionAtIndex (size_t idx) +{ + std::string name(""); + MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); + ClangASTType type{}; + clang::ObjCMethodDecl *method_decl(nullptr); + if (IsValid()) + { + clang::QualType qual_type(GetCanonicalQualType()); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType (m_ast, qual_type)) + { + const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + { + auto method_iter = cxx_record_decl->method_begin(); + auto method_end = cxx_record_decl->method_end(); + if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + auto method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + if (!method_decl->getName().empty()) + name.assign(method_decl->getName().data()); + else + name.clear(); + if (method_decl->isStatic()) + kind = lldb::eMemberFunctionKindStaticMethod; + else if (llvm::isa<clang::CXXConstructorDecl>(method_decl)) + kind = lldb::eMemberFunctionKindConstructor; + else if (llvm::isa<clang::CXXDestructorDecl>(method_decl)) + kind = lldb::eMemberFunctionKindDestructor; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + type = ClangASTType(m_ast,method_decl->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType()) + { + const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType()) + { + const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + if (objc_class_type) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if (class_interface_decl) + { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) + { + std::advance(method_iter, idx); + method_decl = method_iter->getCanonicalDecl(); + if (method_decl) + { + name = method_decl->getSelector().getAsString(); + if (method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::Typedef: + return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMemberFunctionAtIndex(idx); + + case clang::Type::Elaborated: + return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetMemberFunctionAtIndex(idx); + + case clang::Type::Paren: + return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetMemberFunctionAtIndex(idx); + + default: + break; + } + } + + if (kind == eMemberFunctionKindUnknown) + return TypeMemberFunctionImpl(); + if (method_decl) + return TypeMemberFunctionImpl(method_decl, name, kind); + if (type) + return TypeMemberFunctionImpl(type, name, kind); + + return TypeMemberFunctionImpl(); +} ClangASTType ClangASTType::GetLValueReferenceType () const @@ -3448,7 +3642,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, case clang::Type::IncompleteArray: if (ignore_array_bounds || idx_is_valid) { - const clang::ArrayType *array = llvm::cast<clang::ArrayType>(parent_qual_type.getTypePtr()); + const clang::ArrayType *array = GetQualType()->getAsArrayTypeUnsafe(); if (array) { ClangASTType element_type (m_ast, array->getElementType()); @@ -4752,6 +4946,17 @@ ClangASTType::BuildIndirectFields () } } +void +ClangASTType::SetIsPacked () +{ + clang::RecordDecl *record_decl = GetAsRecordDecl(); + + if (!record_decl) + return; + + record_decl->addAttr(clang::PackedAttr::CreateImplicit(*m_ast)); +} + clang::VarDecl * ClangASTType::AddVariableToRecordType (const char *name, const ClangASTType &var_type, @@ -5176,9 +5381,12 @@ ClangASTType::AddObjCClassProperty (const char *property_name, if (getter && metadata) ClangASTContext::SetMetadata(m_ast, getter, *metadata); - getter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>()); + if (getter) + { + getter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>()); - class_interface_decl->addDecl(getter); + class_interface_decl->addDecl(getter); + } } if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) @@ -5223,9 +5431,12 @@ ClangASTType::AddObjCClassProperty (const char *property_name, clang::SC_Auto, nullptr)); - setter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>()); + if (setter) + { + setter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>()); - class_interface_decl->addDecl(setter); + class_interface_decl->addDecl(setter); + } } return true; diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp index 650d252a8fc3..79cc9a91355a 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp @@ -9,30 +9,52 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Core/Stream.h" +#include "lldb/Host/Mutex.h" using namespace lldb_private; -#define ClangExternalASTSourceCommon_MAGIC (0x00112233aabbccddull) - uint64_t g_TotalSizeOfMetadata = 0; -ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() +typedef llvm::DenseMap<clang::ExternalASTSource *, ClangExternalASTSourceCommon *> ASTSourceMap; + +static ASTSourceMap &GetSourceMap() +{ + static ASTSourceMap s_source_map; + return s_source_map; +} + +ClangExternalASTSourceCommon * +ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) { - m_magic = ClangExternalASTSourceCommon_MAGIC; + ASTSourceMap &source_map = GetSourceMap(); + + ASTSourceMap::iterator iter = source_map.find(source); + if (iter != source_map.end()) + { + return iter->second; + } + else + { + return nullptr; + } +} + +ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() +{ g_TotalSizeOfMetadata += m_metadata.size(); + GetSourceMap()[this] = this; } ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() { + GetSourceMap().erase(this); g_TotalSizeOfMetadata -= m_metadata.size(); } ClangASTMetadata * ClangExternalASTSourceCommon::GetMetadata (const void *object) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - if (HasMetadata (object)) return &m_metadata[object]; else @@ -42,8 +64,6 @@ ClangExternalASTSourceCommon::GetMetadata (const void *object) void ClangExternalASTSourceCommon::SetMetadata (const void *object, ClangASTMetadata &metadata) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - uint64_t orig_size = m_metadata.size(); m_metadata[object] = metadata; uint64_t new_size = m_metadata.size(); @@ -53,8 +73,6 @@ ClangExternalASTSourceCommon::SetMetadata (const void *object, ClangASTMetadata bool ClangExternalASTSourceCommon::HasMetadata (const void *object) { - assert (m_magic == ClangExternalASTSourceCommon_MAGIC); - return m_metadata.find(object) != m_metadata.end(); } diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp new file mode 100644 index 000000000000..8c6a2e7214c3 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp @@ -0,0 +1,1215 @@ +//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +#include <algorithm> + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/CompactUnwindInfo.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "llvm/Support/MathExtras.h" + +using namespace lldb; +using namespace lldb_private; + + +namespace lldb_private { + + // Constants from <mach-o/compact_unwind_encoding.h> + + enum { + UNWIND_IS_NOT_FUNCTION_START = 0x80000000, + UNWIND_HAS_LSDA = 0x40000000, + UNWIND_PERSONALITY_MASK = 0x30000000, + }; + + enum { + UNWIND_X86_MODE_MASK = 0x0F000000, + UNWIND_X86_MODE_EBP_FRAME = 0x01000000, + UNWIND_X86_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_MODE_STACK_IND = 0x03000000, + UNWIND_X86_MODE_DWARF = 0x04000000, + + UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + + enum { + UNWIND_X86_REG_NONE = 0, + UNWIND_X86_REG_EBX = 1, + UNWIND_X86_REG_ECX = 2, + UNWIND_X86_REG_EDX = 3, + UNWIND_X86_REG_EDI = 4, + UNWIND_X86_REG_ESI = 5, + UNWIND_X86_REG_EBP = 6, + }; + enum { + UNWIND_X86_64_MODE_MASK = 0x0F000000, + UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, + UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_64_MODE_STACK_IND = 0x03000000, + UNWIND_X86_64_MODE_DWARF = 0x04000000, + + UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + }; + + enum { + UNWIND_X86_64_REG_NONE = 0, + UNWIND_X86_64_REG_RBX = 1, + UNWIND_X86_64_REG_R12 = 2, + UNWIND_X86_64_REG_R13 = 3, + UNWIND_X86_64_REG_R14 = 4, + UNWIND_X86_64_REG_R15 = 5, + UNWIND_X86_64_REG_RBP = 6, + }; +}; + + +#ifndef UNWIND_SECOND_LEVEL_REGULAR +#define UNWIND_SECOND_LEVEL_REGULAR 2 +#endif + +#ifndef UNWIND_SECOND_LEVEL_COMPRESSED +#define UNWIND_SECOND_LEVEL_COMPRESSED 3 +#endif + +#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET +#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) +#endif + +#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX +#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) +#endif + +#define EXTRACT_BITS(value, mask) \ + ( (value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ + (((1 << llvm::CountPopulation_32(static_cast<uint32_t>(mask))))-1) ) + + + +//---------------------- +// 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 () +{ + +} + +//---------------------- +// destructor +//---------------------- + +CompactUnwindInfo::~CompactUnwindInfo() +{ +} + +bool +CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan) +{ + if (!IsValid (target.GetProcessSP())) + { + return false; + } + FunctionInfo function_info; + if (GetCompactUnwindInfoForFunction (target, addr, function_info)) + { + // shortcut return for functions that have no compact unwind + if (function_info.encoding == 0) + return false; + + ArchSpec arch; + if (m_objfile.GetArchitecture (arch)) + { + + Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) + { + StreamString strm; + 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()); + } + + if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + 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, + sl); + unwind_plan.SetPlanValidAddressRange (func_range); + } + } + + if (arch.GetTriple().getArch() == llvm::Triple::x86_64) + { + return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr); + } + if (arch.GetTriple().getArch() == llvm::Triple::x86) + { + return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr); + } + } + } + return false; +} + +bool +CompactUnwindInfo::IsValid (const ProcessSP &process_sp) +{ + if (m_section_sp.get() == nullptr) + return false; + + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return true; + + ScanIndex (process_sp); + + return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; +} + +void +CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) +{ + Mutex::Locker locker(m_mutex); + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return; + + // We can't read the index for some reason. + if (m_indexes_computed == eLazyBoolNo) + { + return; + } + + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes"); + + if (m_unwindinfo_data_computed == false) + { + if (m_section_sp->IsEncrypted()) + { + // Can't get section contents of a protected/encrypted section until we have a live + // process and can read them out of memory. + if (process_sp.get() == nullptr) + return; + 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->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success()) + { + m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder()); + m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0); + } + } + else + { + m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data); + } + if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) + return; + m_unwindinfo_data_computed = true; + } + + if (m_unwindinfo_data.GetByteSize() > 0) + { + offset_t offset = 0; + + // struct unwind_info_section_header + // { + // uint32_t version; // UNWIND_SECTION_VERSION + // uint32_t commonEncodingsArraySectionOffset; + // uint32_t commonEncodingsArrayCount; + // uint32_t personalityArraySectionOffset; + // 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); + m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); + uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); + + uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); + + if (m_unwind_header.version != 1) + { + m_indexes_computed = eLazyBoolNo; + } + + // 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 + // { + // uint32_t functionOffset; + // uint32_t secondLevelPagesSectionOffset; + // uint32_t lsdaIndexArraySectionOffset; + // }; + + offset = indexSectionOffset; + for (uint32_t idx = 0; idx < indexCount; idx++) + { + uint32_t function_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset + uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset + + if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize()) + { + m_indexes_computed = eLazyBoolNo; + } + + UnwindIndex this_index; + this_index.function_offset = function_offset; // + this_index.second_level = second_level_offset; + this_index.lsda_array_start = lsda_offset; + + if (m_indexes.size() > 0) + { + m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; + } + + if (second_level_offset == 0) + { + this_index.sentinal_entry = true; + } + + m_indexes.push_back (this_index); + } + m_indexes_computed = eLazyBoolYes; + } + else + { + m_indexes_computed = eLazyBoolNo; + } +} + +uint32_t +CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset) +{ + // struct unwind_info_section_header_lsda_index_entry + // { + // uint32_t functionOffset; + // uint32_t lsdaOffset; + // }; + + offset_t first_entry = lsda_offset; + uint32_t low = 0; + uint32_t high = lsda_count; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset + if (mid_func_offset == function_offset) + { + return mid_lsda_offset; + } + if (mid_func_offset < function_offset) + { + low = mid + 1; + } + else + { + high = mid; + } + } + return 0; +} + +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 + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; + + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t next_func_offset = 0; + if (mid < last) + { + offset = first_entry + ((mid + 1) * 8); + next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset + } + if (mid_func_offset <= function_offset) + { + if (mid == last || (next_func_offset > function_offset)) + { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return first_entry + (mid * 8); + } + else + { + low = mid + 1; + } + } + else + { + high = mid; + } + } + return LLDB_INVALID_OFFSET; +} + +uint32_t +CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) +{ + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) + { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 4); + uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry + uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); + mid_func_offset += function_offset_base; + uint32_t next_func_offset = 0; + if (mid < last) + { + offset = first_entry + ((mid + 1) * 4); + uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry + next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry); + next_func_offset += function_offset_base; + } + if (mid_func_offset <= function_offset_to_find) + { + if (mid == last || (next_func_offset > function_offset_to_find)) + { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); + } + else + { + low = mid + 1; + } + } + else + { + high = mid; + } + } + + return UINT32_MAX; +} + +bool +CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info) +{ + unwind_info.encoding = 0; + unwind_info.lsda_address.Clear(); + unwind_info.personality_ptr_address.Clear(); + + if (!IsValid (target.GetProcessSP())) + return false; + + addr_t text_section_file_address = LLDB_INVALID_ADDRESS; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true); + if (text_sect.get()) + { + text_section_file_address = text_sect->GetFileAddress(); + } + } + if (text_section_file_address == LLDB_INVALID_ADDRESS) + 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()) + { + return false; + } + + if (it->function_offset != key.function_offset) + { + if (it != m_indexes.begin()) + --it; + } + + if (it->sentinal_entry == true) + { + return false; + } + + auto next_it = it + 1; + if (next_it != m_indexes.begin()) + { + // 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; + } + + offset_t second_page_offset = it->second_level; + offset_t lsda_array_start = it->lsda_array_start; + offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; + + offset_t offset = second_page_offset; + uint32_t kind = m_unwindinfo_data.GetU32(&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED + + if (kind == UNWIND_SECOND_LEVEL_REGULAR) + { + // struct unwind_info_regular_second_level_page_header + // { + // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR + // uint16_t entryPageOffset; + // uint16_t entryCount; + + // typedef uint32_t compact_unwind_encoding_t; + // struct unwind_info_regular_second_level_entry + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; + + uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount + + offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); + if (entry_offset == LLDB_INVALID_OFFSET) + { + return false; + } + entry_offset += 4; // skip over functionOffset + unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding + if (unwind_info.encoding & UNWIND_HAS_LSDA) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) + { + uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) + { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) + { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); + } + } + } + } + return true; + } + else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) + { + // struct unwind_info_compressed_second_level_page_header + // { + // 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 + // // must be added to the index's functionOffset value. + // uint16_t entryCount; + // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings + // uint16_t encodingsCount; + + uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount + uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset + uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset); // encodingsCount + + uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); + if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count) + { + return false; + } + uint32_t encoding = 0; + if (encoding_index < m_unwind_header.common_encodings_array_count) + { + 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 + { + 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)); + encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the page-specific encoding array + } + if (encoding == 0) + return false; + + unwind_info.encoding = encoding; + if (unwind_info.encoding & UNWIND_HAS_LSDA) + { + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) + { + uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) + { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) + { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); + } + } + } + } + return true; + } + return false; +} + +enum x86_64_eh_regnum { + rax = 0, + rdx = 1, + rcx = 2, + rbx = 3, + rsi = 4, + rdi = 5, + rbp = 6, + rsp = 7, + r8 = 8, + r9 = 9, + r10 = 10, + r11 = 11, + r12 = 12, + r13 = 13, + r14 = 14, + r15 = 15, + rip = 16 // this is officially the Return Address register number, but close enough +}; + +// Convert the compact_unwind_info.h register numbering scheme +// to eRegisterKindGCC (eh_frame) register numbering scheme. +uint32_t +translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno) +{ + switch (unwind_regno) + { + case UNWIND_X86_64_REG_RBX: + return x86_64_eh_regnum::rbx; + case UNWIND_X86_64_REG_R12: + return x86_64_eh_regnum::r12; + case UNWIND_X86_64_REG_R13: + return x86_64_eh_regnum::r13; + case UNWIND_X86_64_REG_R14: + return x86_64_eh_regnum::r14; + case UNWIND_X86_64_REG_R15: + return x86_64_eh_regnum::r15; + case UNWIND_X86_64_REG_RBP: + return x86_64_eh_regnum::rbp; + default: + return LLDB_INVALID_REGNUM; + } +} + +bool +CompactUnwindInfo::CreateUnwindPlan_x86_64 (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 (eRegisterKindGCC); + + 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_X86_64_MODE_MASK; + switch (mode) + { + case UNWIND_X86_64_MODE_RBP_FRAME: + { + row->SetCFARegister (translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP)); + row->SetCFAOffset (2 * wordsize); + row->SetOffset (0); + 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); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow (row); + return true; + } + break; + + 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. + return false; + } + break; + + case UNWIND_X86_64_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0) + { + uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) + { + Address subl_payload_addr (function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide (offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), + 4, 0, error); + if (large_stack_size != 0 && error.Success ()) + { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } + else + { + return false; + } + } + else + { + return false; + } + } + else + { + return false; + } + } + + row->SetCFARegister (x86_64_eh_regnum::rsp); + row->SetCFAOffset (stack_size * wordsize); + row->SetOffset (0); + row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 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. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + uint32_t saved_registers_offset = 1; + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + case UNWIND_X86_64_REG_RBP: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset++; + } + } + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_64_MODE_DWARF: + { + return false; + } + break; + + case 0: + { + return false; + } + break; + } + return false; +} + +enum i386_eh_regnum { + eax = 0, + ecx = 1, + edx = 2, + ebx = 3, + ebp = 4, + esp = 5, + esi = 6, + edi = 7, + eip = 8 // this is officially the Return Address register number, but close enough +}; + +// Convert the compact_unwind_info.h register numbering scheme +// to eRegisterKindGCC (eh_frame) register numbering scheme. +uint32_t +translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno) +{ + switch (unwind_regno) + { + case UNWIND_X86_REG_EBX: + return i386_eh_regnum::ebx; + case UNWIND_X86_REG_ECX: + return i386_eh_regnum::ecx; + case UNWIND_X86_REG_EDX: + return i386_eh_regnum::edx; + case UNWIND_X86_REG_EDI: + return i386_eh_regnum::edi; + case UNWIND_X86_REG_ESI: + return i386_eh_regnum::esi; + case UNWIND_X86_REG_EBP: + return i386_eh_regnum::ebp; + default: + return LLDB_INVALID_REGNUM; + } +} + + +bool +CompactUnwindInfo::CreateUnwindPlan_i386 (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 (eRegisterKindGCC); + + 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_X86_MODE_MASK; + switch (mode) + { + case UNWIND_X86_MODE_EBP_FRAME: + { + row->SetCFARegister (translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP)); + row->SetCFAOffset (2 * wordsize); + row->SetOffset (0); + 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); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) + { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_MODE_STACK_IND: + case UNWIND_X86_MODE_STACK_IMMD: + { + uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0) + { + uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList (); + if (sl) + { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) + { + Address subl_payload_addr (function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide (offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), + 4, 0, error); + if (large_stack_size != 0 && error.Success ()) + { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } + else + { + return false; + } + } + else + { + return false; + } + } + else + { + return false; + } + } + + row->SetCFARegister (i386_eh_regnum::esp); + row->SetCFAOffset (stack_size * wordsize); + 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. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) + { + case 6: + permunreg[0] = permutation/120; // 120 == 5! + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; // 24 == 4! + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; // 6 == 3! + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; // 2 == 2! + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation/120; + permutation -= (permunreg[0]*120); + permunreg[1] = permutation/24; + permutation -= (permunreg[1]*24); + permunreg[2] = permutation/6; + permutation -= (permunreg[2]*6); + permunreg[3] = permutation/2; + permutation -= (permunreg[3]*2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation/60; + permutation -= (permunreg[0]*60); + permunreg[1] = permutation/12; + permutation -= (permunreg[1]*12); + permunreg[2] = permutation/3; + permutation -= (permunreg[2]*3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation/20; + permutation -= (permunreg[0]*20); + permunreg[1] = permutation/4; + permutation -= (permunreg[1]*4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation/5; + permutation -= (permunreg[0]*5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < register_count; i++) + { + int renum = 0; + for (int j = 1; j < 7; j++) + { + if (used[j] == false) + { + if (renum == permunreg[i]) + { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + uint32_t saved_registers_offset = 1; + saved_registers_offset++; + + for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) + { + switch (registers[i]) + { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + case UNWIND_X86_REG_EBP: + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset++; + } + } + + unwind_plan.AppendRow (row); + return true; + } + break; + + case UNWIND_X86_MODE_DWARF: + { + return false; + } + break; + } + return false; +} diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp index f99ca53d9629..6483258ee678 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp @@ -325,18 +325,19 @@ CompileUnit::ResolveSymbolContext // when finding file indexes std::vector<uint32_t> file_indexes; const bool full_match = (bool)file_spec.GetDirectory(); - bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match); + const bool remove_backup_dots = true; + bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots); // If we are not looking for inlined functions and our file spec doesn't // match then we are done... if (file_spec_matches_cu_file_spec == false && check_inlines == false) return 0; - uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true); + uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true, remove_backup_dots); while (file_idx != UINT32_MAX) { file_indexes.push_back (file_idx); - file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true); + file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true, remove_backup_dots); } const size_t num_file_indexes = file_indexes.size(); diff --git a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp index a9da631eb452..78d262307c24 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -218,20 +218,27 @@ DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset) // FDE, which is the address of a language-specific // data area (LSDA). The size of the LSDA pointer is // specified by the pointer encoding used. - m_cfi_data.GetU8(&offset); + cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset); break; case 'P': // Indicates the presence of two arguments in the - // Augmentation Data of the cie_sp-> The first argument + // Augmentation Data of the CIE. The first argument // is 1-byte and represents the pointer encoding // used for the second argument, which is the // address of a personality routine handler. The // size of the personality routine pointer is // specified by the pointer encoding used. + // + // The address of the personality function will + // be stored at this location. Pre-execution, it + // will be all zero's so don't read it until we're + // trying to do an unwind & the reloc has been + // resolved. { uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); - m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); + const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); + cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); } break; @@ -449,11 +456,39 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr AddressRange range (range_base, m_objfile.GetAddressByteSize(), m_objfile.GetSectionList()); range.SetByteSize (range_len); + addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS; + if (cie->augmentation[0] == 'z') { uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); + if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) + { + offset_t saved_offset = offset; + lsda_data_file_address = m_cfi_data.GetGNUEHPointer(&offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); + if (offset - saved_offset != aug_data_len) + { + // There is more in the augmentation region than we know how to process; + // don't read anything. + lsda_data_file_address = LLDB_INVALID_ADDRESS; + } + offset = saved_offset; + } offset += aug_data_len; } + Address lsda_data; + Address personality_function_ptr; + + if (lsda_data_file_address != LLDB_INVALID_ADDRESS && cie->personality_loc != LLDB_INVALID_ADDRESS) + { + m_objfile.GetModule()->ResolveFileAddress (lsda_data_file_address, lsda_data); + m_objfile.GetModule()->ResolveFileAddress (cie->personality_loc, personality_function_ptr); + } + + if (lsda_data.IsValid() && personality_function_ptr.IsValid()) + { + unwind_plan.SetLSDAAddress (lsda_data); + unwind_plan.SetPersonalityFunctionPtr (personality_function_ptr); + } uint32_t reg_num = 0; int32_t op_offset = 0; diff --git a/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp b/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp index 3943f02c5474..c72ca045b6c7 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Declaration.cpp @@ -110,7 +110,7 @@ lldb_private::operator == (const Declaration &lhs, const Declaration &rhs) return lhs.GetFile() == rhs.GetFile(); #else if (lhs.GetLine () == rhs.GetLine ()) - return lhs.GetFile() == rhs.GetFile(); + return FileSpec::Equal(lhs.GetFile(),rhs.GetFile(), true, true); #endif return false; } diff --git a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp index 95fc81747859..1eb73ee3649b 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Address.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/UnwindTable.h" @@ -24,145 +25,212 @@ using namespace lldb; using namespace lldb_private; +//------------------------------------------------ +/// constructor +//------------------------------------------------ -FuncUnwinders::FuncUnwinders -( - UnwindTable& unwind_table, - AddressRange range -) : - m_unwind_table(unwind_table), - m_range(range), +FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) : + m_unwind_table (unwind_table), + m_range (range), m_mutex (Mutex::eMutexTypeRecursive), - m_unwind_plan_call_site_sp (), - m_unwind_plan_non_call_site_sp (), + 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_fast_sp (), m_unwind_plan_arch_default_sp (), - m_tried_unwind_at_call_site (false), - m_tried_unwind_at_non_call_site (false), + 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_fast (false), m_tried_unwind_arch_default (false), m_tried_unwind_arch_default_at_func_entry (false), - m_first_non_prologue_insn() + m_first_non_prologue_insn () { } -FuncUnwinders::~FuncUnwinders () +//------------------------------------------------ +/// destructor +//------------------------------------------------ + +FuncUnwinders::~FuncUnwinders () { } UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset) +FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests a call site unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // m_unwind_plan_call_site_sp, and have another thread enter this function - // and return the partially filled in m_unwind_plan_call_site_sp pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) Mutex::Locker locker (m_mutex); - if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr) + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset); + if (unwind_plan_sp.get() == nullptr) { - m_tried_unwind_at_call_site = true; - // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a - // function does not cover the entire range of the function and so the FDE only lists a subset of the - // address range. If we try to look up the unwind info by the starting address of the function - // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE. We need to use the actual byte offset - // into the function when looking it up. - - if (m_range.GetBaseAddress().IsValid()) - { - Address current_pc (m_range.GetBaseAddress ()); - if (current_offset != -1) - current_pc.SetOffset (current_pc.GetOffset() + current_offset); + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset); + } + + return unwind_plan_sp; +} - DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); - if (eh_frame) +UnwindPlanSP +FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset) +{ + if (m_unwind_plan_compact_unwind.size() > 0) + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func + if (m_tried_unwind_plan_compact_unwind) + return UnwindPlanSP(); + + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_compact_unwind = true; + if (m_range.GetBaseAddress().IsValid()) + { + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); + if (compact_unwind) + { + UnwindPlanSP unwind_plan_sp (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (compact_unwind->GetUnwindPlan (target, current_pc, *unwind_plan_sp)) { - m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp)) - m_unwind_plan_call_site_sp.reset(); + m_unwind_plan_compact_unwind.push_back (unwind_plan_sp); + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func } } } - return m_unwind_plan_call_site_sp; + return UnwindPlanSP(); } UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) +FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) - Mutex::Locker locker (m_mutex); - if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr) + 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); + m_tried_unwind_plan_eh_frame = true; + if (m_range.GetBaseAddress().IsValid()) { - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); - if (assembly_profiler_sp) + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); + if (eh_frame) { - if (target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_32_i386 - || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64 - || target.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h) + m_unwind_plan_eh_frame_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_sp)) + m_unwind_plan_eh_frame_sp.reset(); + } + } + return m_unwind_plan_eh_frame_sp; +} + +UnwindPlanSP +FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset) +{ + if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented) + return m_unwind_plan_eh_frame_augmented_sp; + + // Only supported on x86 architectures where we get eh_frame from the compiler that describes + // the prologue instructions perfectly, and sometimes the epilogue instructions too. + if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 + && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 + && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) + { + m_tried_unwind_plan_eh_frame_augmented = true; + return m_unwind_plan_eh_frame_augmented_sp; + } + + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_eh_frame_augmented = true; + + if (m_range.GetBaseAddress().IsValid()) + { + Address current_pc (m_range.GetBaseAddress ()); + if (current_offset != -1) + current_pc.SetOffset (current_pc.GetOffset() + current_offset); + DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); + if (eh_frame) + { + m_unwind_plan_eh_frame_augmented_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_augmented_sp)) { - // For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler - // to augment it into asynchronous unwind table. - GetUnwindPlanAtCallSite(current_offset); - if (m_unwind_plan_call_site_sp) { - UnwindPlan* plan = new UnwindPlan (*m_unwind_plan_call_site_sp); - if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan)) { - m_unwind_plan_non_call_site_sp.reset (plan); - return m_unwind_plan_non_call_site_sp; + m_unwind_plan_eh_frame_augmented_sp.reset(); + } + else + { + // Augment the eh_frame instructions with epilogue descriptions if necessary so the + // UnwindPlan can be used at any instruction in the function. + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) + { + if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) + { + m_unwind_plan_eh_frame_augmented_sp.reset(); } } + else + { + m_unwind_plan_eh_frame_augmented_sp.reset(); + } } + } + } + return m_unwind_plan_eh_frame_augmented_sp; +} + + +UnwindPlanSP +FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset) +{ + if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly) + return m_unwind_plan_assembly_sp; - m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp)) - m_unwind_plan_non_call_site_sp.reset(); + Mutex::Locker lock (m_mutex); + m_tried_unwind_plan_assembly = true; + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) + { + m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_assembly_sp)) + { + m_unwind_plan_assembly_sp.reset(); } } - return m_unwind_plan_non_call_site_sp; + return m_unwind_plan_assembly_sp; +} + + +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) + { + non_call_site_unwindplan_sp = GetAssemblyUnwindPlan (target, thread, current_offset); + } + return non_call_site_unwindplan_sp; } UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) + return m_unwind_plan_fast_sp; + Mutex::Locker locker (m_mutex); - if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr) + m_tried_unwind_fast = true; + + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + if (assembly_profiler_sp) { - m_tried_unwind_fast = true; - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); - if (assembly_profiler_sp) + m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) { - m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) - m_unwind_plan_fast_sp.reset(); + m_unwind_plan_fast_sp.reset(); } } return m_unwind_plan_fast_sp; @@ -171,32 +239,23 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + 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); - if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr) + m_tried_unwind_arch_default = true; + + Address current_pc; + ProcessSP process_sp (thread.CalculateProcess()); + if (process_sp) { - m_tried_unwind_arch_default = true; - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) + ABI *abi = process_sp->GetABI().get(); + if (abi) { - ABI *abi = process_sp->GetABI().get(); - if (abi) + m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { - m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (m_unwind_plan_arch_default_sp) - abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp); + m_unwind_plan_arch_default_sp.reset(); } } } @@ -207,32 +266,23 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) { - // Lock the mutex to ensure we can always give out the most appropriate - // information. We want to make sure if someone requests an unwind - // plan, that they get one and don't run into a race condition where one - // thread has started to create the unwind plan and has put it into - // the unique pointer member variable, and have another thread enter this function - // and return the partially filled pointer contained in the unique pointer. - // We also want to make sure that we lock out other unwind plans from - // being accessed until this one is done creating itself in case someone - // had some code like: - // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) - // if (best_unwind_plan == NULL) - // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) + 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); - if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr) + m_tried_unwind_arch_default_at_func_entry = true; + + Address current_pc; + ProcessSP process_sp (thread.CalculateProcess()); + if (process_sp) { - m_tried_unwind_arch_default_at_func_entry = true; - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) + ABI *abi = process_sp->GetABI().get(); + if (abi) { - ABI *abi = process_sp->GetABI().get(); - if (abi) + m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp)) { - m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (m_unwind_plan_arch_default_at_func_entry_sp) - abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp); + m_unwind_plan_arch_default_at_func_entry_sp.reset(); } } } @@ -246,10 +296,11 @@ FuncUnwinders::GetFirstNonPrologueInsn (Target& target) { if (m_first_non_prologue_insn.IsValid()) return m_first_non_prologue_insn; + + Mutex::Locker locker (m_mutex); ExecutionContext exe_ctx (target.shared_from_this(), false); UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); if (assembly_profiler_sp) - if (assembly_profiler_sp) assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn); return m_first_non_prologue_insn; } @@ -260,16 +311,6 @@ FuncUnwinders::GetFunctionStartAddress () const return m_range.GetBaseAddress(); } -void -FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread) -{ - UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread); - if (arch_default && m_tried_unwind_at_call_site) - { - m_unwind_plan_call_site_sp = arch_default; - } -} - lldb::UnwindAssemblySP FuncUnwinders::GetUnwindAssemblyProfiler () { @@ -281,3 +322,39 @@ FuncUnwinders::GetUnwindAssemblyProfiler () } return assembly_profiler_sp; } + +Address +FuncUnwinders::GetLSDAAddress (Target &target) +{ + Address lsda_addr; + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); + if (unwind_plan_sp.get() == nullptr) + { + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); + } + if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) + { + lsda_addr = unwind_plan_sp->GetLSDAAddress(); + } + return lsda_addr; +} + + +Address +FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target) +{ + Address personality_addr; + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); + if (unwind_plan_sp.get() == nullptr) + { + unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); + } + if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) + { + personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); + } + + return personality_addr; +} diff --git a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp index 4b4e33b2b0e9..92b243d80a91 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp @@ -562,7 +562,6 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map) // Append the sequence since we just terminated the previous one line_table_ap->InsertSequence (&sequence); sequence.Clear(); - prev_entry_was_linked = false; } // Now link the current entry diff --git a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp index 11b540071208..c24e83260d4d 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp @@ -371,6 +371,7 @@ ObjectFile::GetAddressClass (addr_t file_addr) case eSectionTypeDWARFAppleObjC: return eAddressClassDebug; case eSectionTypeEHFrame: + case eSectionTypeCompactUnwind: return eAddressClassRuntime; case eSectionTypeELFSymbolTable: case eSectionTypeELFDynamicSymbols: @@ -458,6 +459,9 @@ ObjectFile::CopyData (lldb::offset_t offset, size_t length, void *dst) const size_t ObjectFile::ReadSectionData (const Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len) const { + assert(section); + section_offset *= section->GetTargetByteSize(); + // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData (section, section_offset, dst, dst_len); @@ -555,8 +559,6 @@ ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section // The object file now contains a full mmap'ed copy of the object file data, so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); } - section_data.Clear(); - return 0; } diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp index 880519955277..b6ed94610b0a 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Symbol.cpp @@ -626,7 +626,7 @@ Symbol::ResolveCallableAddress(Target &target) const Address func_so_addr; - bool is_indirect; + bool is_indirect = IsIndirect(); if (GetType() == eSymbolTypeReExported) { Symbol *reexported_symbol = ResolveReExportedSymbol(target); diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp index 0e390dd08c5f..129f4def0067 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp @@ -128,7 +128,8 @@ SymbolContext::DumpStopContext const Address &addr, bool show_fullpaths, bool show_module, - bool show_inlined_frames + bool show_inlined_frames, + bool show_function_arguments ) const { bool dumped_something = false; @@ -146,7 +147,12 @@ SymbolContext::DumpStopContext { SymbolContext inline_parent_sc; Address inline_parent_addr; - if (function->GetMangled().GetName()) + if (show_function_arguments == false && function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments)) + { + dumped_something = true; + function->GetMangled().GetName(Mangled::ePreferDemangledWithoutArguments).Dump(s); + } + else if (function->GetMangled().GetName()) { dumped_something = true; function->GetMangled().GetName().Dump(s); @@ -188,7 +194,7 @@ SymbolContext::DumpStopContext { s->EOL(); s->Indent(); - return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames); + return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames, show_function_arguments); } } else diff --git a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp index 4eb538fb1352..42b76590aaea 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp @@ -31,6 +31,7 @@ #include "llvm/ADT/StringRef.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" using namespace lldb; using namespace lldb_private; @@ -1291,6 +1292,117 @@ TypeImpl::GetDescription (lldb_private::Stream &strm, return true; } +TypeMemberFunctionImpl& +TypeMemberFunctionImpl::operator = (const TypeMemberFunctionImpl& rhs) +{ + if (this != &rhs) + { + m_type = rhs.m_type; + m_objc_method_decl = rhs.m_objc_method_decl; + m_name = rhs.m_name; + m_kind = rhs.m_kind; + } + return *this; +} + +bool +TypeMemberFunctionImpl::IsValid () +{ + return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; +} + +ConstString +TypeMemberFunctionImpl::GetName () const +{ + return m_name; +} + +ClangASTType +TypeMemberFunctionImpl::GetType () const +{ + return m_type; +} + +lldb::MemberFunctionKind +TypeMemberFunctionImpl::GetKind () const +{ + return m_kind; +} + +std::string +TypeMemberFunctionImpl::GetPrintableTypeName () +{ + if (m_type) + return m_type.GetTypeName().AsCString("<unknown>"); + if (m_objc_method_decl) + { + if (m_objc_method_decl->getClassInterface()) + { + return m_objc_method_decl->getClassInterface()->getName(); + } + } + return "<unknown>"; +} + +bool +TypeMemberFunctionImpl::GetDescription (Stream& stream) +{ + switch (m_kind) { + case lldb::eMemberFunctionKindUnknown: + return false; + case lldb::eMemberFunctionKindConstructor: + stream.Printf("constructor for %s", GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindDestructor: + stream.Printf("destructor for %s", GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindInstanceMethod: + stream.Printf("instance method %s of type %s", + m_name.AsCString(), + GetPrintableTypeName().c_str()); + break; + case lldb::eMemberFunctionKindStaticMethod: + stream.Printf("static method %s of type %s", + m_name.AsCString(), + GetPrintableTypeName().c_str()); + break; + } + return true; +} + +ClangASTType +TypeMemberFunctionImpl::GetReturnType () const +{ + if (m_type) + return m_type.GetFunctionReturnType(); + if (m_objc_method_decl) + return ClangASTType(&m_objc_method_decl->getASTContext(),m_objc_method_decl->getReturnType().getAsOpaquePtr()); + return ClangASTType(); +} + +size_t +TypeMemberFunctionImpl::GetNumArguments () const +{ + if (m_type) + return m_type.GetNumberOfFunctionArguments(); + if (m_objc_method_decl) + return m_objc_method_decl->param_size(); + return 0; +} + +ClangASTType +TypeMemberFunctionImpl::GetArgumentAtIndex (size_t idx) const +{ + if (m_type) + return m_type.GetFunctionArgumentAtIndex (idx); + if (m_objc_method_decl) + { + if (idx < m_objc_method_decl->param_size()) + return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->parameters()[idx]->getOriginalType().getAsOpaquePtr()); + } + return ClangASTType(); +} + TypeEnumMemberImpl::TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl, const lldb_private::ClangASTType& integer_type) : m_integer_type_sp(), diff --git a/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp b/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp index ff0468e314d8..87d0f49421c5 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp @@ -153,6 +153,7 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla void UnwindPlan::Row::Clear () { + m_cfa_type = CFAIsRegisterPlusOffset; m_offset = 0; m_cfa_reg_num = LLDB_INVALID_REGNUM; m_cfa_offset = 0; @@ -167,7 +168,7 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, if (base_addr != LLDB_INVALID_ADDRESS) s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); else - s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset()); + s.Printf ("%4" PRId64 ": CFA=", GetOffset()); if (reg_info) s.Printf ("%s", reg_info->name); @@ -189,10 +190,11 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, } UnwindPlan::Row::Row() : - m_offset(0), - m_cfa_reg_num(LLDB_INVALID_REGNUM), - m_cfa_offset(0), - m_register_locations() + m_offset (0), + m_cfa_type (CFAIsRegisterPlusOffset), + m_cfa_reg_num (LLDB_INVALID_REGNUM), + m_cfa_offset (0), + m_register_locations () { } @@ -209,6 +211,16 @@ UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLoc } void +UnwindPlan::Row::RemoveRegisterInfo (uint32_t reg_num) +{ + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) + { + m_register_locations.erase(pos); + } +} + +void UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) { m_register_locations[reg_num] = register_location; @@ -301,6 +313,23 @@ UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const { if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset) return false; + + if (m_cfa_type != rhs.m_cfa_type) + return false; + + if (m_cfa_type == CFAIsRegisterPlusOffset) + { + if (m_cfa_reg_num != rhs.m_cfa_reg_num) + return false; + if (m_cfa_offset != rhs.m_cfa_offset) + return false; + } + if (m_cfa_type == CFAIsRegisterDereferenced) + { + if (m_cfa_reg_num != rhs.m_cfa_reg_num) + return false; + } + return m_register_locations == rhs.m_register_locations; } @@ -449,6 +478,44 @@ UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const { s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); } + if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) + { + TargetSP target_sp(thread->CalculateTarget()); + addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get()); + addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get()); + + if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS) + { + s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n", + lsda_load_addr, personality_func_load_addr); + } + } + s.Printf ("This UnwindPlan is sourced from the compiler: "); + switch (m_plan_is_sourced_from_compiler) + { + case eLazyBoolYes: + s.Printf ("yes.\n"); + break; + case eLazyBoolNo: + s.Printf ("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf ("not specified.\n"); + break; + } + s.Printf ("This UnwindPlan is valid at all instruction locations: "); + switch (m_plan_is_valid_at_all_instruction_locations) + { + case eLazyBoolYes: + s.Printf ("yes.\n"); + break; + case eLazyBoolNo: + s.Printf ("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf ("not specified.\n"); + break; + } if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) { s.PutCString ("Address range of this UnwindPlan: "); diff --git a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp index df9f5b932565..90b33a69a789 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/CompactUnwindInfo.h" // There is one UnwindTable object per ObjectFile. // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile. @@ -30,7 +31,8 @@ UnwindTable::UnwindTable (ObjectFile& objfile) : m_unwinds (), m_initialized (false), m_mutex (), - m_eh_frame (nullptr) + m_eh_frame (nullptr), + m_compact_unwind (nullptr) { } @@ -56,6 +58,11 @@ UnwindTable::Initialize () { m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true); } + sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true); + if (sect.get()) + { + m_compact_unwind = new CompactUnwindInfo(m_object_file, sect); + } } m_initialized = true; @@ -154,6 +161,13 @@ UnwindTable::GetEHFrameInfo () return m_eh_frame; } +CompactUnwindInfo * +UnwindTable::GetCompactUnwindInfo () +{ + Initialize(); + return m_compact_unwind; +} + bool UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch) { diff --git a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp index e6a9b027fc13..b1a60f6b4a24 100644 --- a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp +++ b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp @@ -174,13 +174,15 @@ Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) sc.block = nullptr; sc.line_entry.Clear(); bool show_inlined_frames = false; + const bool show_function_arguments = true; dumped_declaration_info = sc.DumpStopContext (s, nullptr, Address(), show_fullpaths, show_module, - show_inlined_frames); + show_inlined_frames, + show_function_arguments); if (sc.function) s->PutChar(':'); |