aboutsummaryrefslogtreecommitdiffstats
path: root/source/Symbol
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
committerEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
commit205afe679855a4ce8149cdaa94d3f0868ce796dc (patch)
tree09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/Symbol
parent0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff)
downloadsrc-205afe679855a4ce8149cdaa94d3f0868ce796dc.tar.gz
src-205afe679855a4ce8149cdaa94d3f0868ce796dc.zip
Import LLDB as of upstream SVN r225923 (git 2b588ecd)vendor/lldb/lldb-r225923
This corresponds with the branchpoint for the 3.6 release. A number of files not required for the FreeBSD build have been removed. Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=278332 svn path=/vendor/lldb/lldb-r225923/; revision=278333; tag=vendor/lldb/lldb-r225923
Diffstat (limited to 'source/Symbol')
-rw-r--r--source/Symbol/ClangASTContext.cpp67
-rw-r--r--source/Symbol/ClangASTImporter.cpp2
-rw-r--r--source/Symbol/ClangASTType.cpp225
-rw-r--r--source/Symbol/ClangExternalASTSourceCommon.cpp38
-rw-r--r--source/Symbol/CompactUnwindInfo.cpp1215
-rw-r--r--source/Symbol/CompileUnit.cpp7
-rw-r--r--source/Symbol/DWARFCallFrameInfo.cpp41
-rw-r--r--source/Symbol/Declaration.cpp2
-rw-r--r--source/Symbol/FuncUnwinders.cpp379
-rw-r--r--source/Symbol/LineTable.cpp1
-rw-r--r--source/Symbol/ObjectFile.cpp6
-rw-r--r--source/Symbol/Symbol.cpp2
-rw-r--r--source/Symbol/SymbolContext.cpp12
-rw-r--r--source/Symbol/Type.cpp112
-rw-r--r--source/Symbol/UnwindPlan.cpp77
-rw-r--r--source/Symbol/UnwindTable.cpp16
-rw-r--r--source/Symbol/Variable.cpp4
17 files changed, 2002 insertions, 204 deletions
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index aae96bfa9a3b..d851ae792181 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/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);
@@ -1799,7 +1822,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);
}
@@ -1849,7 +1872,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
@@ -2067,7 +2106,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);
@@ -2078,7 +2117,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/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index 6579afb2f748..a925f808f858 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/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/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp
index a0878ae442c8..8b672fac4312 100644
--- a/source/Symbol/ClangASTType.cpp
+++ b/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/source/Symbol/ClangExternalASTSourceCommon.cpp b/source/Symbol/ClangExternalASTSourceCommon.cpp
index 650d252a8fc3..79cc9a91355a 100644
--- a/source/Symbol/ClangExternalASTSourceCommon.cpp
+++ b/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/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp
new file mode 100644
index 000000000000..8c6a2e7214c3
--- /dev/null
+++ b/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/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp
index f99ca53d9629..6483258ee678 100644
--- a/source/Symbol/CompileUnit.cpp
+++ b/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/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp
index a9da631eb452..78d262307c24 100644
--- a/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/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/source/Symbol/Declaration.cpp b/source/Symbol/Declaration.cpp
index 3943f02c5474..c72ca045b6c7 100644
--- a/source/Symbol/Declaration.cpp
+++ b/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/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 95fc81747859..1eb73ee3649b 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/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/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp
index 4b4e33b2b0e9..92b243d80a91 100644
--- a/source/Symbol/LineTable.cpp
+++ b/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/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
index 11b540071208..c24e83260d4d 100644
--- a/source/Symbol/ObjectFile.cpp
+++ b/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/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
index 880519955277..b6ed94610b0a 100644
--- a/source/Symbol/Symbol.cpp
+++ b/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/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index 0e390dd08c5f..129f4def0067 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/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/source/Symbol/Type.cpp b/source/Symbol/Type.cpp
index 4eb538fb1352..42b76590aaea 100644
--- a/source/Symbol/Type.cpp
+++ b/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/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp
index ff0468e314d8..87d0f49421c5 100644
--- a/source/Symbol/UnwindPlan.cpp
+++ b/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/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp
index df9f5b932565..90b33a69a789 100644
--- a/source/Symbol/UnwindTable.cpp
+++ b/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/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
index e6a9b027fc13..b1a60f6b4a24 100644
--- a/source/Symbol/Variable.cpp
+++ b/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(':');