summaryrefslogtreecommitdiffstats
path: root/source/Expression
diff options
context:
space:
mode:
Diffstat (limited to 'source/Expression')
-rw-r--r--source/Expression/ASTDumper.cpp132
-rw-r--r--source/Expression/ASTResultSynthesizer.cpp512
-rw-r--r--source/Expression/ASTStructExtractor.cpp220
-rw-r--r--source/Expression/ClangASTSource.cpp2075
-rw-r--r--source/Expression/ClangExpressionDeclMap.cpp2171
-rw-r--r--source/Expression/ClangExpressionParser.cpp621
-rw-r--r--source/Expression/ClangExpressionVariable.cpp142
-rw-r--r--source/Expression/ClangModulesDeclVendor.cpp731
-rw-r--r--source/Expression/ClangPersistentVariables.cpp89
-rw-r--r--source/Expression/ClangUserExpression.cpp1172
-rw-r--r--source/Expression/ClangUtilityFunction.cpp198
-rw-r--r--source/Expression/DWARFExpression.cpp659
-rw-r--r--source/Expression/Expression.cpp32
-rw-r--r--source/Expression/ExpressionSourceCode.cpp145
-rw-r--r--source/Expression/ExpressionVariable.cpp36
-rw-r--r--source/Expression/FunctionCaller.cpp (renamed from source/Expression/ClangFunction.cpp)248
-rw-r--r--source/Expression/IRDynamicChecks.cpp100
-rw-r--r--source/Expression/IRExecutionUnit.cpp22
-rw-r--r--source/Expression/IRForTarget.cpp2819
-rw-r--r--source/Expression/IRInterpreter.cpp16
-rw-r--r--source/Expression/IRMemoryMap.cpp21
-rw-r--r--source/Expression/LLVMUserExpression.cpp363
-rw-r--r--source/Expression/Materializer.cpp303
-rw-r--r--source/Expression/REPL.cpp649
-rw-r--r--source/Expression/UserExpression.cpp348
-rw-r--r--source/Expression/UtilityFunction.cpp124
26 files changed, 2431 insertions, 11517 deletions
diff --git a/source/Expression/ASTDumper.cpp b/source/Expression/ASTDumper.cpp
deleted file mode 100644
index 5210d14..0000000
--- a/source/Expression/ASTDumper.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/Log.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Symbol/ClangASTType.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lldb_private;
-
-ASTDumper::ASTDumper (clang::Decl *decl)
-{
- clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl);
-
- bool has_external_lexical_storage;
- bool has_external_visible_storage;
-
- if (decl_ctx)
- {
- has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
- }
-
- llvm::raw_string_ostream os(m_dump);
- decl->print (os);
- os.flush();
-
- if (decl_ctx)
- {
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
- }
-}
-
-ASTDumper::ASTDumper (clang::DeclContext *decl_ctx)
-{
- bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
-
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
-
- if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx))
- {
- llvm::raw_string_ostream os(m_dump);
- decl->print (os);
- os.flush();
- }
- else
- {
- m_dump.assign("<DeclContext is not a Decl>");
- }
-
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
-}
-
-ASTDumper::ASTDumper (const clang::Type *type)
-{
- m_dump = clang::QualType(type, 0).getAsString();
-}
-
-ASTDumper::ASTDumper (clang::QualType type)
-{
- m_dump = type.getAsString();
-}
-
-ASTDumper::ASTDumper (lldb::clang_type_t type)
-{
- m_dump = clang::QualType::getFromOpaquePtr(type).getAsString();
-}
-
-ASTDumper::ASTDumper (const ClangASTType &clang_type)
-{
- m_dump = clang_type.GetQualType().getAsString();
-}
-
-
-const char *
-ASTDumper::GetCString()
-{
- return m_dump.c_str();
-}
-
-void ASTDumper::ToSTDERR()
-{
- fprintf(stderr, "%s\n", m_dump.c_str());
-}
-
-void ASTDumper::ToLog(Log *log, const char *prefix)
-{
- size_t len = m_dump.length() + 1;
-
- char *alloc = (char*)malloc(len);
- char *str = alloc;
-
- memcpy(str, m_dump.c_str(), len);
-
- char *end = NULL;
-
- end = strchr(str, '\n');
-
- while (end)
- {
- *end = '\0';
-
- log->Printf("%s%s", prefix, str);
-
- *end = '\n';
-
- str = end + 1;
- end = strchr(str, '\n');
- }
-
- log->Printf("%s%s", prefix, str);
-
- free(alloc);
-}
-
-void ASTDumper::ToStream(lldb::StreamSP &stream)
-{
- stream->PutCString(m_dump.c_str());
-}
diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp
deleted file mode 100644
index c3d42cb..0000000
--- a/source/Expression/ASTResultSynthesizer.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "stdlib.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Stmt.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ASTResultSynthesizer.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Target/Target.h"
-
-using namespace llvm;
-using namespace clang;
-using namespace lldb_private;
-
-ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
- Target &target) :
- m_ast_context (NULL),
- m_passthrough (passthrough),
- m_passthrough_sema (NULL),
- m_target (target),
- m_sema (NULL)
-{
- if (!m_passthrough)
- return;
-
- m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
-}
-
-ASTResultSynthesizer::~ASTResultSynthesizer()
-{
-}
-
-void
-ASTResultSynthesizer::Initialize(ASTContext &Context)
-{
- m_ast_context = &Context;
-
- if (m_passthrough)
- m_passthrough->Initialize(Context);
-}
-
-void
-ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
- {
- if (log && log->GetVerbose())
- {
- if (named_decl->getIdentifier())
- log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
- else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
- log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
- else
- log->Printf("TransformTopLevelDecl(<complex>)");
- }
-
- }
-
- if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
- {
- RecordDecl::decl_iterator decl_iterator;
-
- for (decl_iterator = linkage_spec_decl->decls_begin();
- decl_iterator != linkage_spec_decl->decls_end();
- ++decl_iterator)
- {
- TransformTopLevelDecl(*decl_iterator);
- }
- }
- else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
- {
- if (m_ast_context &&
- !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
- {
- RecordPersistentTypes(method_decl);
- SynthesizeObjCMethodResult(method_decl);
- }
- }
- else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
- {
- if (m_ast_context &&
- !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
- {
- RecordPersistentTypes(function_decl);
- SynthesizeFunctionResult(function_decl);
- }
- }
-}
-
-bool
-ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
-{
- DeclGroupRef::iterator decl_iterator;
-
- for (decl_iterator = D.begin();
- decl_iterator != D.end();
- ++decl_iterator)
- {
- Decl *decl = *decl_iterator;
-
- TransformTopLevelDecl(decl);
- }
-
- if (m_passthrough)
- return m_passthrough->HandleTopLevelDecl(D);
- return true;
-}
-
-bool
-ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_sema)
- return false;
-
- FunctionDecl *function_decl = FunDecl;
-
- if (!function_decl)
- return false;
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream os(s);
-
- function_decl->print(os);
-
- os.flush();
-
- log->Printf ("Untransformed function AST:\n%s", s.c_str());
- }
-
- Stmt *function_body = function_decl->getBody();
- CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
-
- bool ret = SynthesizeBodyResult (compound_stmt,
- function_decl);
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream os(s);
-
- function_decl->print(os);
-
- os.flush();
-
- log->Printf ("Transformed function AST:\n%s", s.c_str());
- }
-
- return ret;
-}
-
-bool
-ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_sema)
- return false;
-
- if (!MethodDecl)
- return false;
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream os(s);
-
- MethodDecl->print(os);
-
- os.flush();
-
- log->Printf ("Untransformed method AST:\n%s", s.c_str());
- }
-
- Stmt *method_body = MethodDecl->getBody();
-
- if (!method_body)
- return false;
-
- CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
-
- bool ret = SynthesizeBodyResult (compound_stmt,
- MethodDecl);
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream os(s);
-
- MethodDecl->print(os);
-
- os.flush();
-
- log->Printf("Transformed method AST:\n%s", s.c_str());
- }
-
- return ret;
-}
-
-bool
-ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
- DeclContext *DC)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- ASTContext &Ctx(*m_ast_context);
-
- if (!Body)
- return false;
-
- if (Body->body_empty())
- return false;
-
- Stmt **last_stmt_ptr = Body->body_end() - 1;
- Stmt *last_stmt = *last_stmt_ptr;
-
- while (dyn_cast<NullStmt>(last_stmt))
- {
- if (last_stmt_ptr != Body->body_begin())
- {
- last_stmt_ptr--;
- last_stmt = *last_stmt_ptr;
- }
- else
- {
- return false;
- }
- }
-
- Expr *last_expr = dyn_cast<Expr>(last_stmt);
-
- if (!last_expr)
- // No auxiliary variable necessary; expression returns void
- return true;
-
- // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the
- // case.
-
- do {
- ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
-
- if (!implicit_cast)
- break;
-
- if (implicit_cast->getCastKind() != CK_LValueToRValue)
- break;
-
- last_expr = implicit_cast->getSubExpr();
- } while (0);
-
- // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
- // Rvalue. This is relevant because they are handled differently.
- //
- // For Lvalues
- //
- // - In AST result synthesis (here!) the expression E is transformed into an initialization
- // T *$__lldb_expr_result_ptr = &E.
- //
- // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
- // passed into the expression.
- //
- // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
- // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent
- // variables are treated similarly, having been materialized as references, but in those
- // cases the value of the reference itself is never modified.)
- //
- // - During materialization, $0 (the result persistent variable) is ignored.
- //
- // - During dematerialization, $0 is marked up as a load address with value equal to the
- // contents of the structure entry.
- //
- // For Rvalues
- //
- // - In AST result synthesis the expression E is transformed into an initialization
- // static T $__lldb_expr_result = E.
- //
- // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
- // passed into the expression.
- //
- // - In IR transformations, an instruction is inserted at the beginning of the function to
- // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result
- // are redirected at that dereferenced version. Guard variables for the static variable
- // are excised.
- //
- // - During materialization, $0 (the result persistent variable) is populated with the location
- // of a newly-allocated area of memory.
- //
- // - During dematerialization, $0 is ignored.
-
- bool is_lvalue =
- (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
- (last_expr->getObjectKind() == OK_Ordinary);
-
- QualType expr_qual_type = last_expr->getType();
- const clang::Type *expr_type = expr_qual_type.getTypePtr();
-
- if (!expr_type)
- return false;
-
- if (expr_type->isVoidType())
- return true;
-
- if (log)
- {
- std::string s = expr_qual_type.getAsString();
-
- log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
- }
-
- clang::VarDecl *result_decl = NULL;
-
- if (is_lvalue)
- {
- IdentifierInfo *result_ptr_id;
-
- if (expr_type->isFunctionType())
- result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
- else
- result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
-
- m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);
-
- QualType ptr_qual_type;
-
- if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
- ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
- else
- ptr_qual_type = Ctx.getPointerType(expr_qual_type);
-
- result_decl = VarDecl::Create(Ctx,
- DC,
- SourceLocation(),
- SourceLocation(),
- result_ptr_id,
- ptr_qual_type,
- NULL,
- SC_Static);
-
- if (!result_decl)
- return false;
-
- ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
-
- m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false);
- }
- else
- {
- IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
-
- result_decl = VarDecl::Create(Ctx,
- DC,
- SourceLocation(),
- SourceLocation(),
- &result_id,
- expr_qual_type,
- NULL,
- SC_Static);
-
- if (!result_decl)
- return false;
-
- m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
- }
-
- DC->addDecl(result_decl);
-
- ///////////////////////////////
- // call AddInitializerToDecl
- //
-
- //m_sema->AddInitializerToDecl(result_decl, last_expr);
-
- /////////////////////////////////
- // call ConvertDeclToDeclGroup
- //
-
- Sema::DeclGroupPtrTy result_decl_group_ptr;
-
- result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
-
- ////////////////////////
- // call ActOnDeclStmt
- //
-
- StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
- SourceLocation(),
- SourceLocation()));
-
- ////////////////////////////////////////////////
- // replace the old statement with the new one
- //
-
- *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.get());
-
- return true;
-}
-
-void
-ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
-{
- if (m_passthrough)
- m_passthrough->HandleTranslationUnit(Ctx);
-}
-
-void
-ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
-{
- typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
-
- for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
- e = TypeDeclIterator(FunDeclCtx->decls_end());
- i != e;
- ++i)
- {
- MaybeRecordPersistentType(*i);
- }
-}
-
-void
-ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
-{
- if (!D->getIdentifier())
- return;
-
- StringRef name = D->getName();
-
- if (name.size() == 0 || name[0] != '$')
- return;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- ConstString name_cs(name.str().c_str());
-
- if (log)
- log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
-
- Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
- m_ast_context,
- D);
-
- if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
- m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
-}
-
-void
-ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
-{
- if (m_passthrough)
- m_passthrough->HandleTagDeclDefinition(D);
-}
-
-void
-ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
-{
- if (m_passthrough)
- m_passthrough->CompleteTentativeDefinition(D);
-}
-
-void
-ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD)
-{
- if (m_passthrough)
- m_passthrough->HandleVTable(RD);
-}
-
-void
-ASTResultSynthesizer::PrintStats()
-{
- if (m_passthrough)
- m_passthrough->PrintStats();
-}
-
-void
-ASTResultSynthesizer::InitializeSema(Sema &S)
-{
- m_sema = &S;
-
- if (m_passthrough_sema)
- m_passthrough_sema->InitializeSema(S);
-}
-
-void
-ASTResultSynthesizer::ForgetSema()
-{
- m_sema = NULL;
-
- if (m_passthrough_sema)
- m_passthrough_sema->ForgetSema();
-}
diff --git a/source/Expression/ASTStructExtractor.cpp b/source/Expression/ASTStructExtractor.cpp
deleted file mode 100644
index 98628db..0000000
--- a/source/Expression/ASTStructExtractor.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "stdlib.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Stmt.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/Sema.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Expression/ASTStructExtractor.h"
-
-using namespace llvm;
-using namespace clang;
-using namespace lldb_private;
-
-ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
- const char *struct_name,
- ClangFunction &function) :
- m_ast_context (NULL),
- m_passthrough (passthrough),
- m_passthrough_sema (NULL),
- m_sema (NULL),
- m_action (NULL),
- m_function (function),
- m_struct_name (struct_name)
-{
- if (!m_passthrough)
- return;
-
- m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
-}
-
-ASTStructExtractor::~ASTStructExtractor()
-{
-}
-
-void
-ASTStructExtractor::Initialize(ASTContext &Context)
-{
- m_ast_context = &Context;
-
- if (m_passthrough)
- m_passthrough->Initialize(Context);
-}
-
-void
-ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
-{
- if (!F->hasBody())
- return;
-
- Stmt *body_stmt = F->getBody();
- CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt);
-
- if (!body_compound_stmt)
- return; // do we have to handle this?
-
- RecordDecl *struct_decl = NULL;
-
- StringRef desired_name(m_struct_name.c_str());
-
- for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end();
- bi != be;
- ++bi)
- {
- Stmt *curr_stmt = *bi;
- DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt);
- if (!curr_decl_stmt)
- continue;
- DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup();
- for (Decl *candidate_decl : decl_group)
- {
- RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl);
- if (!candidate_record_decl)
- continue;
- if (candidate_record_decl->getName() == desired_name)
- {
- struct_decl = candidate_record_decl;
- break;
- }
- }
- if (struct_decl)
- break;
- }
-
- if (!struct_decl)
- return;
-
- const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
-
- if (!struct_layout)
- return;
-
- m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits
- m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
- m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
-
- for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
- field_index < num_fields;
- ++field_index)
- {
- m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
- }
-
- m_function.m_struct_valid = true;
-}
-
-void
-ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
-{
- LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
-
- if (linkage_spec_decl)
- {
- RecordDecl::decl_iterator decl_iterator;
-
- for (decl_iterator = linkage_spec_decl->decls_begin();
- decl_iterator != linkage_spec_decl->decls_end();
- ++decl_iterator)
- {
- ExtractFromTopLevelDecl(*decl_iterator);
- }
- }
-
- FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
-
- if (m_ast_context &&
- function_decl &&
- !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str()))
- {
- ExtractFromFunctionDecl(function_decl);
- }
-}
-
-bool
-ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
-{
- DeclGroupRef::iterator decl_iterator;
-
- for (decl_iterator = D.begin();
- decl_iterator != D.end();
- ++decl_iterator)
- {
- Decl *decl = *decl_iterator;
-
- ExtractFromTopLevelDecl(decl);
- }
-
- if (m_passthrough)
- return m_passthrough->HandleTopLevelDecl(D);
- return true;
-}
-
-void
-ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
-{
- if (m_passthrough)
- m_passthrough->HandleTranslationUnit(Ctx);
-}
-
-void
-ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
-{
- if (m_passthrough)
- m_passthrough->HandleTagDeclDefinition(D);
-}
-
-void
-ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
-{
- if (m_passthrough)
- m_passthrough->CompleteTentativeDefinition(D);
-}
-
-void
-ASTStructExtractor::HandleVTable(CXXRecordDecl *RD)
-{
- if (m_passthrough)
- m_passthrough->HandleVTable(RD);
-}
-
-void
-ASTStructExtractor::PrintStats()
-{
- if (m_passthrough)
- m_passthrough->PrintStats();
-}
-
-void
-ASTStructExtractor::InitializeSema(Sema &S)
-{
- m_sema = &S;
- m_action = reinterpret_cast<Action*>(m_sema);
-
- if (m_passthrough_sema)
- m_passthrough_sema->InitializeSema(S);
-}
-
-void
-ASTStructExtractor::ForgetSema()
-{
- m_sema = NULL;
- m_action = NULL;
-
- if (m_passthrough_sema)
- m_passthrough_sema->ForgetSema();
-}
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
deleted file mode 100644
index 3988cd6..0000000
--- a/source/Expression/ClangASTSource.cpp
+++ /dev/null
@@ -1,2075 +0,0 @@
-//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecordLayout.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/TaggedASTType.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Target.h"
-
-#include <vector>
-
-using namespace clang;
-using namespace lldb_private;
-
-//------------------------------------------------------------------
-// Scoped class that will remove an active lexical decl from the set
-// when it goes out of scope.
-//------------------------------------------------------------------
-namespace {
- class ScopedLexicalDeclEraser
- {
- public:
- ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls,
- const clang::Decl *decl)
- : m_active_lexical_decls(decls), m_decl(decl)
- {
- }
-
- ~ScopedLexicalDeclEraser()
- {
- m_active_lexical_decls.erase(m_decl);
- }
-
- private:
- std::set<const clang::Decl *> &m_active_lexical_decls;
- const clang::Decl *m_decl;
- };
-}
-
-ClangASTSource::~ClangASTSource()
-{
- m_ast_importer->ForgetDestination(m_ast_context);
-
- // We are in the process of destruction, don't create clang ast context on demand
- // by passing false to Target::GetScratchClangASTContext(create_on_demand).
- ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false);
-
- if (!scratch_clang_ast_context)
- return;
-
- clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
-
- if (!scratch_ast_context)
- return;
-
- if (m_ast_context != scratch_ast_context)
- m_ast_importer->ForgetSource(scratch_ast_context, m_ast_context);
-}
-
-void
-ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
-{
- if (!m_ast_context)
- return;
-
- m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage();
- m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage();
-}
-
-// The core lookup interface.
-bool
-ClangASTSource::FindExternalVisibleDeclsByName
-(
- const DeclContext *decl_ctx,
- DeclarationName clang_decl_name
-)
-{
- if (!m_ast_context)
- {
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
-
- if (GetImportInProgress())
- {
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
-
- std::string decl_name (clang_decl_name.getAsString());
-
-// if (m_decl_map.DoingASTImport ())
-// return DeclContext::lookup_result();
-//
- switch (clang_decl_name.getNameKind()) {
- // Normal identifiers.
- case DeclarationName::Identifier:
- {
- clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo();
-
- if (!identifier_info ||
- identifier_info->getBuiltinID() != 0)
- {
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
- }
- break;
-
- // Operator names. Not important for now.
- case DeclarationName::CXXOperatorName:
- case DeclarationName::CXXLiteralOperatorName:
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
-
- // Using directives found in this context.
- // Tell Sema we didn't find any or we'll end up getting asked a *lot*.
- case DeclarationName::CXXUsingDirective:
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- {
- llvm::SmallVector<NamedDecl*, 1> method_decls;
-
- NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx);
-
- FindObjCMethodDecls(method_search_context);
-
- SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls);
- return (method_decls.size() > 0);
- }
- // These aren't possible in the global context.
- case DeclarationName::CXXConstructorName:
- case DeclarationName::CXXDestructorName:
- case DeclarationName::CXXConversionFunctionName:
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
-
-
- if (!GetLookupsEnabled())
- {
- // Wait until we see a '$' at the start of a name before we start doing
- // any lookups so we can avoid lookup up all of the builtin types.
- if (!decl_name.empty() && decl_name[0] == '$')
- {
- SetLookupsEnabled (true);
- }
- else
- {
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
- }
-
- ConstString const_decl_name(decl_name.c_str());
-
- const char *uniqued_const_decl_name = const_decl_name.GetCString();
- if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end())
- {
- // We are currently looking up this name...
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
- }
- m_active_lookups.insert(uniqued_const_decl_name);
-// static uint32_t g_depth = 0;
-// ++g_depth;
-// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name);
- llvm::SmallVector<NamedDecl*, 4> name_decls;
- NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx);
- FindExternalVisibleDecls(name_search_context);
- SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls);
-// --g_depth;
- m_active_lookups.erase (uniqued_const_decl_name);
- return (name_decls.size() != 0);
-}
-
-void
-ClangASTSource::CompleteType (TagDecl *tag_decl)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- if (log)
- {
- log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
- current_id, static_cast<void*>(m_ast_context),
- static_cast<void*>(tag_decl),
- tag_decl->getName().str().c_str());
-
- log->Printf(" CTD[%u] Before:", current_id);
- ASTDumper dumper((Decl*)tag_decl);
- dumper.ToLog(log, " [CTD] ");
- }
-
- auto iter = m_active_lexical_decls.find(tag_decl);
- if (iter != m_active_lexical_decls.end())
- return;
- m_active_lexical_decls.insert(tag_decl);
- ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl);
-
- if (!m_ast_importer->CompleteTagDecl (tag_decl))
- {
- // We couldn't complete the type. Maybe there's a definition
- // somewhere else that can be completed.
-
- if (log)
- log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id);
-
- bool found = false;
-
- DeclContext *decl_ctx = tag_decl->getDeclContext();
-
- if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx))
- {
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
- if (log && log->GetVerbose())
- log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)",
- current_id, static_cast<void*>(namespace_map.get()),
- static_cast<int>(namespace_map->size()));
-
- if (!namespace_map)
- return;
-
- for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
- i != e && !found;
- ++i)
- {
- if (log)
- log->Printf(" CTD[%u] Searching namespace %s in module %s",
- current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
- i->first->GetFileSpec().GetFilename().GetCString());
-
- TypeList types;
-
- SymbolContext null_sc;
- ConstString name(tag_decl->getName().str().c_str());
-
- i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types);
-
- for (uint32_t ti = 0, te = types.GetSize();
- ti != te && !found;
- ++ti)
- {
- lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
- if (!type)
- continue;
-
- ClangASTType clang_type (type->GetClangFullType());
-
- if (!clang_type)
- continue;
-
- const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
-
- if (!tag_type)
- continue;
-
- TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
-
- if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
- found = true;
- }
- }
- }
- else
- {
- TypeList types;
-
- SymbolContext null_sc;
- ConstString name(tag_decl->getName().str().c_str());
- ClangNamespaceDecl namespace_decl;
-
- const ModuleList &module_list = m_target->GetImages();
-
- bool exact_match = false;
- module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types);
-
- for (uint32_t ti = 0, te = types.GetSize();
- ti != te && !found;
- ++ti)
- {
- lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
- if (!type)
- continue;
-
- ClangASTType clang_type (type->GetClangFullType());
-
- if (!clang_type)
- continue;
-
- const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
-
- if (!tag_type)
- continue;
-
- TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
-
- if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
- found = true;
- }
- }
- }
-
- if (log)
- {
- log->Printf(" [CTD] After:");
- ASTDumper dumper((Decl*)tag_decl);
- dumper.ToLog(log, " [CTD] ");
- }
-}
-
-void
-ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- {
- log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s",
- static_cast<void*>(m_ast_context),
- interface_decl->getName().str().c_str());
- log->Printf(" [COID] Before:");
- ASTDumper dumper((Decl*)interface_decl);
- dumper.ToLog(log, " [COID] ");
- }
-
- Decl *original_decl = NULL;
- ASTContext *original_ctx = NULL;
-
- if (m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
- {
- if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
- {
- ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
- {
- m_ast_importer->SetDeclOrigin(interface_decl, original_iface_decl);
- }
- }
- }
-
- m_ast_importer->CompleteObjCInterfaceDecl (interface_decl);
-
- if (interface_decl->getSuperClass() &&
- interface_decl->getSuperClass() != interface_decl)
- CompleteType(interface_decl->getSuperClass());
-
- if (log)
- {
- log->Printf(" [COID] After:");
- ASTDumper dumper((Decl*)interface_decl);
- dumper.ToLog(log, " [COID] ");
- }
-}
-
-clang::ObjCInterfaceDecl *
-ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl)
-{
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- return NULL;
-
- ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
- if (!language_runtime)
- return NULL;
-
- ConstString class_name(interface_decl->getNameAsString().c_str());
-
- lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
-
- if (!complete_type_sp)
- return NULL;
-
- TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType());
- lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
-
- if (!complete_opaque_type)
- return NULL;
-
- const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
- const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
-
- if (!complete_interface_type)
- return NULL;
-
- ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl());
-
- return complete_iface_decl;
-}
-
-clang::ExternalLoadResult
-ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
- bool (*predicate)(Decl::Kind),
- llvm::SmallVectorImpl<Decl*> &decls)
-{
- ClangASTMetrics::RegisterLexicalQuery();
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const Decl *context_decl = dyn_cast<Decl>(decl_context);
-
- if (!context_decl)
- return ELR_Failure;
-
- auto iter = m_active_lexical_decls.find(context_decl);
- if (iter != m_active_lexical_decls.end())
- return ELR_Failure;
- m_active_lexical_decls.insert(context_decl);
- ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl);
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- if (log)
- {
- if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate",
- current_id, static_cast<void*>(m_ast_context),
- context_named_decl->getNameAsString().c_str(),
- context_decl->getDeclKindName(),
- static_cast<const void*>(context_decl),
- (predicate ? "non-null" : "null"));
- else if(context_decl)
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate",
- current_id, static_cast<void*>(m_ast_context),
- context_decl->getDeclKindName(),
- static_cast<const void*>(context_decl),
- (predicate ? "non-null" : "null"));
- else
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate",
- current_id, static_cast<const void*>(m_ast_context),
- (predicate ? "non-null" : "null"));
- }
-
- Decl *original_decl = NULL;
- ASTContext *original_ctx = NULL;
-
- if (!m_ast_importer->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
- return ELR_Failure;
-
- if (log)
- {
- log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:",
- current_id, static_cast<void*>(original_ctx),
- static_cast<void*>(original_decl));
- ASTDumper(original_decl).ToLog(log, " ");
- }
-
- if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
- {
- ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
- {
- original_decl = complete_iface_decl;
- original_ctx = &complete_iface_decl->getASTContext();
-
- m_ast_importer->SetDeclOrigin(context_decl, original_iface_decl);
- }
- }
-
- if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
- {
- ExternalASTSource *external_source = original_ctx->getExternalSource();
-
- if (external_source)
- external_source->CompleteType (original_tag_decl);
- }
-
- const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);
-
- if (!original_decl_context)
- return ELR_Failure;
-
- for (TagDecl::decl_iterator iter = original_decl_context->decls_begin();
- iter != original_decl_context->decls_end();
- ++iter)
- {
- Decl *decl = *iter;
-
- if (!predicate || predicate(decl->getKind()))
- {
- if (log)
- {
- ASTDumper ast_dumper(decl);
- if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
- log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString());
- else
- log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
- }
-
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);
-
- if (!copied_decl)
- continue;
-
- if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl))
- {
- QualType copied_field_type = copied_field->getType();
-
- m_ast_importer->RequireCompleteType(copied_field_type);
- }
-
- decls.push_back(copied_decl);
-
- DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context);
-
- if (copied_decl->getDeclContext() != decl_context)
- {
- if (copied_decl->getDeclContext()->containsDecl(copied_decl))
- copied_decl->getDeclContext()->removeDecl(copied_decl);
- copied_decl->setDeclContext(decl_context_non_const);
- }
-
- if (!decl_context_non_const->containsDecl(copied_decl))
- decl_context_non_const->addDeclInternal(copied_decl);
- }
- }
-
- return ELR_AlreadyLoaded;
-}
-
-void
-ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
-{
- assert (m_ast_context);
-
- ClangASTMetrics::RegisterVisibleQuery();
-
- const ConstString name(context.m_decl_name.getAsString().c_str());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- if (log)
- {
- if (!context.m_decl_context)
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext",
- current_id, static_cast<void*>(m_ast_context),
- name.GetCString());
- else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'",
- current_id, static_cast<void*>(m_ast_context),
- name.GetCString(),
- context_named_decl->getNameAsString().c_str());
- else
- log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'",
- current_id, static_cast<void*>(m_ast_context),
- name.GetCString(),
- context.m_decl_context->getDeclKindName());
- }
-
- context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap);
-
- if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
- {
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
- if (log && log->GetVerbose())
- log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
- current_id, static_cast<void*>(namespace_map.get()),
- static_cast<int>(namespace_map->size()));
-
- if (!namespace_map)
- return;
-
- for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
- i != e;
- ++i)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s",
- current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
- i->first->GetFileSpec().GetFilename().GetCString());
-
- FindExternalVisibleDecls(context,
- i->first,
- i->second,
- current_id);
- }
- }
- else if (isa<ObjCInterfaceDecl>(context.m_decl_context))
- {
- FindObjCPropertyAndIvarDecls(context);
- }
- else if (!isa<TranslationUnitDecl>(context.m_decl_context))
- {
- // we shouldn't be getting FindExternalVisibleDecls calls for these
- return;
- }
- else
- {
- ClangNamespaceDecl namespace_decl;
-
- if (log)
- log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id);
-
- FindExternalVisibleDecls(context,
- lldb::ModuleSP(),
- namespace_decl,
- current_id);
- }
-
- if (!context.m_namespace_map->empty())
- {
- if (log && log->GetVerbose())
- log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)",
- current_id,
- static_cast<void*>(context.m_namespace_map.get()),
- static_cast<int>(context.m_namespace_map->size()));
-
- NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map);
-
- if (clang_namespace_decl)
- clang_namespace_decl->setHasExternalVisibleStorage();
- }
-}
-
-void
-ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
- lldb::ModuleSP module_sp,
- ClangNamespaceDecl &namespace_decl,
- unsigned int current_id)
-{
- assert (m_ast_context);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- SymbolContextList sc_list;
-
- const ConstString name(context.m_decl_name.getAsString().c_str());
-
- const char *name_unique_cstr = name.GetCString();
-
- static ConstString id_name("id");
- static ConstString Class_name("Class");
-
- if (name == id_name || name == Class_name)
- return;
-
- if (name_unique_cstr == NULL)
- return;
-
- // The ClangASTSource is not responsible for finding $-names.
- if (name_unique_cstr[0] == '$')
- return;
-
- if (module_sp && namespace_decl)
- {
- ClangNamespaceDecl found_namespace_decl;
-
- SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
-
- if (symbol_vendor)
- {
- SymbolContext null_sc;
-
- found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
-
- if (found_namespace_decl)
- {
- context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
-
- if (log)
- log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
- current_id,
- name.GetCString(),
- module_sp->GetFileSpec().GetFilename().GetCString());
- }
- }
- }
- else
- {
- const ModuleList &target_images = m_target->GetImages();
- Mutex::Locker modules_locker (target_images.GetMutex());
-
- for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
- {
- lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
-
- if (!image)
- continue;
-
- ClangNamespaceDecl found_namespace_decl;
-
- SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
- if (!symbol_vendor)
- continue;
-
- SymbolContext null_sc;
-
- found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
-
- if (found_namespace_decl)
- {
- context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
-
- if (log)
- log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
- current_id,
- name.GetCString(),
- image->GetFileSpec().GetFilename().GetCString());
- }
- }
- }
-
- do
- {
- TypeList types;
- SymbolContext null_sc;
- const bool exact_match = false;
-
- if (module_sp && namespace_decl)
- module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
- else
- m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types);
-
- bool found_a_type = false;
-
- if (types.GetSize())
- {
- lldb::TypeSP type_sp = types.GetTypeAtIndex(0);
-
- if (log)
- {
- const char *name_string = type_sp->GetName().GetCString();
-
- log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
- current_id,
- name.GetCString(),
- (name_string ? name_string : "<anonymous>"));
- }
-
- ClangASTType full_type = type_sp->GetClangFullType();
-
- ClangASTType copied_clang_type (GuardedCopyType(full_type));
-
- if (!copied_clang_type)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a type",
- current_id);
-
- break;
- }
-
- context.AddTypeDecl(copied_clang_type);
-
- found_a_type = true;
- }
-
- if (!found_a_type)
- {
- // Try the modules next.
-
- do
- {
- if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
- {
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!modules_decl_vendor->FindDecls(name,
- append,
- max_matches,
- decls))
- break;
-
- if (log)
- {
- log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules",
- current_id,
- name.GetCString());
- }
-
- clang::NamedDecl *const decl_from_modules = decls[0];
-
- if (llvm::isa<clang::TypeDecl>(decl_from_modules) ||
- llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) ||
- llvm::isa<clang::EnumConstantDecl>(decl_from_modules))
- {
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
- clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
-
- if (!copied_named_decl)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules",
- current_id);
-
- break;
- }
-
- context.AddNamedDecl(copied_named_decl);
-
- found_a_type = true;
- }
- }
- } while (0);
- }
-
- if (!found_a_type)
- {
- do
- {
- // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists.
-
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- break;
-
- ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
- if (!language_runtime)
- break;
-
- DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
-
- if (!decl_vendor)
- break;
-
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!decl_vendor->FindDecls(name,
- append,
- max_matches,
- decls))
- break;
-
- if (log)
- {
- log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime",
- current_id,
- name.GetCString());
- }
-
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]);
- clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
-
- if (!copied_named_decl)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime",
- current_id);
-
- break;
- }
-
- context.AddNamedDecl(copied_named_decl);
- }
- while(0);
- }
-
- } while(0);
-}
-
-template <class D> class TaggedASTDecl {
-public:
- TaggedASTDecl() : decl(NULL) { }
- TaggedASTDecl(D *_decl) : decl(_decl) { }
- bool IsValid() const { return (decl != NULL); }
- bool IsInvalid() const { return !IsValid(); }
- D *operator->() const { return decl; }
- D *decl;
-};
-
-template <class D2, template <class D> class TD, class D1>
-TD<D2>
-DynCast(TD<D1> source)
-{
- return TD<D2> (dyn_cast<D2>(source.decl));
-}
-
-template <class D = Decl> class DeclFromParser;
-template <class D = Decl> class DeclFromUser;
-
-template <class D> class DeclFromParser : public TaggedASTDecl<D> {
-public:
- DeclFromParser() : TaggedASTDecl<D>() { }
- DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }
-
- DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
-};
-
-template <class D> class DeclFromUser : public TaggedASTDecl<D> {
-public:
- DeclFromUser() : TaggedASTDecl<D>() { }
- DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }
-
- DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
-};
-
-template <class D>
-DeclFromUser<D>
-DeclFromParser<D>::GetOrigin(ClangASTImporter *importer)
-{
- DeclFromUser <> origin_decl;
- importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL);
- if (origin_decl.IsInvalid())
- return DeclFromUser<D>();
- return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
-}
-
-template <class D>
-DeclFromParser<D>
-DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx)
-{
- DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl));
- if (parser_generic_decl.IsInvalid())
- return DeclFromParser<D>();
- return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
-}
-
-static bool
-FindObjCMethodDeclsWithOrigin (unsigned int current_id,
- NameSearchContext &context,
- ObjCInterfaceDecl *original_interface_decl,
- clang::ASTContext *ast_context,
- ClangASTImporter *ast_importer,
- const char *log_info)
-{
- const DeclarationName &decl_name(context.m_decl_name);
- clang::ASTContext *original_ctx = &original_interface_decl->getASTContext();
-
- Selector original_selector;
-
- if (decl_name.isObjCZeroArgSelector())
- {
- IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
- original_selector = original_ctx->Selectors.getSelector(0, &ident);
- }
- else if (decl_name.isObjCOneArgSelector())
- {
- const std::string &decl_name_string = decl_name.getAsString();
- std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1);
- IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str());
- original_selector = original_ctx->Selectors.getSelector(1, &ident);
- }
- else
- {
- SmallVector<IdentifierInfo *, 4> idents;
-
- clang::Selector sel = decl_name.getObjCSelector();
-
- unsigned num_args = sel.getNumArgs();
-
- for (unsigned i = 0;
- i != num_args;
- ++i)
- {
- idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
- }
-
- original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
- }
-
- DeclarationName original_decl_name(original_selector);
-
- llvm::SmallVector<NamedDecl *, 1> methods;
-
- ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl);
-
- if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector))
- {
- methods.push_back(instance_method_decl);
- }
- else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector))
- {
- methods.push_back(class_method_decl);
- }
-
- if (methods.empty())
- {
- return false;
- }
-
- for (NamedDecl *named_decl : methods)
- {
- if (!named_decl)
- continue;
-
- ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl);
-
- if (!result_method)
- continue;
-
- Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);
-
- if (!copied_decl)
- continue;
-
- ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
- if (!copied_method_decl)
- continue;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- {
- ASTDumper dumper((Decl*)copied_method_decl);
- log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
- }
-
- context.AddNamedDecl(copied_method_decl);
- }
-
- return true;
-}
-
-void
-ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- const DeclarationName &decl_name(context.m_decl_name);
- const DeclContext *decl_ctx(context.m_decl_context);
-
- const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx);
-
- if (!interface_decl)
- return;
-
- do
- {
- Decl *original_decl = NULL;
- ASTContext *original_ctx = NULL;
-
- m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);
-
- if (!original_decl)
- break;
-
- ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl);
-
- if (FindObjCMethodDeclsWithOrigin(current_id,
- context,
- original_interface_decl,
- m_ast_context,
- m_ast_importer,
- "at origin"))
- return; // found it, no need to look any further
- } while (0);
-
- StreamString ss;
-
- if (decl_name.isObjCZeroArgSelector())
- {
- ss.Printf("%s", decl_name.getAsString().c_str());
- }
- else if (decl_name.isObjCOneArgSelector())
- {
- ss.Printf("%s", decl_name.getAsString().c_str());
- }
- else
- {
- clang::Selector sel = decl_name.getObjCSelector();
-
- for (unsigned i = 0, e = sel.getNumArgs();
- i != e;
- ++i)
- {
- llvm::StringRef r = sel.getNameForSlot(i);
- ss.Printf("%s:", r.str().c_str());
- }
- }
- ss.Flush();
-
- if (strstr(ss.GetData(), "$__lldb"))
- return; // we don't need any results
-
- ConstString selector_name(ss.GetData());
-
- if (log)
- log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]",
- current_id, static_cast<void*>(m_ast_context),
- interface_decl->getNameAsString().c_str(),
- selector_name.AsCString());
- SymbolContextList sc_list;
-
- const bool include_symbols = false;
- const bool include_inlines = false;
- const bool append = false;
-
- std::string interface_name = interface_decl->getNameAsString();
-
- do
- {
- StreamString ms;
- ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString());
- ms.Flush();
- ConstString instance_method_name(ms.GetData());
-
- m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
-
- if (sc_list.GetSize())
- break;
-
- ms.Clear();
- ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString());
- ms.Flush();
- ConstString class_method_name(ms.GetData());
-
- m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
-
- if (sc_list.GetSize())
- break;
-
- // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in
- // categories on the desired class.
-
- SymbolContextList candidate_sc_list;
-
- m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list);
-
- for (uint32_t ci = 0, ce = candidate_sc_list.GetSize();
- ci != ce;
- ++ci)
- {
- SymbolContext candidate_sc;
-
- if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc))
- continue;
-
- if (!candidate_sc.function)
- continue;
-
- const char *candidate_name = candidate_sc.function->GetName().AsCString();
-
- const char *cursor = candidate_name;
-
- if (*cursor != '+' && *cursor != '-')
- continue;
-
- ++cursor;
-
- if (*cursor != '[')
- continue;
-
- ++cursor;
-
- size_t interface_len = interface_name.length();
-
- if (strncmp(cursor, interface_name.c_str(), interface_len))
- continue;
-
- cursor += interface_len;
-
- if (*cursor == ' ' || *cursor == '(')
- sc_list.Append(candidate_sc);
- }
- }
- while (0);
-
- if (sc_list.GetSize())
- {
- // We found a good function symbol. Use that.
-
- for (uint32_t i = 0, e = sc_list.GetSize();
- i != e;
- ++i)
- {
- SymbolContext sc;
-
- if (!sc_list.GetContextAtIndex(i, sc))
- continue;
-
- if (!sc.function)
- continue;
-
- DeclContext *function_ctx = sc.function->GetClangDeclContext();
-
- if (!function_ctx)
- continue;
-
- ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);
-
- if (!method_decl)
- continue;
-
- ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();
-
- if (!found_interface_decl)
- continue;
-
- if (found_interface_decl->getName() == interface_decl->getName())
- {
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
-
- if (!copied_decl)
- continue;
-
- ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
- if (!copied_method_decl)
- continue;
-
- if (log)
- {
- ASTDumper dumper((Decl*)copied_method_decl);
- log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString());
- }
-
- context.AddNamedDecl(copied_method_decl);
- }
- }
-
- return;
- }
-
- // Try the debug information.
-
- do
- {
- ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl));
-
- if (!complete_interface_decl)
- break;
-
- // We found the complete interface. The runtime never needs to be queried in this scenario.
-
- DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
-
- if (complete_interface_decl == interface_decl)
- break; // already checked this one
-
- if (log)
- log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id, static_cast<void*>(complete_interface_decl),
- static_cast<void*>(&complete_iface_decl->getASTContext()));
-
- FindObjCMethodDeclsWithOrigin(current_id,
- context,
- complete_interface_decl,
- m_ast_context,
- m_ast_importer,
- "in debug info");
-
- return;
- }
- while (0);
-
- do
- {
- // Check the modules only if the debug information didn't have a complete interface.
-
- if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
- {
- ConstString interface_name(interface_decl->getNameAsString().c_str());
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!modules_decl_vendor->FindDecls(interface_name,
- append,
- max_matches,
- decls))
- break;
-
- ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast<ObjCInterfaceDecl>(decls[0]);
-
- if (!interface_decl_from_modules)
- break;
-
- if (FindObjCMethodDeclsWithOrigin(current_id,
- context,
- interface_decl_from_modules,
- m_ast_context,
- m_ast_importer,
- "in modules"))
- return;
- }
- }
- while (0);
-
- do
- {
- // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere.
-
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- break;
-
- ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
- if (!language_runtime)
- break;
-
- DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
-
- if (!decl_vendor)
- break;
-
- ConstString interface_name(interface_decl->getNameAsString().c_str());
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!decl_vendor->FindDecls(interface_name,
- append,
- max_matches,
- decls))
- break;
-
- ObjCInterfaceDecl *runtime_interface_decl = dyn_cast<ObjCInterfaceDecl>(decls[0]);
-
- if (!runtime_interface_decl)
- break;
-
- FindObjCMethodDeclsWithOrigin(current_id,
- context,
- runtime_interface_decl,
- m_ast_context,
- m_ast_importer,
- "in runtime");
- }
- while(0);
-}
-
-static bool
-FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
- NameSearchContext &context,
- clang::ASTContext &ast_context,
- ClangASTImporter *ast_importer,
- DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (origin_iface_decl.IsInvalid())
- return false;
-
- std::string name_str = context.m_decl_name.getAsString();
- StringRef name(name_str.c_str());
- IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
-
- DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
-
- bool found = false;
-
- if (origin_property_decl.IsValid())
- {
- DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context));
- if (parser_property_decl.IsValid())
- {
- if (log)
- {
- ASTDumper dumper((Decl*)parser_property_decl.decl);
- log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
- }
-
- context.AddNamedDecl(parser_property_decl.decl);
- found = true;
- }
- }
-
- DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
-
- if (origin_ivar_decl.IsValid())
- {
- DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context));
- if (parser_ivar_decl.IsValid())
- {
- if (log)
- {
- ASTDumper dumper((Decl*)parser_ivar_decl.decl);
- log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
- }
-
- context.AddNamedDecl(parser_ivar_decl.decl);
- found = true;
- }
- }
-
- return found;
-}
-
-void
-ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
- DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
-
- ConstString class_name(parser_iface_decl->getNameAsString().c_str());
-
- if (log)
- log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
- current_id, static_cast<void*>(m_ast_context),
- parser_iface_decl->getNameAsString().c_str(),
- context.m_decl_name.getAsString().c_str());
-
- if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
- origin_iface_decl))
- return;
-
- if (log)
- log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...",
- current_id, static_cast<const void*>(origin_iface_decl.decl),
- static_cast<void*>(&origin_iface_decl->getASTContext()));
-
- SymbolContext null_sc;
- TypeList type_list;
-
- do
- {
- ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl));
-
- if (!complete_interface_decl)
- break;
-
- // We found the complete interface. The runtime never needs to be queried in this scenario.
-
- DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
-
- if (complete_iface_decl.decl == origin_iface_decl.decl)
- break; // already checked this one
-
- if (log)
- log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id,
- static_cast<const void*>(complete_iface_decl.decl),
- static_cast<void*>(&complete_iface_decl->getASTContext()));
-
- FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
- complete_iface_decl);
-
- return;
- }
- while(0);
-
- do
- {
- // Check the modules only if the debug information didn't have a complete interface.
-
- ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
-
- if (!modules_decl_vendor)
- break;
-
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!modules_decl_vendor->FindDecls(class_name,
- append,
- max_matches,
- decls))
- break;
-
- DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules(dyn_cast<ObjCInterfaceDecl>(decls[0]));
-
- if (!interface_decl_from_modules.IsValid())
- break;
-
- if (log)
- log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id,
- static_cast<const void*>(interface_decl_from_modules.decl),
- static_cast<void*>(&interface_decl_from_modules->getASTContext()));
-
- if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
- interface_decl_from_modules))
- return;
- }
- while(0);
-
- do
- {
- // Check the runtime only if the debug information didn't have a complete interface
- // and nothing was in the modules.
-
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- return;
-
- ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
-
- if (!language_runtime)
- return;
-
- DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
-
- if (!decl_vendor)
- break;
-
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!decl_vendor->FindDecls(class_name,
- append,
- max_matches,
- decls))
- break;
-
- DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime(dyn_cast<ObjCInterfaceDecl>(decls[0]));
-
- if (!interface_decl_from_runtime.IsValid())
- break;
-
- if (log)
- log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id,
- static_cast<const void*>(interface_decl_from_runtime.decl),
- static_cast<void*>(&interface_decl_from_runtime->getASTContext()));
-
- if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
- interface_decl_from_runtime))
- return;
- }
- while(0);
-}
-
-typedef llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsetMap;
-typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap;
-
-template <class D, class O>
-static bool
-ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map,
- ClangASTImporter *importer, ASTContext &dest_ctx)
-{
- // When importing fields into a new record, clang has a hard requirement that
- // fields be imported in field offset order. Since they are stored in a DenseMap
- // with a pointer as the key type, this means we cannot simply iterate over the
- // map, as the order will be non-deterministic. Instead we have to sort by the offset
- // and then insert in sorted order.
- typedef llvm::DenseMap<const D *, O> MapType;
- typedef typename MapType::value_type PairType;
- std::vector<PairType> sorted_items;
- sorted_items.reserve(source_map.size());
- sorted_items.assign(source_map.begin(), source_map.end());
- std::sort(sorted_items.begin(), sorted_items.end(),
- [](const PairType &lhs, const PairType &rhs)
- {
- return lhs.second < rhs.second;
- });
-
- for (const auto &item : sorted_items)
- {
- DeclFromUser<D> user_decl(const_cast<D *>(item.first));
- DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx));
- if (parser_decl.IsInvalid())
- return false;
- destination_map.insert(std::pair<const D *, O>(parser_decl.decl, item.second));
- }
-
- return true;
-}
-
-template <bool IsVirtual>
-bool
-ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser<const CXXRecordDecl> &record,
- BaseOffsetMap &base_offsets)
-{
- for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
- be = (IsVirtual ? record->vbases_end() : record->bases_end());
- bi != be; ++bi)
- {
- if (!IsVirtual && bi->isVirtual())
- continue;
-
- const clang::Type *origin_base_type = bi->getType().getTypePtr();
- const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();
-
- if (!origin_base_record_type)
- return false;
-
- DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());
-
- if (origin_base_record.IsInvalid())
- return false;
-
- DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));
-
- if (origin_base_cxx_record.IsInvalid())
- return false;
-
- CharUnits base_offset;
-
- if (IsVirtual)
- base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
- else
- base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);
-
- base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
- }
-
- return true;
-}
-
-bool
-ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment,
- FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets,
- BaseOffsetMap &virtual_base_offsets)
-{
- ClangASTMetrics::RegisterRecordLayout();
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']",
- current_id, static_cast<void*>(m_ast_context),
- static_cast<const void*>(record),
- record->getNameAsString().c_str());
-
- DeclFromParser <const RecordDecl> parser_record(record);
- DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
-
- if (origin_record.IsInvalid())
- return false;
-
- FieldOffsetMap origin_field_offsets;
- BaseOffsetMap origin_base_offsets;
- BaseOffsetMap origin_virtual_base_offsets;
-
- ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl));
-
- if (!origin_record.decl->getDefinition())
- return false;
-
- const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
-
- int field_idx = 0, field_count = record_layout.getFieldCount();
-
- for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi)
- {
- if (field_idx >= field_count)
- return false; // Layout didn't go well. Bail out.
-
- uint64_t field_offset = record_layout.getFieldOffset(field_idx);
-
- origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));
-
- field_idx++;
- }
-
- ASTContext &parser_ast_context(record->getASTContext());
-
- DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));
-
- if (origin_cxx_record.IsValid())
- {
- if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) ||
- !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets))
- return false;
- }
-
- if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) ||
- !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
- !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
- return false;
-
- size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
- alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();
-
- if (log)
- {
- log->Printf("LRT[%u] returned:", current_id);
- log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id,
- static_cast<const void*>(origin_record.decl));
- log->Printf("LRT[%u] Size = %" PRId64, current_id, size);
- log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment);
- log->Printf("LRT[%u] Fields:", current_id);
- for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end();
- fi != fe;
- ++fi)
- {
- log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id,
- static_cast<void *>(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]);
- }
- DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
- if (parser_cxx_record.IsValid())
- {
- log->Printf("LRT[%u] Bases:", current_id);
- for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end();
- bi != be;
- ++bi)
- {
- bool is_virtual = bi->isVirtual();
-
- QualType base_type = bi->getType();
- const RecordType *base_record_type = base_type->getAs<RecordType>();
- DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
- DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);
-
- log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id,
- (is_virtual ? "Virtual " : ""), static_cast<void *>(base_cxx_record.decl),
- base_cxx_record.decl->getNameAsString().c_str(),
- (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity()
- : base_offsets[base_cxx_record.decl].getQuantity()));
- }
- }
- else
- {
- log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id);
- }
- }
-
- return true;
-}
-
-void
-ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map,
- const ConstString &name,
- ClangASTImporter::NamespaceMapSP &parent_map) const
-{
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- {
- if (parent_map && parent_map->size())
- log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
- current_id, static_cast<void*>(m_ast_context),
- name.GetCString(),
- parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str());
- else
- log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
- current_id, static_cast<void*>(m_ast_context),
- name.GetCString());
- }
-
- if (parent_map)
- {
- for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end();
- i != e;
- ++i)
- {
- ClangNamespaceDecl found_namespace_decl;
-
- lldb::ModuleSP module_sp = i->first;
- ClangNamespaceDecl module_parent_namespace_decl = i->second;
-
- SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
-
- if (!symbol_vendor)
- continue;
-
- SymbolContext null_sc;
-
- found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl);
-
- if (!found_namespace_decl)
- continue;
-
- namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
-
- if (log)
- log->Printf(" CMN[%u] Found namespace %s in module %s",
- current_id,
- name.GetCString(),
- module_sp->GetFileSpec().GetFilename().GetCString());
- }
- }
- else
- {
- const ModuleList &target_images = m_target->GetImages();
- Mutex::Locker modules_locker(target_images.GetMutex());
-
- ClangNamespaceDecl null_namespace_decl;
-
- for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
- {
- lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
-
- if (!image)
- continue;
-
- ClangNamespaceDecl found_namespace_decl;
-
- SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
- if (!symbol_vendor)
- continue;
-
- SymbolContext null_sc;
-
- found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl);
-
- if (!found_namespace_decl)
- continue;
-
- namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
-
- if (log)
- log->Printf(" CMN[%u] Found namespace %s in module %s",
- current_id,
- name.GetCString(),
- image->GetFileSpec().GetFilename().GetCString());
- }
- }
-}
-
-NamespaceDecl *
-ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls)
-{
- if (!namespace_decls)
- return NULL;
-
- const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second;
-
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());
-
- if (!copied_decl)
- return NULL;
-
- NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);
-
- if (!copied_namespace_decl)
- return NULL;
-
- context.m_decls.push_back(copied_namespace_decl);
-
- m_ast_importer->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);
-
- return dyn_cast<NamespaceDecl>(copied_decl);
-}
-
-ClangASTType
-ClangASTSource::GuardedCopyType (const ClangASTType &src_type)
-{
- ClangASTMetrics::RegisterLLDBImport();
-
- SetImportInProgress(true);
-
- QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType());
-
- SetImportInProgress(false);
-
- if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull())
- // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types
- // on occasion.
- return ClangASTType();
-
- return ClangASTType(m_ast_context, copied_qual_type);
-}
-
-clang::NamedDecl *
-NameSearchContext::AddVarDecl(const ClangASTType &type)
-{
- assert (type && "Type for variable must be valid!");
-
- if (!type.IsValid())
- return NULL;
-
- IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
-
- clang::ASTContext *ast = type.GetASTContext();
-
- clang::NamedDecl *Decl = VarDecl::Create(*ast,
- const_cast<DeclContext*>(m_decl_context),
- SourceLocation(),
- SourceLocation(),
- ii,
- type.GetQualType(),
- 0,
- SC_Static);
- m_decls.push_back(Decl);
-
- return Decl;
-}
-
-clang::NamedDecl *
-NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c)
-{
- assert (type && "Type for variable must be valid!");
-
- if (!type.IsValid())
- return NULL;
-
- if (m_function_types.count(type))
- return NULL;
-
- m_function_types.insert(type);
-
- QualType qual_type (type.GetQualType());
-
- clang::ASTContext *ast = type.GetASTContext();
-
- const bool isInlineSpecified = false;
- const bool hasWrittenPrototype = true;
- const bool isConstexprSpecified = false;
-
- clang::DeclContext *context = const_cast<DeclContext*>(m_decl_context);
-
- if (extern_c) {
- context = LinkageSpecDecl::Create(*ast,
- context,
- SourceLocation(),
- SourceLocation(),
- clang::LinkageSpecDecl::LanguageIDs::lang_c,
- false);
- }
-
- clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast,
- context,
- SourceLocation(),
- SourceLocation(),
- m_decl_name.getAsIdentifierInfo(),
- qual_type,
- NULL,
- SC_Extern,
- isInlineSpecified,
- hasWrittenPrototype,
- isConstexprSpecified);
-
- // We have to do more than just synthesize the FunctionDecl. We have to
- // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
- // this, we raid the function's FunctionProtoType for types.
-
- const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>();
-
- if (func_proto_type)
- {
- unsigned NumArgs = func_proto_type->getNumParams();
- unsigned ArgIndex;
-
- SmallVector<ParmVarDecl *, 5> parm_var_decls;
-
- for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex)
- {
- QualType arg_qual_type (func_proto_type->getParamType(ArgIndex));
-
- parm_var_decls.push_back(ParmVarDecl::Create (*ast,
- const_cast<DeclContext*>(context),
- SourceLocation(),
- SourceLocation(),
- NULL,
- arg_qual_type,
- NULL,
- SC_Static,
- NULL));
- }
-
- func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls));
- }
- else
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("Function type wasn't a FunctionProtoType");
- }
-
- m_decls.push_back(func_decl);
-
- return func_decl;
-}
-
-clang::NamedDecl *
-NameSearchContext::AddGenericFunDecl()
-{
- FunctionProtoType::ExtProtoInfo proto_info;
-
- proto_info.Variadic = true;
-
- QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result
- ArrayRef<QualType>(), // argument types
- proto_info));
-
- return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type), true);
-}
-
-clang::NamedDecl *
-NameSearchContext::AddTypeDecl(const ClangASTType &clang_type)
-{
- if (clang_type)
- {
- QualType qual_type = clang_type.GetQualType();
-
- if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type))
- {
- TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
-
- m_decls.push_back(typedef_name_decl);
-
- return (NamedDecl*)typedef_name_decl;
- }
- else if (const TagType *tag_type = qual_type->getAs<TagType>())
- {
- TagDecl *tag_decl = tag_type->getDecl();
-
- m_decls.push_back(tag_decl);
-
- return tag_decl;
- }
- else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>())
- {
- ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
-
- m_decls.push_back((NamedDecl*)interface_decl);
-
- return (NamedDecl*)interface_decl;
- }
- }
- return NULL;
-}
-
-void
-NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result)
-{
- for (clang::NamedDecl *decl : result)
- m_decls.push_back (decl);
-}
-
-void
-NameSearchContext::AddNamedDecl (clang::NamedDecl *decl)
-{
- m_decls.push_back (decl);
-}
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
deleted file mode 100644
index 2c66a0a..0000000
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ /dev/null
@@ -1,2171 +0,0 @@
-//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclarationName.h"
-#include "clang/AST/Decl.h"
-#include "lldb/lldb-private.h"
-#include "lldb/Core/Address.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/Materializer.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Symbol/Variable.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace clang;
-
-ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, ExecutionContext &exe_ctx) :
- ClangASTSource (exe_ctx.GetTargetSP()),
- m_found_entities (),
- m_struct_members (),
- m_keep_result_in_memory (keep_result_in_memory),
- m_parser_vars (),
- m_struct_vars ()
-{
- EnableStructVars();
-}
-
-ClangExpressionDeclMap::~ClangExpressionDeclMap()
-{
- // Note: The model is now that the parser's AST context and all associated
- // data does not vanish until the expression has been executed. This means
- // that valuable lookup data (like namespaces) doesn't vanish, but
-
- DidParse();
- DisableStructVars();
-}
-
-bool
-ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
- Materializer *materializer)
-{
- ClangASTMetrics::ClearLocalCounters();
-
- EnableParserVars();
- m_parser_vars->m_exe_ctx = exe_ctx;
-
- Target *target = exe_ctx.GetTargetPtr();
- if (exe_ctx.GetFramePtr())
- m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything);
- else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0))
- m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything);
- else if (exe_ctx.GetProcessPtr())
- {
- m_parser_vars->m_sym_ctx.Clear(true);
- m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
- }
- else if (target)
- {
- m_parser_vars->m_sym_ctx.Clear(true);
- m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
- }
-
- if (target)
- {
- m_parser_vars->m_persistent_vars = &target->GetPersistentVariables();
-
- if (!target->GetScratchClangASTContext())
- return false;
- }
-
- m_parser_vars->m_target_info = GetTargetInfo();
- m_parser_vars->m_materializer = materializer;
-
- return true;
-}
-
-void
-ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen)
-{
- assert(m_parser_vars);
- m_parser_vars->m_code_gen = code_gen;
-}
-
-void
-ClangExpressionDeclMap::DidParse()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- ClangASTMetrics::DumpCounters(log);
-
- if (m_parser_vars.get())
- {
- for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
- entity_index < num_entities;
- ++entity_index)
- {
- ClangExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index));
- if (var_sp)
- var_sp->DisableParserVars(GetParserID());
- }
-
- for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize();
- pvar_index < num_pvars;
- ++pvar_index)
- {
- ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
- if (pvar_sp)
- pvar_sp->DisableParserVars(GetParserID());
- }
-
- DisableParserVars();
- }
-}
-
-// Interface for IRForTarget
-
-ClangExpressionDeclMap::TargetInfo
-ClangExpressionDeclMap::GetTargetInfo()
-{
- assert (m_parser_vars.get());
-
- TargetInfo ret;
-
- ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- ret.byte_order = process->GetByteOrder();
- ret.address_byte_size = process->GetAddressByteSize();
- }
- else
- {
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- ret.byte_order = target->GetArchitecture().GetByteOrder();
- ret.address_byte_size = target->GetArchitecture().GetAddressByteSize();
- }
- }
-
- return ret;
-}
-
-bool
-ClangExpressionDeclMap::AddPersistentVariable
-(
- const NamedDecl *decl,
- const ConstString &name,
- TypeFromParser parser_type,
- bool is_result,
- bool is_lvalue
-)
-{
- assert (m_parser_vars.get());
-
- if (m_parser_vars->m_materializer && is_result)
- {
- Error err;
-
- ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
- Target *target = exe_ctx.GetTargetPtr();
- if (target == NULL)
- return false;
-
- ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
-
- TypeFromUser user_type(m_ast_importer->DeportType(context,
- parser_type.GetASTContext(),
- parser_type.GetOpaqueQualType()),
- context);
-
- uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err);
-
- ClangExpressionVariableSP var_sp = m_found_entities.CreateVariable(exe_ctx.GetBestExecutionContextScope(),
- name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size);
-
- if (!var_sp)
- return false;
-
- var_sp->EnableParserVars(GetParserID());
-
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
-
- parser_vars->m_named_decl = decl;
- parser_vars->m_parser_type = parser_type;
-
- var_sp->EnableJITVars(GetParserID());
-
- ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
-
- jit_vars->m_offset = offset;
-
- return true;
- }
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
- Target *target = exe_ctx.GetTargetPtr();
- if (target == NULL)
- return false;
-
- ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
-
- TypeFromUser user_type(m_ast_importer->DeportType(context,
- parser_type.GetASTContext(),
- parser_type.GetOpaqueQualType()),
- context);
-
- if (!user_type.GetOpaqueQualType())
- {
- if (log)
- log->Printf("Persistent variable's type wasn't copied successfully");
- return false;
- }
-
- if (!m_parser_vars->m_target_info.IsValid())
- return false;
-
- ClangExpressionVariableSP var_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (),
- name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size);
-
- if (!var_sp)
- return false;
-
- var_sp->m_frozen_sp->SetHasCompleteType();
-
- if (is_result)
- var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
- else
- var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
-
- if (is_lvalue)
- {
- var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
- }
- else
- {
- var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
- var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
- }
-
- if (m_keep_result_in_memory)
- {
- var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
- }
-
- if (log)
- log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
-
- var_sp->EnableParserVars(GetParserID());
-
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
-
- parser_vars->m_named_decl = decl;
- parser_vars->m_parser_type = parser_type;
-
- return true;
-}
-
-bool
-ClangExpressionDeclMap::AddValueToStruct
-(
- const NamedDecl *decl,
- const ConstString &name,
- llvm::Value *value,
- size_t size,
- lldb::offset_t alignment
-)
-{
- assert (m_struct_vars.get());
- assert (m_parser_vars.get());
-
- bool is_persistent_variable = false;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- m_struct_vars->m_struct_laid_out = false;
-
- if (m_struct_members.GetVariable(decl, GetParserID()))
- return true;
-
- ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl, GetParserID()));
-
- if (!var_sp)
- {
- var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl, GetParserID());
- is_persistent_variable = true;
- }
-
- if (!var_sp)
- return false;
-
- if (log)
- log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure",
- static_cast<const void*>(decl), name.GetCString(),
- var_sp->GetName().GetCString());
-
- // We know entity->m_parser_vars is valid because we used a parser variable
- // to find it
-
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
-
- parser_vars->m_llvm_value = value;
-
- if (ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()))
- {
- // We already laid this out; do not touch
-
- if (log)
- log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset);
- }
-
- var_sp->EnableJITVars(GetParserID());
-
- ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
-
- jit_vars->m_alignment = alignment;
- jit_vars->m_size = size;
-
- m_struct_members.AddVariable(var_sp);
-
- if (m_parser_vars->m_materializer)
- {
- uint32_t offset = 0;
-
- Error err;
-
- if (is_persistent_variable)
- {
- offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, err);
- }
- else
- {
- if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym)
- offset = m_parser_vars->m_materializer->AddSymbol(*sym, err);
- else if (const RegisterInfo *reg_info = var_sp->GetRegisterInfo())
- offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err);
- else if (parser_vars->m_lldb_var)
- offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err);
- }
-
- if (!err.Success())
- return false;
-
- if (log)
- log->Printf("Placed at 0x%llx", (unsigned long long)offset);
-
- jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this.
- }
-
- return true;
-}
-
-bool
-ClangExpressionDeclMap::DoStructLayout ()
-{
- assert (m_struct_vars.get());
-
- if (m_struct_vars->m_struct_laid_out)
- return true;
-
- if (!m_parser_vars->m_materializer)
- return false;
-
- m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment();
- m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize();
- m_struct_vars->m_struct_laid_out = true;
- return true;
-}
-
-bool ClangExpressionDeclMap::GetStructInfo
-(
- uint32_t &num_elements,
- size_t &size,
- lldb::offset_t &alignment
-)
-{
- assert (m_struct_vars.get());
-
- if (!m_struct_vars->m_struct_laid_out)
- return false;
-
- num_elements = m_struct_members.GetSize();
- size = m_struct_vars->m_struct_size;
- alignment = m_struct_vars->m_struct_alignment;
-
- return true;
-}
-
-bool
-ClangExpressionDeclMap::GetStructElement
-(
- const NamedDecl *&decl,
- llvm::Value *&value,
- lldb::offset_t &offset,
- ConstString &name,
- uint32_t index
-)
-{
- assert (m_struct_vars.get());
-
- if (!m_struct_vars->m_struct_laid_out)
- return false;
-
- if (index >= m_struct_members.GetSize())
- return false;
-
- ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
-
- if (!member_sp)
- return false;
-
- ClangExpressionVariable::ParserVars *parser_vars = member_sp->GetParserVars(GetParserID());
- ClangExpressionVariable::JITVars *jit_vars = member_sp->GetJITVars(GetParserID());
-
- if (!parser_vars ||
- !jit_vars ||
- !member_sp->GetValueObject())
- return false;
-
- decl = parser_vars->m_named_decl;
- value = parser_vars->m_llvm_value;
- offset = jit_vars->m_offset;
- name = member_sp->GetName();
-
- return true;
-}
-
-bool
-ClangExpressionDeclMap::GetFunctionInfo
-(
- const NamedDecl *decl,
- uint64_t &ptr
-)
-{
- ClangExpressionVariableSP entity_sp(m_found_entities.GetVariable(decl, GetParserID()));
-
- if (!entity_sp)
- return false;
-
- // We know m_parser_vars is valid since we searched for the variable by
- // its NamedDecl
-
- ClangExpressionVariable::ParserVars *parser_vars = entity_sp->GetParserVars(GetParserID());
-
- ptr = parser_vars->m_lldb_value.GetScalar().ULongLong();
-
- return true;
-}
-
-static void
-FindCodeSymbolInContext
-(
- const ConstString &name,
- SymbolContext &sym_ctx,
- SymbolContextList &sc_list
-)
-{
- sc_list.Clear();
- SymbolContextList temp_sc_list;
- if (sym_ctx.module_sp)
- sym_ctx.module_sp->FindFunctions(name,
- NULL,
- eFunctionNameTypeAuto,
- true, // include_symbols
- false, // include_inlines
- true, // append
- temp_sc_list);
- if (temp_sc_list.GetSize() == 0)
- {
- if (sym_ctx.target_sp)
- sym_ctx.target_sp->GetImages().FindFunctions(name,
- eFunctionNameTypeAuto,
- true, // include_symbols
- false, // include_inlines
- true, // append
- temp_sc_list);
- }
-
- SymbolContextList internal_symbol_sc_list;
- unsigned temp_sc_list_size = temp_sc_list.GetSize();
- for (unsigned i = 0; i < temp_sc_list_size; i++)
- {
- SymbolContext sc;
- temp_sc_list.GetContextAtIndex(i, sc);
- if (sc.function)
- {
- sc_list.Append(sc);
- }
- else if (sc.symbol)
- {
- if (sc.symbol->IsExternal())
- {
- sc_list.Append(sc);
- }
- else
- {
- internal_symbol_sc_list.Append(sc);
- }
- }
- }
-
- // If we had internal symbols and we didn't find any external symbols or
- // functions in debug info, then fallback to the internal symbols
- if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize())
- {
- sc_list = internal_symbol_sc_list;
- }
-}
-
-bool
-ClangExpressionDeclMap::GetFunctionAddress
-(
- const ConstString &name,
- uint64_t &func_addr
-)
-{
- assert (m_parser_vars.get());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
- Target *target = exe_ctx.GetTargetPtr();
- // Back out in all cases where we're not fully initialized
- if (target == NULL)
- return false;
- if (!m_parser_vars->m_sym_ctx.target_sp)
- return false;
-
- SymbolContextList sc_list;
-
- FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list);
-
- uint32_t sc_list_size = sc_list.GetSize();
-
- if (sc_list_size == 0)
- {
- // We occasionally get debug information in which a const function is reported
- // as non-const, so the mangled name is wrong. This is a hack to compensate.
-
- if (!strncmp(name.GetCString(), "_ZN", 3) &&
- strncmp(name.GetCString(), "_ZNK", 4))
- {
- std::string fixed_scratch("_ZNK");
- fixed_scratch.append(name.GetCString() + 3);
- ConstString fixed_name(fixed_scratch.c_str());
-
- if (log)
- log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString());
-
- FindCodeSymbolInContext(fixed_name, m_parser_vars->m_sym_ctx, sc_list);
- sc_list_size = sc_list.GetSize();
- }
- }
-
- lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS;
-
- for (uint32_t i=0; i<sc_list_size; ++i)
- {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(i, sym_ctx);
-
-
- lldb::addr_t callable_load_addr = LLDB_INVALID_ADDRESS;
-
- if (sym_ctx.function)
- {
- const Address func_so_addr = sym_ctx.function->GetAddressRange().GetBaseAddress();
- if (func_so_addr.IsValid())
- {
- callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false);
- }
- }
- else if (sym_ctx.symbol)
- {
- if (sym_ctx.symbol->IsExternal())
- callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target);
- else
- {
- if (intern_callable_load_addr == LLDB_INVALID_ADDRESS)
- intern_callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target);
- }
- }
-
- if (callable_load_addr != LLDB_INVALID_ADDRESS)
- {
- func_addr = callable_load_addr;
- return true;
- }
- }
-
- // See if we found an internal symbol
- if (intern_callable_load_addr != LLDB_INVALID_ADDRESS)
- {
- func_addr = intern_callable_load_addr;
- return true;
- }
-
- return false;
-}
-
-addr_t
-ClangExpressionDeclMap::GetSymbolAddress (Target &target,
- Process *process,
- const ConstString &name,
- lldb::SymbolType symbol_type,
- lldb_private::Module *module)
-{
- SymbolContextList sc_list;
-
- if (module)
- module->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
- else
- target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list);
-
- const uint32_t num_matches = sc_list.GetSize();
- addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
-
- for (uint32_t i=0; i<num_matches && (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); i++)
- {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(i, sym_ctx);
-
- const Address sym_address = sym_ctx.symbol->GetAddress();
-
- if (!sym_address.IsValid())
- continue;
-
- switch (sym_ctx.symbol->GetType())
- {
- case eSymbolTypeCode:
- case eSymbolTypeTrampoline:
- symbol_load_addr = sym_address.GetCallableLoadAddress (&target);
- break;
-
- case eSymbolTypeResolver:
- symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true);
- break;
-
- case eSymbolTypeReExported:
- {
- ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName();
- if (reexport_name)
- {
- ModuleSP reexport_module_sp;
- ModuleSpec reexport_module_spec;
- reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary();
- if (reexport_module_spec.GetPlatformFileSpec())
- {
- reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
- if (!reexport_module_sp)
- {
- reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
- reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
- }
- }
- symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get());
- }
- }
- break;
-
- case eSymbolTypeData:
- case eSymbolTypeRuntime:
- case eSymbolTypeVariable:
- case eSymbolTypeLocal:
- case eSymbolTypeParam:
- case eSymbolTypeInvalid:
- case eSymbolTypeAbsolute:
- case eSymbolTypeException:
- case eSymbolTypeSourceFile:
- case eSymbolTypeHeaderFile:
- case eSymbolTypeObjectFile:
- case eSymbolTypeCommonBlock:
- case eSymbolTypeBlock:
- case eSymbolTypeVariableType:
- case eSymbolTypeLineEntry:
- case eSymbolTypeLineHeader:
- case eSymbolTypeScopeBegin:
- case eSymbolTypeScopeEnd:
- case eSymbolTypeAdditional:
- case eSymbolTypeCompiler:
- case eSymbolTypeInstrumentation:
- case eSymbolTypeUndefined:
- case eSymbolTypeObjCClass:
- case eSymbolTypeObjCMetaClass:
- case eSymbolTypeObjCIVar:
- symbol_load_addr = sym_address.GetLoadAddress (&target);
- break;
- }
- }
-
- if (symbol_load_addr == LLDB_INVALID_ADDRESS && process)
- {
- ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
-
- if (runtime)
- {
- symbol_load_addr = runtime->LookupRuntimeSymbol(name);
- }
- }
-
- return symbol_load_addr;
-}
-
-addr_t
-ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type)
-{
- assert (m_parser_vars.get());
-
- if (!m_parser_vars->m_exe_ctx.GetTargetPtr())
- return false;
-
- return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type);
-}
-
-const Symbol *
-ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
- const ConstString &name,
- lldb_private::Module *module)
-{
- SymbolContextList sc_list;
-
- if (module)
- module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
- else
- target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
-
- const uint32_t matches = sc_list.GetSize();
- for (uint32_t i=0; i<matches; ++i)
- {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(i, sym_ctx);
- if (sym_ctx.symbol)
- {
- const Symbol *symbol = sym_ctx.symbol;
- const Address sym_address = symbol->GetAddress();
-
- if (sym_address.IsValid())
- {
- switch (symbol->GetType())
- {
- case eSymbolTypeData:
- case eSymbolTypeRuntime:
- case eSymbolTypeAbsolute:
- case eSymbolTypeObjCClass:
- case eSymbolTypeObjCMetaClass:
- case eSymbolTypeObjCIVar:
- if (symbol->GetDemangledNameIsSynthesized())
- {
- // If the demangled name was synthesized, then don't use it
- // for expressions. Only let the symbol match if the mangled
- // named matches for these symbols.
- if (symbol->GetMangled().GetMangledName() != name)
- break;
- }
- return symbol;
-
- case eSymbolTypeReExported:
- {
- ConstString reexport_name = symbol->GetReExportedSymbolName();
- if (reexport_name)
- {
- ModuleSP reexport_module_sp;
- ModuleSpec reexport_module_spec;
- reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary();
- if (reexport_module_spec.GetPlatformFileSpec())
- {
- reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
- if (!reexport_module_sp)
- {
- reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
- reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
- }
- }
- // Don't allow us to try and resolve a re-exported symbol if it is the same
- // as the current symbol
- if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get())
- return NULL;
-
- return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get());
- }
- }
- break;
-
- case eSymbolTypeCode: // We already lookup functions elsewhere
- case eSymbolTypeVariable:
- case eSymbolTypeLocal:
- case eSymbolTypeParam:
- case eSymbolTypeTrampoline:
- case eSymbolTypeInvalid:
- case eSymbolTypeException:
- case eSymbolTypeSourceFile:
- case eSymbolTypeHeaderFile:
- case eSymbolTypeObjectFile:
- case eSymbolTypeCommonBlock:
- case eSymbolTypeBlock:
- case eSymbolTypeVariableType:
- case eSymbolTypeLineEntry:
- case eSymbolTypeLineHeader:
- case eSymbolTypeScopeBegin:
- case eSymbolTypeScopeEnd:
- case eSymbolTypeAdditional:
- case eSymbolTypeCompiler:
- case eSymbolTypeInstrumentation:
- case eSymbolTypeUndefined:
- case eSymbolTypeResolver:
- break;
- }
- }
- }
- }
-
- return NULL;
-}
-
-lldb::VariableSP
-ClangExpressionDeclMap::FindGlobalVariable
-(
- Target &target,
- ModuleSP &module,
- const ConstString &name,
- ClangNamespaceDecl *namespace_decl,
- TypeFromUser *type
-)
-{
- VariableList vars;
-
- if (module && namespace_decl)
- module->FindGlobalVariables (name, namespace_decl, true, -1, vars);
- else
- target.GetImages().FindGlobalVariables(name, true, -1, vars);
-
- if (vars.GetSize())
- {
- if (type)
- {
- for (size_t i = 0; i < vars.GetSize(); ++i)
- {
- VariableSP var_sp = vars.GetVariableAtIndex(i);
-
- if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetClangFullType()))
- return var_sp;
- }
- }
- else
- {
- return vars.GetVariableAtIndex(0);
- }
- }
-
- return VariableSP();
-}
-
-// Interface for ClangASTSource
-
-void
-ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
-{
- assert (m_ast_context);
-
- ClangASTMetrics::RegisterVisibleQuery();
-
- const ConstString name(context.m_decl_name.getAsString().c_str());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (GetImportInProgress())
- {
- if (log && log->GetVerbose())
- log->Printf("Ignoring a query during an import");
- return;
- }
-
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- if (log)
- {
- if (!context.m_decl_context)
- log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString());
- else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
- log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str());
- else
- log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName());
- }
-
- if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
- {
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
-
- if (log && log->GetVerbose())
- log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
- current_id, static_cast<void*>(namespace_map.get()),
- (int)namespace_map->size());
-
- if (!namespace_map)
- return;
-
- for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
- i != e;
- ++i)
- {
- if (log)
- log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s",
- current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
- i->first->GetFileSpec().GetFilename().GetCString());
-
- FindExternalVisibleDecls(context,
- i->first,
- i->second,
- current_id);
- }
- }
- else if (isa<TranslationUnitDecl>(context.m_decl_context))
- {
- ClangNamespaceDecl namespace_decl;
-
- if (log)
- log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id);
-
- FindExternalVisibleDecls(context,
- lldb::ModuleSP(),
- namespace_decl,
- current_id);
- }
-
- if (!context.m_found.variable)
- ClangASTSource::FindExternalVisibleDecls(context);
-}
-
-void
-ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
- lldb::ModuleSP module_sp,
- ClangNamespaceDecl &namespace_decl,
- unsigned int current_id)
-{
- assert (m_ast_context);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- SymbolContextList sc_list;
-
- const ConstString name(context.m_decl_name.getAsString().c_str());
-
- const char *name_unique_cstr = name.GetCString();
-
- if (name_unique_cstr == NULL)
- return;
-
- static ConstString id_name("id");
- static ConstString Class_name("Class");
-
- if (name == id_name || name == Class_name)
- return;
-
- // Only look for functions by name out in our symbols if the function
- // doesn't start with our phony prefix of '$'
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
- if (name_unique_cstr[0] == '$' && !namespace_decl)
- {
- static ConstString g_lldb_class_name ("$__lldb_class");
-
- if (name == g_lldb_class_name)
- {
- // Clang is looking for the type of "this"
-
- if (frame == NULL)
- return;
-
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
-
- if (!sym_ctx.function)
- return;
-
- // Get the block that defines the function
- Block *function_block = sym_ctx.GetFunctionBlock();
-
- if (!function_block)
- return;
-
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
- if (!decl_context)
- return;
-
- clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context);
-
- if (method_decl)
- {
- clang::CXXRecordDecl *class_decl = method_decl->getParent();
-
- QualType class_qual_type(class_decl->getTypeForDecl(), 0);
-
- TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
- &class_decl->getASTContext());
-
- if (log)
- {
- ASTDumper ast_dumper(class_qual_type);
- log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
- }
-
- TypeFromParser class_type = CopyClassType(class_user_type, current_id);
-
- if (!class_type.IsValid())
- return;
-
- TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType()));
-
- if (!type_source_info)
- return;
-
- TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
- m_ast_context->getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(),
- context.m_decl_name.getAsIdentifierInfo(),
- type_source_info);
-
-
- if (!typedef_decl)
- return;
-
- context.AddNamedDecl(typedef_decl);
-
- if (method_decl->isInstance())
- {
- // self is a pointer to the object
-
- QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
-
- TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
-
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
- }
- else
- {
- // This branch will get hit if we are executing code in the context of a function that
- // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a
- // method of the class. In that case, just look up the "this" variable in the current
- // scope and use its type.
- // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer
- // for C++ so it hasn't actually been tested.
-
- VariableList *vars = frame->GetVariableList(false);
-
- lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
-
- if (this_var &&
- this_var->IsInScope(frame) &&
- this_var->LocationIsValidForFrame (frame))
- {
- Type *this_type = this_var->GetType();
-
- if (!this_type)
- return;
-
- ClangASTType pointee_type = this_type->GetClangForwardType().GetPointeeType();
-
- if (pointee_type.IsValid())
- {
- if (log)
- {
- ASTDumper ast_dumper(this_type->GetClangFullType());
- log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
- }
-
- TypeFromUser class_user_type(pointee_type);
- AddOneType(context, class_user_type, current_id);
-
-
- TypeFromUser this_user_type(this_type->GetClangFullType());
- m_struct_vars->m_object_pointer_type = this_user_type;
- return;
- }
- }
- }
-
- return;
- }
-
- static ConstString g_lldb_objc_class_name ("$__lldb_objc_class");
- if (name == g_lldb_objc_class_name)
- {
- // Clang is looking for the type of "*self"
-
- if (!frame)
- return;
-
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
-
- if (!sym_ctx.function)
- return;
-
- // Get the block that defines the function
- Block *function_block = sym_ctx.GetFunctionBlock();
-
- if (!function_block)
- return;
-
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
- if (!decl_context)
- return;
-
- clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context);
-
- if (method_decl)
- {
- ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
-
- if (!self_interface)
- return;
-
- const clang::Type *interface_type = self_interface->getTypeForDecl();
-
- if (!interface_type)
- return; // This is unlikely, but we have seen crashes where this occurred
-
- TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
- &method_decl->getASTContext());
-
- if (log)
- {
- ASTDumper ast_dumper(interface_type);
- log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
- }
-
- AddOneType(context, class_user_type, current_id);
-
- if (method_decl->isInstanceMethod())
- {
- // self is a pointer to the object
-
- QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
-
- TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
-
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
- else
- {
- // self is a Class pointer
- QualType class_type = method_decl->getASTContext().getObjCClassType();
-
- TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
-
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
-
- return;
- }
- else
- {
- // This branch will get hit if we are executing code in the context of a function that
- // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a
- // method of the class. In that case, just look up the "self" variable in the current
- // scope and use its type.
-
- VariableList *vars = frame->GetVariableList(false);
-
- lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
-
- if (self_var &&
- self_var->IsInScope(frame) &&
- self_var->LocationIsValidForFrame (frame))
- {
- Type *self_type = self_var->GetType();
-
- if (!self_type)
- return;
-
- ClangASTType self_clang_type = self_type->GetClangFullType();
-
- if (self_clang_type.IsObjCClassType())
- {
- return;
- }
- else if (self_clang_type.IsObjCObjectPointerType())
- {
- self_clang_type = self_clang_type.GetPointeeType();
-
- if (!self_clang_type)
- return;
-
- if (log)
- {
- ASTDumper ast_dumper(self_type->GetClangFullType());
- log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
- }
-
- TypeFromUser class_user_type (self_clang_type);
-
- AddOneType(context, class_user_type, current_id);
-
- TypeFromUser self_user_type(self_type->GetClangFullType());
-
- m_struct_vars->m_object_pointer_type = self_user_type;
- return;
- }
- }
- }
-
- return;
- }
-
- // any other $__lldb names should be weeded out now
- if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1))
- return;
-
- do
- {
- if (!target)
- break;
-
- ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext();
-
- if (!scratch_clang_ast_context)
- break;
-
- ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
-
- if (!scratch_ast_context)
- break;
-
- TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name);
-
- if (!ptype_type_decl)
- break;
-
- Decl *parser_ptype_decl = m_ast_importer->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
-
- if (!parser_ptype_decl)
- break;
-
- TypeDecl *parser_ptype_type_decl = dyn_cast<TypeDecl>(parser_ptype_decl);
-
- if (!parser_ptype_type_decl)
- break;
-
- if (log)
- log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString());
-
- context.AddNamedDecl(parser_ptype_type_decl);
- } while (0);
-
- ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
-
- if (pvar_sp)
- {
- AddOneVariable(context, pvar_sp, current_id);
- return;
- }
-
- const char *reg_name(&name.GetCString()[1]);
-
- if (m_parser_vars->m_exe_ctx.GetRegisterContext())
- {
- const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name));
-
- if (reg_info)
- {
- if (log)
- log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name);
-
- AddOneRegister(context, reg_info, current_id);
- }
- }
- }
- else
- {
- ValueObjectSP valobj;
- VariableSP var;
- Error err;
-
- if (frame && !namespace_decl)
- {
- valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr,
- eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var,
- err);
-
- // If we found a variable in scope, no need to pull up function names
- if (err.Success() && var)
- {
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- return;
- }
- }
-
- if (target)
- {
- var = FindGlobalVariable (*target,
- module_sp,
- name,
- &namespace_decl,
- NULL);
-
- if (var)
- {
- valobj = ValueObjectVariable::Create(target, var);
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- return;
- }
- }
-
- std::vector<clang::NamedDecl *> decls_from_modules;
-
- if (target)
- {
- if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
- {
- decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
- }
- }
-
- if (!context.m_found.variable)
- {
- const bool include_inlines = false;
- const bool append = false;
-
- if (namespace_decl && module_sp)
- {
- const bool include_symbols = false;
-
- module_sp->FindFunctions(name,
- &namespace_decl,
- eFunctionNameTypeBase,
- include_symbols,
- include_inlines,
- append,
- sc_list);
- }
- else if (target && !namespace_decl)
- {
- const bool include_symbols = true;
-
- // TODO Fix FindFunctions so that it doesn't return
- // instance methods for eFunctionNameTypeBase.
-
- target->GetImages().FindFunctions(name,
- eFunctionNameTypeFull,
- include_symbols,
- include_inlines,
- append,
- sc_list);
- }
-
- if (sc_list.GetSize())
- {
- Symbol *extern_symbol = NULL;
- Symbol *non_extern_symbol = NULL;
-
- for (uint32_t index = 0, num_indices = sc_list.GetSize();
- index < num_indices;
- ++index)
- {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(index, sym_ctx);
-
- if (sym_ctx.function)
- {
- clang::DeclContext *decl_ctx = sym_ctx.function->GetClangDeclContext();
-
- if (!decl_ctx)
- continue;
-
- // Filter out class/instance methods.
- if (dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
- continue;
- if (dyn_cast<clang::CXXMethodDecl>(decl_ctx))
- continue;
-
- AddOneFunction(context, sym_ctx.function, NULL, current_id);
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- }
- else if (sym_ctx.symbol)
- {
- if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target)
- {
- sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
- if (sym_ctx.symbol == NULL)
- continue;
- }
-
- if (sym_ctx.symbol->IsExternal())
- extern_symbol = sym_ctx.symbol;
- else
- non_extern_symbol = sym_ctx.symbol;
- }
- }
-
- if (!context.m_found.function_with_type_info)
- {
- for (clang::NamedDecl *decl : decls_from_modules)
- {
- if (llvm::isa<clang::FunctionDecl>(decl))
- {
- clang::NamedDecl *copied_decl = llvm::cast<FunctionDecl>(m_ast_importer->CopyDecl(m_ast_context, &decl->getASTContext(), decl));
- context.AddNamedDecl(copied_decl);
- context.m_found.function_with_type_info = true;
- }
- }
- }
-
- if (!context.m_found.function_with_type_info)
- {
- if (extern_symbol)
- {
- AddOneFunction (context, NULL, extern_symbol, current_id);
- context.m_found.function = true;
- }
- else if (non_extern_symbol)
- {
- AddOneFunction (context, NULL, non_extern_symbol, current_id);
- context.m_found.function = true;
- }
- }
- }
-
- if (!context.m_found.function_with_type_info)
- {
- // Try the modules next.
-
- do
- {
- if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
- {
- bool append = false;
- uint32_t max_matches = 1;
- std::vector <clang::NamedDecl *> decls;
-
- if (!modules_decl_vendor->FindDecls(name,
- append,
- max_matches,
- decls))
- break;
-
- clang::NamedDecl *const decl_from_modules = decls[0];
-
- if (llvm::isa<clang::FunctionDecl>(decl_from_modules))
- {
- if (log)
- {
- log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules",
- current_id,
- name.GetCString());
- }
-
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
- clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr;
-
- if (!copied_function_decl)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules",
- current_id);
-
- break;
- }
-
- if (copied_function_decl->getBody() && m_parser_vars->m_code_gen)
- {
- DeclGroupRef decl_group_ref(copied_function_decl);
- m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
- }
-
- context.AddNamedDecl(copied_function_decl);
-
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- }
- else if (llvm::isa<clang::VarDecl>(decl_from_modules))
- {
- if (log)
- {
- log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules",
- current_id,
- name.GetCString());
- }
-
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
- clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr;
-
- if (!copied_var_decl)
- {
- if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules",
- current_id);
-
- break;
- }
-
- context.AddNamedDecl(copied_var_decl);
-
- context.m_found.variable = true;
- }
- }
- } while (0);
- }
-
- if (target && !context.m_found.variable && !namespace_decl)
- {
- // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic
- // data symbol, and -- if it is found -- treat it as a variable.
-
- const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
-
- if (data_symbol)
- {
- std::string warning("got name from symbols: ");
- warning.append(name.AsCString());
- const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0");
- m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
- AddOneGenericVariable(context, *data_symbol, current_id);
- context.m_found.variable = true;
- }
- }
- }
- }
-}
-
-//static clang_type_t
-//MaybePromoteToBlockPointerType
-//(
-// ASTContext *ast_context,
-// clang_type_t candidate_type
-//)
-//{
-// if (!candidate_type)
-// return candidate_type;
-//
-// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type);
-//
-// const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type);
-//
-// if (!candidate_pointer_type)
-// return candidate_type;
-//
-// QualType pointee_qual_type = candidate_pointer_type->getPointeeType();
-//
-// const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type);
-//
-// if (!pointee_record_type)
-// return candidate_type;
-//
-// RecordDecl *pointee_record_decl = pointee_record_type->getDecl();
-//
-// if (!pointee_record_decl->isRecord())
-// return candidate_type;
-//
-// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_")))
-// return candidate_type;
-//
-// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy);
-// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type);
-//
-// return block_pointer_type.getAsOpaquePtr();
-//}
-
-bool
-ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
- lldb_private::Value &var_location,
- TypeFromUser *user_type,
- TypeFromParser *parser_type)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Type *var_type = var->GetType();
-
- if (!var_type)
- {
- if (log)
- log->PutCString("Skipped a definition because it has no type");
- return false;
- }
-
- ClangASTType var_clang_type = var_type->GetClangFullType();
-
- if (!var_clang_type)
- {
- if (log)
- log->PutCString("Skipped a definition because it has no Clang type");
- return false;
- }
-
- ASTContext *ast = var_type->GetClangASTContext().getASTContext();
-
- if (!ast)
- {
- if (log)
- log->PutCString("There is no AST context for the current execution context");
- return false;
- }
- //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type);
-
- DWARFExpression &var_location_expr = var->LocationExpression();
-
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- Error err;
-
- if (var->GetLocationIsConstantValueData())
- {
- DataExtractor const_value_extractor;
-
- if (var_location_expr.GetExpressionData(const_value_extractor))
- {
- var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize());
- var_location.SetValueType(Value::eValueTypeHostAddress);
- }
- else
- {
- if (log)
- log->Printf("Error evaluating constant variable: %s", err.AsCString());
- return false;
- }
- }
-
- ClangASTType type_to_use = GuardedCopyType(var_clang_type);
-
- if (!type_to_use)
- {
- if (log)
- log->Printf("Couldn't copy a variable's type into the parser's AST context");
-
- return false;
- }
-
- if (parser_type)
- *parser_type = TypeFromParser(type_to_use);
-
- if (var_location.GetContextType() == Value::eContextTypeInvalid)
- var_location.SetClangType(type_to_use);
-
- if (var_location.GetValueType() == Value::eValueTypeFileAddress)
- {
- SymbolContext var_sc;
- var->CalculateSymbolContext(&var_sc);
-
- if (!var_sc.module_sp)
- return false;
-
- Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList());
-
- lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
-
- if (load_addr != LLDB_INVALID_ADDRESS)
- {
- var_location.GetScalar() = load_addr;
- var_location.SetValueType(Value::eValueTypeLoadAddress);
- }
- }
-
- if (user_type)
- *user_type = TypeFromUser(var_clang_type);
-
- return true;
-}
-
-void
-ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id)
-{
- assert (m_parser_vars.get());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- TypeFromUser ut;
- TypeFromParser pt;
- Value var_location;
-
- if (!GetVariableValue (var, var_location, &ut, &pt))
- return;
-
- clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType());
-
- if (parser_opaque_type.isNull())
- return;
-
- if (const clang::Type *parser_type = parser_opaque_type.getTypePtr())
- {
- if (const TagType *tag_type = dyn_cast<TagType>(parser_type))
- CompleteType(tag_type->getDecl());
- if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type))
- CompleteType(objc_object_ptr_type->getInterfaceDecl());
- }
-
-
- bool is_reference = pt.IsReferenceType();
-
- NamedDecl *var_decl = NULL;
- if (is_reference)
- var_decl = context.AddVarDecl(pt);
- else
- var_decl = context.AddVarDecl(pt.GetLValueReferenceType());
-
- std::string decl_name(context.m_decl_name.getAsString());
- ConstString entity_name(decl_name.c_str());
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (valobj));
-
- assert (entity.get());
- entity->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
- parser_vars->m_parser_type = pt;
- parser_vars->m_named_decl = var_decl;
- parser_vars->m_llvm_value = NULL;
- parser_vars->m_lldb_value = var_location;
- parser_vars->m_lldb_var = var;
-
- if (is_reference)
- entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;
-
- if (log)
- {
- ASTDumper orig_dumper(ut.GetOpaqueQualType());
- ASTDumper ast_dumper(var_decl);
- log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString());
- }
-}
-
-void
-ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
- ClangExpressionVariableSP &pvar_sp,
- unsigned int current_id)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- TypeFromUser user_type (pvar_sp->GetTypeFromUser());
-
- TypeFromParser parser_type (GuardedCopyType(user_type));
-
- if (!parser_type.GetOpaqueQualType())
- {
- if (log)
- log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString());
- return;
- }
-
- NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType());
-
- pvar_sp->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = pvar_sp->GetParserVars(GetParserID());
- parser_vars->m_parser_type = parser_type;
- parser_vars->m_named_decl = var_decl;
- parser_vars->m_llvm_value = NULL;
- parser_vars->m_lldb_value.Clear();
-
- if (log)
- {
- ASTDumper ast_dumper(var_decl);
- log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString());
- }
-}
-
-void
-ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
- const Symbol &symbol,
- unsigned int current_id)
-{
- assert(m_parser_vars.get());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
-
- if (target == NULL)
- return;
-
- ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext();
-
- TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
- TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
- NamedDecl *var_decl = context.AddVarDecl(parser_type);
-
- std::string decl_name(context.m_decl_name.getAsString());
- ConstString entity_name(decl_name.c_str());
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
- entity_name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
-
- entity->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
-
- const Address symbol_address = symbol.GetAddress();
- lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
-
- //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetClangType(user_type);
- parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
-
- parser_vars->m_parser_type = parser_type;
- parser_vars->m_named_decl = var_decl;
- parser_vars->m_llvm_value = NULL;
- parser_vars->m_lldb_sym = &symbol;
-
- if (log)
- {
- ASTDumper ast_dumper(var_decl);
-
- log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString());
- }
-}
-
-bool
-ClangExpressionDeclMap::ResolveUnknownTypes()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
-
- ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext();
-
- for (size_t index = 0, num_entities = m_found_entities.GetSize();
- index < num_entities;
- ++index)
- {
- ClangExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
-
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
-
- if (entity->m_flags & ClangExpressionVariable::EVUnknownType)
- {
- const NamedDecl *named_decl = parser_vars->m_named_decl;
- const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl);
-
- if (!var_decl)
- {
- if (log)
- log->Printf("Entity of unknown type does not have a VarDecl");
- return false;
- }
-
- if (log)
- {
- ASTDumper ast_dumper(const_cast<VarDecl*>(var_decl));
- log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString());
- }
-
- QualType var_type = var_decl->getType();
- TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext());
-
- lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr());
-
- if (!copied_type)
- {
- if (log)
- log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable");
-
- return (bool) lldb::ClangExpressionVariableSP();
- }
-
- TypeFromUser user_type(copied_type, scratch_ast_context);
-
-// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetClangType(user_type);
- parser_vars->m_parser_type = parser_type;
-
- entity->SetClangType(user_type);
-
- entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType);
- }
- }
-
- return true;
-}
-
-void
-ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
- const RegisterInfo *reg_info,
- unsigned int current_id)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- ClangASTType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context,
- reg_info->encoding,
- reg_info->byte_size * 8);
-
- if (!clang_type)
- {
- if (log)
- log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str());
- return;
- }
-
- TypeFromParser parser_clang_type (clang_type);
-
- NamedDecl *var_decl = context.AddVarDecl(parser_clang_type);
-
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
-
- std::string decl_name(context.m_decl_name.getAsString());
- entity->SetName (ConstString (decl_name.c_str()));
- entity->SetRegisterInfo (reg_info);
- entity->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
- parser_vars->m_parser_type = parser_clang_type;
- parser_vars->m_named_decl = var_decl;
- parser_vars->m_llvm_value = NULL;
- parser_vars->m_lldb_value.Clear();
- entity->m_flags |= ClangExpressionVariable::EVBareRegister;
-
- if (log)
- {
- ASTDumper ast_dumper(var_decl);
- log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString());
- }
-}
-
-void
-ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
- Function* function,
- Symbol* symbol,
- unsigned int current_id)
-{
- assert (m_parser_vars.get());
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- NamedDecl *function_decl = NULL;
- Address fun_address;
- ClangASTType function_clang_type;
-
- bool is_indirect_function = false;
-
- if (function)
- {
- Type *function_type = function->GetType();
-
- if (!function_type)
- {
- if (log)
- log->PutCString(" Skipped a function because it has no type");
- return;
- }
-
- function_clang_type = function_type->GetClangFullType();
-
- if (!function_clang_type)
- {
- if (log)
- log->PutCString(" Skipped a function because it has no Clang type");
- return;
- }
-
- fun_address = function->GetAddressRange().GetBaseAddress();
-
- ClangASTType copied_function_type = GuardedCopyType(function_clang_type);
- if (copied_function_type)
- {
- function_decl = context.AddFunDecl(copied_function_type);
-
- if (!function_decl)
- {
- if (log)
- {
- log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}",
- function_type->GetName().GetCString(),
- function_type->GetID());
- }
-
- return;
- }
- }
- else
- {
- // We failed to copy the type we found
- if (log)
- {
- log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt",
- function_type->GetName().GetCString(),
- function_type->GetID());
- }
-
- return;
- }
- }
- else if (symbol)
- {
- fun_address = symbol->GetAddress();
- function_decl = context.AddGenericFunDecl();
- is_indirect_function = symbol->IsIndirect();
- }
- else
- {
- if (log)
- log->PutCString(" AddOneFunction called with no function and no symbol");
- return;
- }
-
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
-
- lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function);
-
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
-
- std::string decl_name(context.m_decl_name.getAsString());
- entity->SetName(ConstString(decl_name.c_str()));
- entity->SetClangType (function_clang_type);
- entity->EnableParserVars(GetParserID());
-
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
-
- if (load_addr != LLDB_INVALID_ADDRESS)
- {
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
- parser_vars->m_lldb_value.GetScalar() = load_addr;
- }
- else
- {
- // We have to try finding a file address.
-
- lldb::addr_t file_addr = fun_address.GetFileAddress();
-
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress);
- parser_vars->m_lldb_value.GetScalar() = file_addr;
- }
-
-
- parser_vars->m_named_decl = function_decl;
- parser_vars->m_llvm_value = NULL;
-
- if (log)
- {
- ASTDumper ast_dumper(function_decl);
-
- StreamString ss;
-
- fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
-
- log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
- current_id,
- (function ? "specific" : "generic"),
- decl_name.c_str(),
- ss.GetData(),
- ast_dumper.GetCString());
- }
-}
-
-TypeFromParser
-ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
- unsigned int current_id)
-{
- ClangASTType copied_clang_type = GuardedCopyType(ut);
-
- if (!copied_clang_type)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type");
-
- return TypeFromParser();
- }
-
- if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ())
- {
- ClangASTType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
- ClangASTType void_ptr_clang_type = void_clang_type.GetPointerType();
-
- ClangASTType method_type = ClangASTContext::CreateFunctionType (m_ast_context,
- void_clang_type,
- &void_ptr_clang_type,
- 1,
- false,
- copied_clang_type.GetTypeQualifiers());
-
- const bool is_virtual = false;
- const bool is_static = false;
- const bool is_inline = false;
- const bool is_explicit = false;
- const bool is_attr_used = true;
- const bool is_artificial = false;
-
- copied_clang_type.AddMethodToCXXRecordType ("$__lldb_expr",
- method_type,
- lldb::eAccessPublic,
- is_virtual,
- is_static,
- is_inline,
- is_explicit,
- is_attr_used,
- is_artificial);
- }
-
- return TypeFromParser(copied_clang_type);
-}
-
-void
-ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
- TypeFromUser &ut,
- unsigned int current_id)
-{
- ClangASTType copied_clang_type = GuardedCopyType(ut);
-
- if (!copied_clang_type)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
-
- return;
- }
-
- context.AddTypeDecl(copied_clang_type);
-}
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
deleted file mode 100644
index 2b344b0..0000000
--- a/source/Expression/ClangExpressionParser.cpp
+++ /dev/null
@@ -1,621 +0,0 @@
-//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/ClangExpressionParser.h"
-
-#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Host/File.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ExternalASTSource.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/FrontendPluginRegistry.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/ParseAST.h"
-#include "clang/Rewrite/Frontend/FrontendActions.h"
-#include "clang/Sema/SemaConsumer.h"
-#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/TargetSelect.h"
-
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Signals.h"
-
-using namespace clang;
-using namespace llvm;
-using namespace lldb_private;
-
-//===----------------------------------------------------------------------===//
-// Utility Methods for Clang
-//===----------------------------------------------------------------------===//
-
-std::string GetBuiltinIncludePath(const char *Argv0) {
- SmallString<128> P(llvm::sys::fs::getMainExecutable(
- Argv0, (void *)(intptr_t) GetBuiltinIncludePath));
-
- if (!P.empty()) {
- llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang
- llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING,
- "include");
- }
-
- return P.str();
-}
-
-class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks
-{
- ClangModulesDeclVendor &m_decl_vendor;
- ClangPersistentVariables &m_persistent_vars;
- StreamString m_error_stream;
- bool m_has_errors = false;
-public:
- LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor,
- ClangPersistentVariables &persistent_vars) :
- m_decl_vendor(decl_vendor),
- m_persistent_vars(persistent_vars)
- {
- }
-
- virtual void moduleImport(SourceLocation import_location,
- ModuleIdPath path,
- const clang::Module * /*null*/)
- {
- std::vector<ConstString> string_path;
-
- for (const std::pair<IdentifierInfo *, SourceLocation> &component : path)
- {
- string_path.push_back(ConstString(component.first->getName()));
- }
-
- StreamString error_stream;
-
- ClangModulesDeclVendor::ModuleVector exported_modules;
-
- if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream))
- {
- m_has_errors = true;
- }
-
- for (ClangModulesDeclVendor::ModuleID module : exported_modules)
- {
- m_persistent_vars.AddHandLoadedClangModule(module);
- }
- }
-
- bool hasErrors()
- {
- return m_has_errors;
- }
-
- const std::string &getErrorString()
- {
- return m_error_stream.GetString();
- }
-};
-
-//===----------------------------------------------------------------------===//
-// Implementation of ClangExpressionParser
-//===----------------------------------------------------------------------===//
-
-ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr,
- bool generate_debug_info) :
- m_expr (expr),
- m_compiler (),
- m_code_generator (),
- m_pp_callbacks(nullptr)
-{
- // 1. Create a new compiler instance.
- m_compiler.reset(new CompilerInstance());
-
- // 2. Install the target.
-
- lldb::TargetSP target_sp;
- if (exe_scope)
- target_sp = exe_scope->CalculateTarget();
-
- // TODO: figure out what to really do when we don't have a valid target.
- // Sometimes this will be ok to just use the host target triple (when we
- // evaluate say "2+3", but other expressions like breakpoint conditions
- // and other things that _are_ target specific really shouldn't just be
- // using the host triple. This needs to be fixed in a better way.
- if (target_sp && target_sp->GetArchitecture().IsValid())
- {
- std::string triple = target_sp->GetArchitecture().GetTriple().str();
- m_compiler->getTargetOpts().Triple = triple;
- }
- else
- {
- m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
- }
-
- if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
- target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
- {
- m_compiler->getTargetOpts().Features.push_back("+sse");
- m_compiler->getTargetOpts().Features.push_back("+sse2");
- }
-
- // Any arm32 iOS environment, but not on arm64
- if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
- m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
- m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
- {
- m_compiler->getTargetOpts().ABI = "apcs-gnu";
- }
-
- m_compiler->createDiagnostics();
-
- // Create the target instance.
- m_compiler->setTarget(TargetInfo::CreateTargetInfo(
- m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts));
-
- assert (m_compiler->hasTarget());
-
- // 3. Set options.
-
- lldb::LanguageType language = expr.Language();
-
- switch (language)
- {
- case lldb::eLanguageTypeC:
- break;
- case lldb::eLanguageTypeObjC:
- m_compiler->getLangOpts().ObjC1 = true;
- m_compiler->getLangOpts().ObjC2 = true;
- break;
- case lldb::eLanguageTypeC_plus_plus:
- m_compiler->getLangOpts().CPlusPlus = true;
- m_compiler->getLangOpts().CPlusPlus11 = true;
- m_compiler->getHeaderSearchOpts().UseLibcxx = true;
- break;
- case lldb::eLanguageTypeObjC_plus_plus:
- default:
- m_compiler->getLangOpts().ObjC1 = true;
- m_compiler->getLangOpts().ObjC2 = true;
- m_compiler->getLangOpts().CPlusPlus = true;
- m_compiler->getLangOpts().CPlusPlus11 = true;
- m_compiler->getHeaderSearchOpts().UseLibcxx = true;
- break;
- }
-
- m_compiler->getLangOpts().Bool = true;
- m_compiler->getLangOpts().WChar = true;
- m_compiler->getLangOpts().Blocks = true;
- m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
- if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
- m_compiler->getLangOpts().DebuggerCastResultToId = true;
-
- m_compiler->getLangOpts().CharIsSigned =
- ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault();
-
- // Spell checking is a nice feature, but it ends up completing a
- // lot of types that we didn't strictly speaking need to complete.
- // As a result, we spend a long time parsing and importing debug
- // information.
- m_compiler->getLangOpts().SpellChecking = false;
-
- lldb::ProcessSP process_sp;
- if (exe_scope)
- process_sp = exe_scope->CalculateProcess();
-
- if (process_sp && m_compiler->getLangOpts().ObjC1)
- {
- if (process_sp->GetObjCLanguageRuntime())
- {
- if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2)
- m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
- else
- m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));
-
- if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
- m_compiler->getLangOpts().DebuggerObjCLiteral = true;
- }
- }
-
- m_compiler->getLangOpts().ThreadsafeStatics = false;
- m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
- m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
-
- // Set CodeGen options
- m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
- m_compiler->getCodeGenOpts().InstrumentFunctions = false;
- m_compiler->getCodeGenOpts().DisableFPElim = true;
- m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
- if (generate_debug_info)
- m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo);
- else
- m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo);
-
- // Disable some warnings.
- m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
- "unused-value", clang::diag::Severity::Ignored, SourceLocation());
- m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
- "odr", clang::diag::Severity::Ignored, SourceLocation());
-
- // Inform the target of the language options
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- m_compiler->getTarget().adjust(m_compiler->getLangOpts());
-
- // 4. Set up the diagnostic buffer for reporting errors
-
- m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
-
- // 5. Set up the source management objects inside the compiler
-
- clang::FileSystemOptions file_system_options;
- m_file_manager.reset(new clang::FileManager(file_system_options));
-
- if (!m_compiler->hasSourceManager())
- m_compiler->createSourceManager(*m_file_manager.get());
-
- m_compiler->createFileManager();
- m_compiler->createPreprocessor(TU_Complete);
-
- if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
- {
- std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, target_sp->GetPersistentVariables()));
- m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
- m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
- }
-
- // 6. Most of this we get from the CompilerInstance, but we
- // also want to give the context an ExternalASTSource.
- m_selector_table.reset(new SelectorTable());
- m_builtin_context.reset(new Builtin::Context());
-
- std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
- m_compiler->getSourceManager(),
- m_compiler->getPreprocessor().getIdentifierTable(),
- *m_selector_table.get(),
- *m_builtin_context.get()));
-
- ast_context->InitBuiltinTypes(m_compiler->getTarget());
-
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
-
- if (decl_map)
- {
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
- decl_map->InstallASTContext(ast_context.get());
- ast_context->setExternalSource(ast_source);
- }
-
- m_compiler->setASTContext(ast_context.release());
-
- std::string module_name("$__lldb_module");
-
- m_llvm_context.reset(new LLVMContext());
- m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
- module_name,
- m_compiler->getHeaderSearchOpts(),
- m_compiler->getPreprocessorOpts(),
- m_compiler->getCodeGenOpts(),
- *m_llvm_context));
-}
-
-ClangExpressionParser::~ClangExpressionParser()
-{
-}
-
-unsigned
-ClangExpressionParser::Parse (Stream &stream)
-{
- TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient());
-
- diag_buf->FlushDiagnostics (m_compiler->getDiagnostics());
-
- const char *expr_text = m_expr.Text();
-
- clang::SourceManager &SourceMgr = m_compiler->getSourceManager();
- bool created_main_file = false;
- if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo)
- {
- std::string temp_source_path;
-
- int temp_fd = -1;
- llvm::SmallString<PATH_MAX> result_path;
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
- {
- tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
- temp_source_path = std::move(tmpdir_file_spec.GetPath());
- llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
- }
- else
- {
- llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
- }
-
- if (temp_fd != -1)
- {
- lldb_private::File file (temp_fd, true);
- const size_t expr_text_len = strlen(expr_text);
- size_t bytes_written = expr_text_len;
- if (file.Write(expr_text, bytes_written).Success())
- {
- if (bytes_written == expr_text_len)
- {
- file.Close();
- SourceMgr.setMainFileID(SourceMgr.createFileID(
- m_file_manager->getFile(result_path),
- SourceLocation(), SrcMgr::C_User));
- created_main_file = true;
- }
- }
- }
- }
-
- if (!created_main_file)
- {
- std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
- SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer)));
- }
-
- diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
-
- ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
-
- if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap())
- decl_map->InstallCodeGenerator(m_code_generator.get());
-
- if (ast_transformer)
- ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
- else
- ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
-
- diag_buf->EndSourceFile();
-
- TextDiagnosticBuffer::const_iterator diag_iterator;
-
- int num_errors = 0;
-
- if (m_pp_callbacks && m_pp_callbacks->hasErrors())
- {
- num_errors++;
-
- stream.PutCString(m_pp_callbacks->getErrorString().c_str());
- }
-
- for (diag_iterator = diag_buf->warn_begin();
- diag_iterator != diag_buf->warn_end();
- ++diag_iterator)
- stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
-
- for (diag_iterator = diag_buf->err_begin();
- diag_iterator != diag_buf->err_end();
- ++diag_iterator)
- {
- num_errors++;
- stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
- }
-
- for (diag_iterator = diag_buf->note_begin();
- diag_iterator != diag_buf->note_end();
- ++diag_iterator)
- stream.Printf("note: %s\n", (*diag_iterator).second.c_str());
-
- if (!num_errors)
- {
- if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes())
- {
- stream.Printf("error: Couldn't infer the type of a variable\n");
- num_errors++;
- }
- }
-
- return num_errors;
-}
-
-static bool FindFunctionInModule (ConstString &mangled_name,
- llvm::Module *module,
- const char *orig_name)
-{
- for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end();
- fi != fe;
- ++fi)
- {
- if (fi->getName().str().find(orig_name) != std::string::npos)
- {
- mangled_name.SetCString(fi->getName().str().c_str());
- return true;
- }
- }
-
- return false;
-}
-
-Error
-ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
- lldb::addr_t &func_end,
- std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
- ExecutionContext &exe_ctx,
- bool &can_interpret,
- ExecutionPolicy execution_policy)
-{
- func_addr = LLDB_INVALID_ADDRESS;
- func_end = LLDB_INVALID_ADDRESS;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Error err;
-
- std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());
-
- if (!llvm_module_ap.get())
- {
- err.SetErrorToGenericError();
- err.SetErrorString("IR doesn't contain a module");
- return err;
- }
-
- // Find the actual name of the function (it's often mangled somehow)
-
- ConstString function_name;
-
- if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
- {
- err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
- return err;
- }
- else
- {
- if (log)
- log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
- }
-
- execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
- llvm_module_ap, // handed off here
- function_name,
- exe_ctx.GetTargetSP(),
- m_compiler->getTargetOpts().Features));
-
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
-
- if (decl_map)
- {
- Stream *error_stream = NULL;
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- error_stream = target->GetDebugger().GetErrorFile().get();
-
- IRForTarget ir_for_target(decl_map,
- m_expr.NeedsVariableResolution(),
- *execution_unit_sp,
- error_stream,
- function_name.AsCString());
-
- bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
-
- Error interpret_error;
- Process *process = exe_ctx.GetProcessPtr();
-
- bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
- can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);
-
-
- if (!ir_can_run)
- {
- err.SetErrorString("The expression could not be prepared to run in the target");
- return err;
- }
-
- if (!can_interpret && execution_policy == eExecutionPolicyNever)
- {
- err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
- return err;
- }
-
- if (!process && execution_policy == eExecutionPolicyAlways)
- {
- err.SetErrorString("Expression needed to run in the target, but the target can't be run");
- return err;
- }
-
- if (execution_policy == eExecutionPolicyAlways || !can_interpret)
- {
- if (m_expr.NeedsValidation() && process)
- {
- if (!process->GetDynamicCheckers())
- {
- DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
-
- StreamString install_errors;
-
- if (!dynamic_checkers->Install(install_errors, exe_ctx))
- {
- if (install_errors.GetString().empty())
- err.SetErrorString ("couldn't install checkers, unknown error");
- else
- err.SetErrorString (install_errors.GetString().c_str());
-
- return err;
- }
-
- process->SetDynamicCheckers(dynamic_checkers);
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
- }
-
- IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
-
- if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Couldn't add dynamic checks to the expression");
- return err;
- }
- }
-
- execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
- }
- }
- else
- {
- execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
- }
-
- return err;
-}
-
-bool
-ClangExpressionParser::GetGenerateDebugInfo () const
-{
- if (m_compiler)
- return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
- return false;
-}
diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp
deleted file mode 100644
index e86016e..0000000
--- a/source/Expression/ClangExpressionVariable.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "clang/AST/ASTContext.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-
-using namespace lldb_private;
-using namespace clang;
-
-ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (EVNone),
- m_frozen_sp (ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size))
-{
-}
-
-ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope,
- Value &value,
- const ConstString &name,
- uint16_t flags) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (flags),
- m_frozen_sp (ValueObjectConstResult::Create (exe_scope, value, name))
-{
-}
-
-ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (EVNone),
- m_frozen_sp (valobj_sp)
-{
-}
-
-//----------------------------------------------------------------------
-/// Return the variable's size in bytes
-//----------------------------------------------------------------------
-size_t
-ClangExpressionVariable::GetByteSize ()
-{
- return m_frozen_sp->GetByteSize();
-}
-
-const ConstString &
-ClangExpressionVariable::GetName ()
-{
- return m_frozen_sp->GetName();
-}
-
-lldb::ValueObjectSP
-ClangExpressionVariable::GetValueObject()
-{
- return m_frozen_sp;
-}
-
-RegisterInfo *
-ClangExpressionVariable::GetRegisterInfo()
-{
- return m_frozen_sp->GetValue().GetRegisterInfo();
-}
-
-void
-ClangExpressionVariable::SetRegisterInfo (const RegisterInfo *reg_info)
-{
- return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_info));
-}
-
-ClangASTType
-ClangExpressionVariable::GetClangType()
-{
- return m_frozen_sp->GetClangType();
-}
-
-void
-ClangExpressionVariable::SetClangType(const ClangASTType &clang_type)
-{
- m_frozen_sp->GetValue().SetClangType(clang_type);
-}
-
-
-TypeFromUser
-ClangExpressionVariable::GetTypeFromUser()
-{
- TypeFromUser tfu (m_frozen_sp->GetClangType());
- return tfu;
-}
-
-uint8_t *
-ClangExpressionVariable::GetValueBytes()
-{
- const size_t byte_size = m_frozen_sp->GetByteSize();
- if (byte_size > 0)
- {
- if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
- {
- m_frozen_sp->GetValue().ResizeData(byte_size);
- m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
- }
- return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
- }
- return NULL;
-}
-
-void
-ClangExpressionVariable::SetName (const ConstString &name)
-{
- m_frozen_sp->SetName (name);
-}
-
-void
-ClangExpressionVariable::ValueUpdated ()
-{
- m_frozen_sp->ValueUpdated ();
-}
-
-void
-ClangExpressionVariable::TransferAddress (bool force)
-{
- if (m_live_sp.get() == NULL)
- return;
-
- if (m_frozen_sp.get() == NULL)
- return;
-
- if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS))
- m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress());
-}
diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp
deleted file mode 100644
index e825363..0000000
--- a/source/Expression/ClangModulesDeclVendor.cpp
+++ /dev/null
@@ -1,731 +0,0 @@
-//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mutex> // std::once
-
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-
-#include "lldb/Core/Log.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/LLDBAssert.h"
-
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Serialization/ASTReader.h"
-
-
-using namespace lldb_private;
-
-namespace {
- // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings
- // so we can provide them to the user in case a module failed to load.
- class StoringDiagnosticConsumer : public clang::DiagnosticConsumer
- {
- public:
- StoringDiagnosticConsumer ();
- void
- HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info);
-
- void
- ClearDiagnostics ();
-
- void
- DumpDiagnostics (Stream &error_stream);
- private:
- typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic;
- std::vector<IDAndDiagnostic> m_diagnostics;
- Log * m_log;
- };
-
- // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required
- // to load modules.
- class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor
- {
- public:
- ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
- llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
- std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
- std::unique_ptr<clang::Parser> &&parser);
-
- virtual bool
- AddModule(ModulePath &path,
- ModuleVector *exported_modules,
- Stream &error_stream) override;
-
- virtual bool
- AddModulesForCompileUnit(CompileUnit &cu,
- ModuleVector &exported_modules,
- Stream &error_stream) override;
-
- virtual uint32_t
- FindDecls (const ConstString &name,
- bool append,
- uint32_t max_matches,
- std::vector <clang::NamedDecl*> &decls) override;
-
- virtual void
- ForEachMacro(const ModuleVector &modules,
- std::function<bool (const std::string &)> handler) override;
-
- ~ClangModulesDeclVendorImpl();
-
- private:
- void
- ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module);
-
- void
- ReportModuleExports (ModuleVector &exports,
- clang::Module *module);
-
- clang::ModuleLoadResult
- DoGetModule(clang::ModuleIdPath path, bool make_visible);
-
- bool m_enabled = false;
-
- llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
- llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation;
- std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
- std::unique_ptr<clang::Parser> m_parser;
- size_t m_source_location_index = 0; // used to give name components fake SourceLocations
-
- typedef std::vector<ConstString> ImportedModule;
- typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
- typedef std::set<ModuleID> ImportedModuleSet;
- ImportedModuleMap m_imported_modules;
- ImportedModuleSet m_user_imported_modules;
- };
-}
-
-StoringDiagnosticConsumer::StoringDiagnosticConsumer ()
-{
- m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-}
-
-void
-StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info)
-{
- llvm::SmallVector<char, 256> diagnostic_string;
-
- info.FormatDiagnostic(diagnostic_string);
-
- m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size())));
-}
-
-void
-StoringDiagnosticConsumer::ClearDiagnostics ()
-{
- m_diagnostics.clear();
-}
-
-void
-StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream)
-{
- for (IDAndDiagnostic &diag : m_diagnostics)
- {
- switch (diag.first)
- {
- default:
- error_stream.PutCString(diag.second.c_str());
- error_stream.PutChar('\n');
- break;
- case clang::DiagnosticsEngine::Level::Ignored:
- break;
- }
- }
-}
-
-static FileSpec
-GetResourceDir ()
-{
- static FileSpec g_cached_resource_dir;
-
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, [](){
- HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir);
- });
-
- return g_cached_resource_dir;
-}
-
-
-ClangModulesDeclVendor::ClangModulesDeclVendor()
-{
-}
-
-ClangModulesDeclVendor::~ClangModulesDeclVendor()
-{
-}
-
-ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
- llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
- std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
- std::unique_ptr<clang::Parser> &&parser) :
- ClangModulesDeclVendor(),
- m_diagnostics_engine(diagnostics_engine),
- m_compiler_invocation(compiler_invocation),
- m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser)),
- m_imported_modules()
-{
-}
-
-void
-ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module)
-{
- if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
- return;
-
- exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
-
- llvm::SmallVector<clang::Module*, 2> sub_exports;
-
- module->getExportedModules(sub_exports);
-
- for (clang::Module *module : sub_exports)
- {
- ReportModuleExportsHelper(exports, module);
- }
-}
-
-void
-ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports,
- clang::Module *module)
-{
- std::set<ClangModulesDeclVendor::ModuleID> exports_set;
-
- ReportModuleExportsHelper(exports_set, module);
-
- for (ModuleID module : exports_set)
- {
- exports.push_back(module);
- }
-}
-
-bool
-ClangModulesDeclVendorImpl::AddModule(ModulePath &path,
- ModuleVector *exported_modules,
- Stream &error_stream)
-{
- // Fail early.
-
- if (m_compiler_instance->hadModuleLoaderFatalFailure())
- {
- error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n");
- return false;
- }
-
- // Check if we've already imported this module.
-
- std::vector<ConstString> imported_module;
-
- for (ConstString path_component : path)
- {
- imported_module.push_back(path_component);
- }
-
- {
- ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
-
- if (mi != m_imported_modules.end())
- {
- if (exported_modules)
- {
- ReportModuleExports(*exported_modules, mi->second);
- }
- return true;
- }
- }
-
- if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef()))
- {
- error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString());
- return false;
- }
-
- llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path;
-
- {
- clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager();
-
- for (ConstString path_component : path)
- {
- clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()),
- source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++)));
- }
- }
-
- StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient());
-
- diagnostic_consumer->ClearDiagnostics();
-
- clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
-
- if (!top_level_module)
- {
- diagnostic_consumer->DumpDiagnostics(error_stream);
- error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString());
- return false;
- }
-
- clang::Module *submodule = top_level_module;
-
- for (size_t ci = 1; ci < path.size(); ++ci)
- {
- llvm::StringRef component = path[ci].GetStringRef();
- submodule = submodule->findSubmodule(component.str());
- if (!submodule)
- {
- diagnostic_consumer->DumpDiagnostics(error_stream);
- error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str());
- return false;
- }
- }
-
- clang::Module *requested_module = DoGetModule(clang_path, true);
-
- if (requested_module != nullptr)
- {
- if (exported_modules)
- {
- ReportModuleExports(*exported_modules, requested_module);
- }
-
- m_imported_modules[imported_module] = requested_module;
-
- m_enabled = true;
-
- return true;
- }
-
- return false;
-}
-
-
-bool
-ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language)
-{
- switch (language)
- {
- default:
- return false;
- // C++ and friends to be added
- case lldb::LanguageType::eLanguageTypeC:
- case lldb::LanguageType::eLanguageTypeC11:
- case lldb::LanguageType::eLanguageTypeC89:
- case lldb::LanguageType::eLanguageTypeC99:
- case lldb::LanguageType::eLanguageTypeObjC:
- return true;
- }
-}
-
-bool
-ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu,
- ClangModulesDeclVendor::ModuleVector &exported_modules,
- Stream &error_stream)
-{
- if (LanguageSupportsClangModules(cu.GetLanguage()))
- {
- std::vector<ConstString> imported_modules = cu.GetImportedModules();
-
- for (ConstString imported_module : imported_modules)
- {
- std::vector<ConstString> path;
-
- path.push_back(imported_module);
-
- if (!AddModule(path, &exported_modules, error_stream))
- {
- return false;
- }
- }
-
- return true;
- }
-
- return true;
-}
-
-// ClangImporter::lookupValue
-
-uint32_t
-ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
- bool append,
- uint32_t max_matches,
- std::vector <clang::NamedDecl*> &decls)
-{
- if (!m_enabled)
- {
- return 0;
- }
-
- if (!append)
- decls.clear();
-
- clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
-
- clang::LookupResult lookup_result(m_compiler_instance->getSema(),
- clang::DeclarationName(&ident),
- clang::SourceLocation(),
- clang::Sema::LookupOrdinaryName);
-
- m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl()));
-
- uint32_t num_matches = 0;
-
- for (clang::NamedDecl *named_decl : lookup_result)
- {
- if (num_matches >= max_matches)
- return num_matches;
-
- decls.push_back(named_decl);
- ++num_matches;
- }
-
- return num_matches;
-}
-
-void
-ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules,
- std::function<bool (const std::string &)> handler)
-{
- if (!m_enabled)
- {
- return;
- }
-
- typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
- ModulePriorityMap module_priorities;
-
- ssize_t priority = 0;
-
- for (ModuleID module : modules)
- {
- module_priorities[module] = priority++;
- }
-
- if (m_compiler_instance->getPreprocessor().getExternalSource())
- {
- m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros();
- }
-
- for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(),
- me = m_compiler_instance->getPreprocessor().macro_end();
- mi != me;
- ++mi)
- {
- const clang::IdentifierInfo *ii = nullptr;
-
- {
- if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup())
- {
- lookup->get(mi->first->getName());
- }
- if (!ii)
- {
- ii = mi->first;
- }
- }
-
- ssize_t found_priority = -1;
- clang::MacroInfo *macro_info = nullptr;
-
- for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
- {
- clang::Module *module = module_macro->getOwningModule();
-
- {
- ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module));
-
- if (pi != module_priorities.end() && pi->second > found_priority)
- {
- macro_info = module_macro->getMacroInfo();
- found_priority = pi->second;
- }
- }
-
- clang::Module *top_level_module = module->getTopLevelModule();
-
- if (top_level_module != module)
- {
- ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module));
-
- if ((pi != module_priorities.end()) && pi->second > found_priority)
- {
- macro_info = module_macro->getMacroInfo();
- found_priority = pi->second;
- }
- }
- }
-
- if (macro_info)
- {
- std::string macro_expansion = "#define ";
- macro_expansion.append(mi->first->getName().str().c_str());
-
- {
- if (macro_info->isFunctionLike())
- {
- macro_expansion.append("(");
-
- bool first_arg = true;
-
- for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(),
- ae = macro_info->arg_end();
- ai != ae;
- ++ai)
- {
- if (!first_arg)
- {
- macro_expansion.append(", ");
- }
- else
- {
- first_arg = false;
- }
-
- macro_expansion.append((*ai)->getName().str());
- }
-
- if (macro_info->isC99Varargs())
- {
- if (first_arg)
- {
- macro_expansion.append("...");
- }
- else
- {
- macro_expansion.append(", ...");
- }
- }
- else if (macro_info->isGNUVarargs())
- {
- macro_expansion.append("...");
- }
-
- macro_expansion.append(")");
- }
-
- macro_expansion.append(" ");
-
- bool first_token = true;
-
- for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
- te = macro_info->tokens_end();
- ti != te;
- ++ti)
- {
- if (!first_token)
- {
- macro_expansion.append(" ");
- }
- else
- {
- first_token = false;
- }
-
- if (ti->isLiteral())
- {
- if (const char *literal_data = ti->getLiteralData())
- {
- std::string token_str(literal_data, ti->getLength());
- macro_expansion.append(token_str);
- }
- else
- {
- bool invalid = false;
- const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid);
-
- if (invalid)
- {
- lldbassert(!"Unhandled token kind");
- macro_expansion.append("<unknown literal value>");
- }
- else
- {
- macro_expansion.append(std::string(literal_source, ti->getLength()));
- }
- }
- }
- else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind()))
- {
- macro_expansion.append(punctuator_spelling);
- }
- else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind()))
- {
- macro_expansion.append(keyword_spelling);
- }
- else
- {
- switch (ti->getKind())
- {
- case clang::tok::TokenKind::identifier:
- macro_expansion.append(ti->getIdentifierInfo()->getName().str());
- break;
- case clang::tok::TokenKind::raw_identifier:
- macro_expansion.append(ti->getRawIdentifier().str());
- default:
- macro_expansion.append(ti->getName());
- break;
- }
- }
- }
-
- if (handler(macro_expansion))
- {
- return;
- }
- }
- }
- }
-}
-
-ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl()
-{
-}
-
-clang::ModuleLoadResult
-ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
- bool make_visible)
-{
- clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
-
- const bool is_inclusion_directive = false;
-
- return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive);
-}
-
-static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
-
-lldb_private::ClangModulesDeclVendor *
-ClangModulesDeclVendor::Create(Target &target)
-{
- // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's
- // compiler are both initialized in the same way – preferably by the same code.
-
- if (!target.GetPlatform()->SupportsModules())
- return nullptr;
-
- const ArchSpec &arch = target.GetArchitecture();
-
- std::vector<std::string> compiler_invocation_arguments =
- {
- "-fmodules",
- "-fcxx-modules",
- "-fsyntax-only",
- "-femit-all-decls",
- "-target", arch.GetTriple().str(),
- "-fmodules-validate-system-headers",
- "-Werror=non-modular-include-in-framework-module"
- };
-
- target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments);
-
- compiler_invocation_arguments.push_back(ModuleImportBufferName);
-
- // Add additional search paths with { "-I", path } or { "-F", path } here.
-
- {
- llvm::SmallString<128> DefaultModuleCache;
- const bool erased_on_reboot = false;
- llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache);
- llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
- llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
- std::string module_cache_argument("-fmodules-cache-path=");
- module_cache_argument.append(DefaultModuleCache.str().str());
- compiler_invocation_arguments.push_back(module_cache_argument);
- }
-
- FileSpecList &module_search_paths = target.GetClangModuleSearchPaths();
-
- for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi)
- {
- const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
-
- std::string search_path_argument = "-I";
- search_path_argument.append(search_path.GetPath());
-
- compiler_invocation_arguments.push_back(search_path_argument);
- }
-
- {
- FileSpec clang_resource_dir = GetResourceDir();
-
- if (clang_resource_dir.IsDirectory())
- {
- compiler_invocation_arguments.push_back("-resource-dir");
- compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
- }
- }
-
- llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
- new StoringDiagnosticConsumer);
-
- std::vector<const char *> compiler_invocation_argument_cstrs;
-
- for (const std::string &arg : compiler_invocation_arguments) {
- compiler_invocation_argument_cstrs.push_back(arg.c_str());
- }
-
- llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine));
-
- if (!invocation)
- return nullptr;
-
- std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));",
- ModuleImportBufferName);
-
- invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release());
-
- std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance);
-
- instance->setDiagnostics(diagnostics_engine.get());
- instance->setInvocation(invocation.get());
-
- std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
-
- instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts));
-
- if (!instance->hasTarget())
- return nullptr;
-
- instance->getTarget().adjust(instance->getLangOpts());
-
- if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0]))
- return nullptr;
-
- instance->getPreprocessor().enableIncrementalProcessing();
-
- instance->createModuleManager();
-
- instance->createSema(action->getTranslationUnitKind(), nullptr);
-
- const bool skipFunctionBodies = false;
- std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
-
- instance->getPreprocessor().EnterMainSourceFile();
- parser->Initialize();
-
- clang::Parser::DeclGroupPtrTy parsed;
-
- while (!parser->ParseTopLevelDecl(parsed));
-
- return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser));
-}
diff --git a/source/Expression/ClangPersistentVariables.cpp b/source/Expression/ClangPersistentVariables.cpp
deleted file mode 100644
index db062d2..0000000
--- a/source/Expression/ClangPersistentVariables.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/Value.h"
-
-#include "llvm/ADT/StringMap.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-ClangPersistentVariables::ClangPersistentVariables () :
- ClangExpressionVariableList(),
- m_next_persistent_variable_id (0)
-{
-}
-
-ClangExpressionVariableSP
-ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp)
-{
- ClangExpressionVariableSP var_sp (CreateVariable(valobj_sp));
- return var_sp;
-}
-
-ClangExpressionVariableSP
-ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope,
- const ConstString &name,
- const TypeFromUser& user_type,
- lldb::ByteOrder byte_order,
- uint32_t addr_byte_size)
-{
- ClangExpressionVariableSP var_sp (GetVariable(name));
-
- if (!var_sp)
- var_sp = CreateVariable(exe_scope, name, user_type, byte_order, addr_byte_size);
-
- return var_sp;
-}
-
-void
-ClangPersistentVariables::RemovePersistentVariable (lldb::ClangExpressionVariableSP variable)
-{
- RemoveVariable(variable);
-
- const char *name = variable->GetName().AsCString();
-
- if (*name != '$')
- return;
- name++;
-
- if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1)
- m_next_persistent_variable_id--;
-}
-
-ConstString
-ClangPersistentVariables::GetNextPersistentVariableName ()
-{
- char name_cstr[256];
- ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++);
- ConstString name(name_cstr);
- return name;
-}
-
-void
-ClangPersistentVariables::RegisterPersistentType (const ConstString &name,
- clang::TypeDecl *type_decl)
-{
- m_persistent_types.insert(std::pair<const char*, clang::TypeDecl*>(name.GetCString(), type_decl));
-}
-
-clang::TypeDecl *
-ClangPersistentVariables::GetPersistentType (const ConstString &name)
-{
- PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString());
-
- if (i == m_persistent_types.end())
- return NULL;
- else
- return i->second;
-}
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
deleted file mode 100644
index 0da70e2..0000000
--- a/source/Expression/ClangUserExpression.cpp
+++ /dev/null
@@ -1,1172 +0,0 @@
-//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#include <cstdlib>
-#include <string>
-#include <map>
-
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Expression/ASTResultSynthesizer.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
-#include "lldb/Expression/ExpressionSourceCode.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Expression/Materializer.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadPlan.h"
-#include "lldb/Target/ThreadPlanCallUserExpression.h"
-
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-
-using namespace lldb_private;
-
-ClangUserExpression::ClangUserExpression (const char *expr,
- const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type) :
- ClangExpression (),
- m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
- m_stack_frame_top (LLDB_INVALID_ADDRESS),
- m_expr_text (expr),
- m_expr_prefix (expr_prefix ? expr_prefix : ""),
- m_language (language),
- m_transformed_text (),
- m_desired_type (desired_type),
- m_expr_decl_map(),
- m_execution_unit_sp(),
- m_materializer_ap(),
- m_result_synthesizer(),
- m_jit_module_wp(),
- m_enforce_valid_object (true),
- m_in_cplusplus_method (false),
- m_in_objectivec_method (false),
- m_in_static_method(false),
- m_needs_object_ptr (false),
- m_const_object (false),
- m_target (NULL),
- m_can_interpret (false),
- m_materialized_address (LLDB_INVALID_ADDRESS)
-{
- switch (m_language)
- {
- case lldb::eLanguageTypeC_plus_plus:
- m_allow_cxx = true;
- break;
- case lldb::eLanguageTypeObjC:
- m_allow_objc = true;
- break;
- case lldb::eLanguageTypeObjC_plus_plus:
- default:
- m_allow_cxx = true;
- m_allow_objc = true;
- break;
- }
-}
-
-ClangUserExpression::~ClangUserExpression ()
-{
- if (m_target)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- m_target->GetImages().Remove(jit_module_sp);
- }
-}
-
-clang::ASTConsumer *
-ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
- *m_target));
-
- return m_result_synthesizer.get();
-}
-
-void
-ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("ClangUserExpression::ScanContext()");
-
- m_target = exe_ctx.GetTargetPtr();
-
- if (!(m_allow_cxx || m_allow_objc))
- {
- if (log)
- log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
- return;
- }
-
- StackFrame *frame = exe_ctx.GetFramePtr();
- if (frame == NULL)
- {
- if (log)
- log->Printf(" [CUE::SC] Null stack frame");
- return;
- }
-
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
-
- if (!sym_ctx.function)
- {
- if (log)
- log->Printf(" [CUE::SC] Null function");
- return;
- }
-
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
-
- if (!function_block)
- {
- if (log)
- log->Printf(" [CUE::SC] Null function block");
- return;
- }
-
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
- if (!decl_context)
- {
- if (log)
- log->Printf(" [CUE::SC] Null decl context");
- return;
- }
-
- if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
- {
- if (m_allow_cxx && method_decl->isInstance())
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(thisErrorString);
- return;
- }
-
- lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
- if (!this_var_sp ||
- !this_var_sp->IsInScope(frame) ||
- !this_var_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(thisErrorString);
- return;
- }
- }
-
- m_in_cplusplus_method = true;
- m_needs_object_ptr = true;
- }
- }
- else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
- {
- if (m_allow_objc)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
- if (!self_variable_sp ||
- !self_variable_sp->IsInScope(frame) ||
- !self_variable_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(selfErrorString);
- return;
- }
- }
-
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
-
- if (!method_decl->isInstanceMethod())
- m_in_static_method = true;
- }
- }
- else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context))
- {
- // We might also have a function that said in the debug information that it captured an
- // object pointer. The best way to deal with getting to the ivars at present is by pretending
- // that this is a method of a class in whatever runtime the debug info says the object pointer
- // belongs to. Do that here.
-
- ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl);
- if (metadata && metadata->HasObjectPtr())
- {
- lldb::LanguageType language = metadata->GetObjectPtrLanguage();
- if (language == lldb::eLanguageTypeC_plus_plus)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(thisErrorString);
- return;
- }
-
- lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
- if (!this_var_sp ||
- !this_var_sp->IsInScope(frame) ||
- !this_var_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(thisErrorString);
- return;
- }
- }
-
- m_in_cplusplus_method = true;
- m_needs_object_ptr = true;
- }
- else if (language == lldb::eLanguageTypeObjC)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
- if (!self_variable_sp ||
- !self_variable_sp->IsInScope(frame) ||
- !self_variable_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- Type *self_type = self_variable_sp->GetType();
-
- if (!self_type)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- ClangASTType self_clang_type = self_type->GetClangForwardType();
-
- if (!self_clang_type)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- if (self_clang_type.IsObjCClassType())
- {
- return;
- }
- else if (self_clang_type.IsObjCObjectPointerType())
- {
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
- }
- else
- {
- err.SetErrorString(selfErrorString);
- return;
- }
- }
- else
- {
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
- }
- }
- }
- }
-}
-
-void
-ClangUserExpression::InstallContext (ExecutionContext &exe_ctx)
-{
- m_process_wp = exe_ctx.GetProcessSP();
-
- lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
-
- if (frame_sp)
- m_address = frame_sp->GetFrameCodeAddress();
-}
-
-bool
-ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
- lldb::TargetSP &target_sp,
- lldb::ProcessSP &process_sp,
- lldb::StackFrameSP &frame_sp)
-{
- lldb::ProcessSP expected_process_sp = m_process_wp.lock();
- process_sp = exe_ctx.GetProcessSP();
-
- if (process_sp != expected_process_sp)
- return false;
-
- process_sp = exe_ctx.GetProcessSP();
- target_sp = exe_ctx.GetTargetSP();
- frame_sp = exe_ctx.GetFrameSP();
-
- if (m_address.IsValid())
- {
- if (!frame_sp)
- return false;
- else
- return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
- }
-
- return true;
-}
-
-bool
-ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx)
-{
- lldb::TargetSP target_sp;
- lldb::ProcessSP process_sp;
- lldb::StackFrameSP frame_sp;
-
- return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
-}
-
-// This is a really nasty hack, meant to fix Objective-C expressions of the form
-// (int)[myArray count]. Right now, because the type information for count is
-// not available, [myArray count] returns id, which can't be directly cast to
-// int without causing a clang error.
-static void
-ApplyObjcCastHack(std::string &expr)
-{
-#define OBJC_CAST_HACK_FROM "(int)["
-#define OBJC_CAST_HACK_TO "(int)(long long)["
-
- size_t from_offset;
-
- while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
- expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
-
-#undef OBJC_CAST_HACK_TO
-#undef OBJC_CAST_HACK_FROM
-}
-
-// Another hack, meant to allow use of unichar despite it not being available in
-// the type information. Although we could special-case it in type lookup,
-// hopefully we'll figure out a way to #include the same environment as is
-// present in the original source file rather than try to hack specific type
-// definitions in as needed.
-//static void
-//ApplyUnicharHack(std::string &expr)
-//{
-//#define UNICHAR_HACK_FROM "unichar"
-//#define UNICHAR_HACK_TO "unsigned short"
-//
-// size_t from_offset;
-//
-// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
-// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
-//
-//#undef UNICHAR_HACK_TO
-//#undef UNICHAR_HACK_FROM
-//}
-
-bool
-ClangUserExpression::Parse (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Error err;
-
- InstallContext(exe_ctx);
-
- ScanContext(exe_ctx, err);
-
- if (!err.Success())
- {
- error_stream.Printf("warning: %s\n", err.AsCString());
- }
-
- StreamString m_transformed_stream;
-
- ////////////////////////////////////
- // Generate the expression
- //
-
- ApplyObjcCastHack(m_expr_text);
- //ApplyUnicharHack(m_expr_text);
-
- std::string prefix = m_expr_prefix;
-
- if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
- {
- const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = m_target->GetPersistentVariables().GetHandLoadedClangModules();
- ClangModulesDeclVendor::ModuleVector modules_for_macros;
-
- for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
- {
- modules_for_macros.push_back(module);
- }
-
- if (m_target->GetEnableAutoImportClangModules())
- {
- if (StackFrame *frame = exe_ctx.GetFramePtr())
- {
- if (Block *block = frame->GetFrameBlock())
- {
- SymbolContext sc;
-
- block->CalculateSymbolContext(&sc);
-
- if (sc.comp_unit)
- {
- StreamString error_stream;
-
- decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
- }
- }
- }
- }
- }
-
- std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
-
- lldb::LanguageType lang_type;
-
- if (m_in_cplusplus_method)
- lang_type = lldb::eLanguageTypeC_plus_plus;
- else if (m_in_objectivec_method)
- lang_type = lldb::eLanguageTypeObjC;
- else
- lang_type = lldb::eLanguageTypeC;
-
- if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
- {
- error_stream.PutCString ("error: couldn't construct expression body");
- return false;
- }
-
- if (log)
- log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
-
- ////////////////////////////////////
- // Set up the target and compiler
- //
-
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- {
- error_stream.PutCString ("error: invalid target\n");
- return false;
- }
-
- //////////////////////////
- // Parse the expression
- //
-
- m_materializer_ap.reset(new Materializer());
-
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
-
- class OnExit
- {
- public:
- typedef std::function <void (void)> Callback;
-
- OnExit (Callback const &callback) :
- m_callback(callback)
- {
- }
-
- ~OnExit ()
- {
- m_callback();
- }
- private:
- Callback m_callback;
- };
-
- OnExit on_exit([this]() { m_expr_decl_map.reset(); });
-
- if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
- {
- error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
-
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
- return false;
- }
-
- Process *process = exe_ctx.GetProcessPtr();
- ExecutionContextScope *exe_scope = process;
-
- if (!exe_scope)
- exe_scope = exe_ctx.GetTargetPtr();
-
- ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
-
- unsigned num_errors = parser.Parse (error_stream);
-
- if (num_errors)
- {
- error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
-
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
- return false;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////
- // Prepare the output of the parser for execution, evaluating it statically if possible
- //
-
- Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
- m_execution_unit_sp,
- exe_ctx,
- m_can_interpret,
- execution_policy);
-
- if (generate_debug_info)
- {
- lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
-
- if (jit_module_sp)
- {
- ConstString const_func_name(FunctionName());
- FileSpec jit_file;
- jit_file.GetFilename() = const_func_name;
- jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
- m_jit_module_wp = jit_module_sp;
- target->GetImages().Append(jit_module_sp);
- }
-// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
-// StreamFile strm (stdout, false);
-// if (jit_obj_file)
-// {
-// jit_obj_file->GetSectionList();
-// jit_obj_file->GetSymtab();
-// jit_obj_file->Dump(&strm);
-// }
-// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
-// if (jit_sym_vendor)
-// {
-// lldb_private::SymbolContextList sc_list;
-// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
-// sc_list.Dump(&strm, target);
-// jit_sym_vendor->Dump(&strm);
-// }
- }
-
- m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
-
- if (jit_error.Success())
- {
- if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
- m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
- return true;
- }
- else
- {
- const char *error_cstr = jit_error.AsCString();
- if (error_cstr && error_cstr[0])
- error_stream.Printf ("error: %s\n", error_cstr);
- else
- error_stream.Printf ("error: expression can't be interpreted or run\n");
- return false;
- }
-}
-
-static lldb::addr_t
-GetObjectPointer (lldb::StackFrameSP frame_sp,
- ConstString &object_name,
- Error &err)
-{
- err.Clear();
-
- if (!frame_sp)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- lldb::VariableSP var_sp;
- lldb::ValueObjectSP valobj_sp;
-
- valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
- lldb::eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var_sp,
- err);
-
- if (!err.Success() || !valobj_sp.get())
- return LLDB_INVALID_ADDRESS;
-
- lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- return ret;
-}
-
-bool
-ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address,
- lldb::addr_t &object_ptr,
- lldb::addr_t &cmd_ptr)
-{
- lldb::TargetSP target;
- lldb::ProcessSP process;
- lldb::StackFrameSP frame;
-
- if (!LockAndCheckContext(exe_ctx,
- target,
- process,
- frame))
- {
- error_stream.Printf("The context has changed before we could JIT the expression!\n");
- return false;
- }
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- if (m_needs_object_ptr)
- {
- ConstString object_name;
-
- if (m_in_cplusplus_method)
- {
- object_name.SetCString("this");
- }
- else if (m_in_objectivec_method)
- {
- object_name.SetCString("self");
- }
- else
- {
- error_stream.Printf("Need object pointer but don't know the language\n");
- return false;
- }
-
- Error object_ptr_error;
-
- object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- object_ptr = 0;
- }
-
- if (m_in_objectivec_method)
- {
- ConstString cmd_name("_cmd");
-
- cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- cmd_ptr = 0;
- }
- }
- }
-
- if (m_materialized_address == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
-
- IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
-
- m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
- m_materializer_ap->GetStructAlignment(),
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- policy,
- alloc_error);
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
- return false;
- }
- }
-
- struct_address = m_materialized_address;
-
- if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
-
- const size_t stack_frame_size = 512 * 1024;
-
- m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
- 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyHostOnly,
- alloc_error);
-
- m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
- return false;
- }
- }
-
- Error materialize_error;
-
- m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
-
- if (!materialize_error.Success())
- {
- error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
- return false;
- }
- }
- return true;
-}
-
-bool
-ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::ClangExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom,
- lldb::addr_t function_stack_top)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
-
- if (!m_dematerializer_sp)
- {
- error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
- return false;
- }
-
- Error dematerialize_error;
-
- m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
-
- if (!dematerialize_error.Success())
- {
- error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
- return false;
- }
-
- if (result)
- result->TransferAddress();
-
- m_dematerializer_sp.reset();
-
- return true;
-}
-
-lldb::ExpressionResults
-ClangUserExpression::Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- lldb::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ClangExpressionVariableSP &result)
-{
- // The expression log is quite verbose, and if you're just tracking the execution of the
- // expression, it's quite convenient to have these logs come out with the STEP log as well.
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
-
- lldb::addr_t object_ptr = 0;
- lldb::addr_t cmd_ptr = 0;
-
- if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
- {
- error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
- if (m_can_interpret)
- {
- llvm::Module *module = m_execution_unit_sp->GetModule();
- llvm::Function *function = m_execution_unit_sp->GetFunction();
-
- if (!module || !function)
- {
- error_stream.Printf("Supposed to interpret, but nothing is there");
- return lldb::eExpressionSetupError;
- }
-
- Error interpreter_error;
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr)
- {
- args.push_back(object_ptr);
-
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- function_stack_bottom = m_stack_frame_bottom;
- function_stack_top = m_stack_frame_top;
-
- IRInterpreter::Interpret (*module,
- *function,
- args,
- *m_execution_unit_sp.get(),
- interpreter_error,
- function_stack_bottom,
- function_stack_top,
- exe_ctx);
-
- if (!interpreter_error.Success())
- {
- error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
- return lldb::eExpressionDiscarded;
- }
- }
- else
- {
- if (!exe_ctx.HasThreadScope())
- {
- error_stream.Printf("ClangUserExpression::Execute called with no thread selected.");
- return lldb::eExpressionSetupError;
- }
-
- Address wrapper_address (m_jit_start_addr);
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr) {
- args.push_back(object_ptr);
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- args,
- options,
- shared_ptr_to_me));
-
- if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
- return lldb::eExpressionSetupError;
-
- ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
- lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
-
- function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
- function_stack_top = function_stack_pointer;
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
- call_plan_sp,
- options,
- error_stream);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
-
- if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
- {
- const char *error_desc = NULL;
-
- if (call_plan_sp)
- {
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
- }
- if (error_desc)
- error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
- else
- error_stream.PutCString ("Execution was interrupted.");
-
- if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
- || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
- error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
- else
- {
- if (execution_result == lldb::eExpressionHitBreakpoint)
- user_expression_plan->TransferExpressionOwnership();
- error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
- "use \"thread return -x\" to return to the state before expression evaluation.");
- }
-
- return execution_result;
- }
- else if (execution_result == lldb::eExpressionStoppedForDebug)
- {
- error_stream.PutCString ("Execution was halted at the first instruction of the expression "
- "function because \"debug\" was requested.\n"
- "Use \"thread return -x\" to return to the state before expression evaluation.");
- return execution_result;
- }
- else if (execution_result != lldb::eExpressionCompleted)
- {
- error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
- return execution_result;
- }
- }
-
- if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
- {
- return lldb::eExpressionCompleted;
- }
- else
- {
- return lldb::eExpressionResultUnavailable;
- }
- }
- else
- {
- error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
- return lldb::eExpressionSetupError;
- }
-}
-
-lldb::ExpressionResults
-ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
- const lldb::LanguageType language = options.GetLanguage();
- const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny;
- lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process == NULL || process->GetState() != lldb::eStateStopped)
- {
- if (execution_policy == eExecutionPolicyAlways)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- error.SetErrorString ("expression needed to run but couldn't");
-
- return execution_results;
- }
- }
-
- if (process == NULL || !process->CanJIT())
- execution_policy = eExecutionPolicyNever;
-
- const char *full_prefix = NULL;
- const char *option_prefix = options.GetPrefix();
- std::string full_prefix_storage;
- if (expr_prefix && option_prefix)
- {
- full_prefix_storage.assign(expr_prefix);
- full_prefix_storage.append(option_prefix);
- if (!full_prefix_storage.empty())
- full_prefix = full_prefix_storage.c_str();
- }
- else if (expr_prefix)
- full_prefix = expr_prefix;
- else
- full_prefix = option_prefix;
-
- lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type));
-
- StreamString error_stream;
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
-
- const bool keep_expression_in_memory = true;
- const bool generate_debug_info = options.GetGenerateDebugInfo();
-
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
- {
- error.SetErrorString ("expression interrupted by callback before parse");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- if (!user_expression_sp->Parse (error_stream,
- exe_ctx,
- execution_policy,
- keep_expression_in_memory,
- generate_debug_info))
- {
- execution_results = lldb::eExpressionParseError;
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- lldb::ClangExpressionVariableSP expr_result;
-
- if (execution_policy == eExecutionPolicyNever &&
- !user_expression_sp->CanInterpret())
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
- }
- else
- {
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- error_stream.GetString().clear();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
-
- execution_results = user_expression_sp->Execute (error_stream,
- exe_ctx,
- options,
- user_expression_sp,
- expr_result);
-
- if (options.GetResultIsInternal() && expr_result && process)
- {
- process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
- }
-
- if (execution_results != lldb::eExpressionCompleted)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- if (expr_result)
- {
- result_valobj_sp = expr_result->GetValueObject();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==",
- result_valobj_sp->GetValueAsCString());
- }
- else
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
-
- error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
- }
- }
- }
- }
-
- if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
- return lldb::eExpressionInterrupted;
- }
-
- if (result_valobj_sp.get() == NULL)
- {
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- }
-
- return execution_results;
-}
diff --git a/source/Expression/ClangUtilityFunction.cpp b/source/Expression/ClangUtilityFunction.cpp
deleted file mode 100644
index de5b0c1..0000000
--- a/source/Expression/ClangUtilityFunction.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-//===-- ClangUserExpression.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
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-// C++ Includes
-
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
-#include "lldb/Expression/ExpressionSourceCode.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Target.h"
-
-using namespace lldb_private;
-
-//------------------------------------------------------------------
-/// Constructor
-///
-/// @param[in] text
-/// The text of the function. Must be a full translation unit.
-///
-/// @param[in] name
-/// The name of the function, as used in the text.
-//------------------------------------------------------------------
-ClangUtilityFunction::ClangUtilityFunction (const char *text,
- const char *name) :
- ClangExpression (),
- m_expr_decl_map (),
- m_execution_unit_sp (),
- m_jit_module_wp (),
- m_function_text (ExpressionSourceCode::g_expression_prefix),
- m_function_name (name)
-{
- if (text && text[0])
- m_function_text.append (text);
-}
-
-ClangUtilityFunction::~ClangUtilityFunction ()
-{
- lldb::ProcessSP process_sp (m_jit_process_wp.lock());
- if (process_sp)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- process_sp->GetTarget().GetImages().Remove(jit_module_sp);
- }
-
-}
-
-//------------------------------------------------------------------
-/// Install the utility function into a process
-///
-/// @param[in] error_stream
-/// A stream to print parse errors and warnings to.
-///
-/// @param[in] exe_ctx
-/// The execution context to install the utility function to.
-///
-/// @return
-/// True on success (no errors); false otherwise.
-//------------------------------------------------------------------
-bool
-ClangUtilityFunction::Install (Stream &error_stream,
- ExecutionContext &exe_ctx)
-{
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
- {
- error_stream.PutCString("error: already installed\n");
- return false;
- }
-
- ////////////////////////////////////
- // Set up the target and compiler
- //
-
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- {
- error_stream.PutCString ("error: invalid target\n");
- return false;
- }
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (!process)
- {
- error_stream.PutCString ("error: invalid process\n");
- return false;
- }
-
- //////////////////////////
- // Parse the expression
- //
-
- bool keep_result_in_memory = false;
-
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
-
- if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
- {
- error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
- return false;
- }
-
- const bool generate_debug_info = true;
- ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info);
-
- unsigned num_errors = parser.Parse (error_stream);
-
- if (num_errors)
- {
- error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
-
- m_expr_decl_map.reset();
-
- return false;
- }
-
- //////////////////////////////////
- // JIT the output of the parser
- //
-
- bool can_interpret = false; // should stay that way
-
- Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
- m_execution_unit_sp,
- exe_ctx,
- can_interpret,
- eExecutionPolicyAlways);
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
- {
- m_jit_process_wp = process->shared_from_this();
- if (parser.GetGenerateDebugInfo())
- {
- lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
-
- if (jit_module_sp)
- {
- ConstString const_func_name(FunctionName());
- FileSpec jit_file;
- jit_file.GetFilename() = const_func_name;
- jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
- m_jit_module_wp = jit_module_sp;
- target->GetImages().Append(jit_module_sp);
- }
- }
- }
-
-#if 0
- // jingham: look here
- StreamFile logfile ("/tmp/exprs.txt", "a");
- logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
- m_jit_start_addr,
- m_function_name.c_str(),
- m_function_text.c_str());
-#endif
-
- m_expr_decl_map->DidParse();
-
- m_expr_decl_map.reset();
-
- if (jit_error.Success())
- {
- return true;
- }
- else
- {
- const char *error_cstr = jit_error.AsCString();
- if (error_cstr && error_cstr[0])
- error_stream.Printf ("error: %s\n", error_cstr);
- else
- error_stream.Printf ("error: expression can't be interpreted or run\n");
- return false;
- }
-}
-
-
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
index 9307c84..ebcc284 100644
--- a/source/Expression/DWARFExpression.cpp
+++ b/source/Expression/DWARFExpression.cpp
@@ -24,8 +24,8 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/VMRange.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
@@ -38,190 +38,27 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
+#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
+
using namespace lldb;
using namespace lldb_private;
-// TODO- why is this also defined (in a better way) in DWARFDefines.cpp?
-const char *
-DW_OP_value_to_name (uint32_t val)
+static lldb::addr_t
+ReadAddressFromDebugAddrSection(const DWARFCompileUnit* dwarf_cu, uint32_t index)
{
- static char invalid[100];
- switch (val) {
- case 0x03: return "DW_OP_addr";
- case 0x06: return "DW_OP_deref";
- case 0x08: return "DW_OP_const1u";
- case 0x09: return "DW_OP_const1s";
- case 0x0a: return "DW_OP_const2u";
- case 0x0b: return "DW_OP_const2s";
- case 0x0c: return "DW_OP_const4u";
- case 0x0d: return "DW_OP_const4s";
- case 0x0e: return "DW_OP_const8u";
- case 0x0f: return "DW_OP_const8s";
- case 0x10: return "DW_OP_constu";
- case 0x11: return "DW_OP_consts";
- case 0x12: return "DW_OP_dup";
- case 0x13: return "DW_OP_drop";
- case 0x14: return "DW_OP_over";
- case 0x15: return "DW_OP_pick";
- case 0x16: return "DW_OP_swap";
- case 0x17: return "DW_OP_rot";
- case 0x18: return "DW_OP_xderef";
- case 0x19: return "DW_OP_abs";
- case 0x1a: return "DW_OP_and";
- case 0x1b: return "DW_OP_div";
- case 0x1c: return "DW_OP_minus";
- case 0x1d: return "DW_OP_mod";
- case 0x1e: return "DW_OP_mul";
- case 0x1f: return "DW_OP_neg";
- case 0x20: return "DW_OP_not";
- case 0x21: return "DW_OP_or";
- case 0x22: return "DW_OP_plus";
- case 0x23: return "DW_OP_plus_uconst";
- case 0x24: return "DW_OP_shl";
- case 0x25: return "DW_OP_shr";
- case 0x26: return "DW_OP_shra";
- case 0x27: return "DW_OP_xor";
- case 0x2f: return "DW_OP_skip";
- case 0x28: return "DW_OP_bra";
- case 0x29: return "DW_OP_eq";
- case 0x2a: return "DW_OP_ge";
- case 0x2b: return "DW_OP_gt";
- case 0x2c: return "DW_OP_le";
- case 0x2d: return "DW_OP_lt";
- case 0x2e: return "DW_OP_ne";
- case 0x30: return "DW_OP_lit0";
- case 0x31: return "DW_OP_lit1";
- case 0x32: return "DW_OP_lit2";
- case 0x33: return "DW_OP_lit3";
- case 0x34: return "DW_OP_lit4";
- case 0x35: return "DW_OP_lit5";
- case 0x36: return "DW_OP_lit6";
- case 0x37: return "DW_OP_lit7";
- case 0x38: return "DW_OP_lit8";
- case 0x39: return "DW_OP_lit9";
- case 0x3a: return "DW_OP_lit10";
- case 0x3b: return "DW_OP_lit11";
- case 0x3c: return "DW_OP_lit12";
- case 0x3d: return "DW_OP_lit13";
- case 0x3e: return "DW_OP_lit14";
- case 0x3f: return "DW_OP_lit15";
- case 0x40: return "DW_OP_lit16";
- case 0x41: return "DW_OP_lit17";
- case 0x42: return "DW_OP_lit18";
- case 0x43: return "DW_OP_lit19";
- case 0x44: return "DW_OP_lit20";
- case 0x45: return "DW_OP_lit21";
- case 0x46: return "DW_OP_lit22";
- case 0x47: return "DW_OP_lit23";
- case 0x48: return "DW_OP_lit24";
- case 0x49: return "DW_OP_lit25";
- case 0x4a: return "DW_OP_lit26";
- case 0x4b: return "DW_OP_lit27";
- case 0x4c: return "DW_OP_lit28";
- case 0x4d: return "DW_OP_lit29";
- case 0x4e: return "DW_OP_lit30";
- case 0x4f: return "DW_OP_lit31";
- case 0x50: return "DW_OP_reg0";
- case 0x51: return "DW_OP_reg1";
- case 0x52: return "DW_OP_reg2";
- case 0x53: return "DW_OP_reg3";
- case 0x54: return "DW_OP_reg4";
- case 0x55: return "DW_OP_reg5";
- case 0x56: return "DW_OP_reg6";
- case 0x57: return "DW_OP_reg7";
- case 0x58: return "DW_OP_reg8";
- case 0x59: return "DW_OP_reg9";
- case 0x5a: return "DW_OP_reg10";
- case 0x5b: return "DW_OP_reg11";
- case 0x5c: return "DW_OP_reg12";
- case 0x5d: return "DW_OP_reg13";
- case 0x5e: return "DW_OP_reg14";
- case 0x5f: return "DW_OP_reg15";
- case 0x60: return "DW_OP_reg16";
- case 0x61: return "DW_OP_reg17";
- case 0x62: return "DW_OP_reg18";
- case 0x63: return "DW_OP_reg19";
- case 0x64: return "DW_OP_reg20";
- case 0x65: return "DW_OP_reg21";
- case 0x66: return "DW_OP_reg22";
- case 0x67: return "DW_OP_reg23";
- case 0x68: return "DW_OP_reg24";
- case 0x69: return "DW_OP_reg25";
- case 0x6a: return "DW_OP_reg26";
- case 0x6b: return "DW_OP_reg27";
- case 0x6c: return "DW_OP_reg28";
- case 0x6d: return "DW_OP_reg29";
- case 0x6e: return "DW_OP_reg30";
- case 0x6f: return "DW_OP_reg31";
- case 0x70: return "DW_OP_breg0";
- case 0x71: return "DW_OP_breg1";
- case 0x72: return "DW_OP_breg2";
- case 0x73: return "DW_OP_breg3";
- case 0x74: return "DW_OP_breg4";
- case 0x75: return "DW_OP_breg5";
- case 0x76: return "DW_OP_breg6";
- case 0x77: return "DW_OP_breg7";
- case 0x78: return "DW_OP_breg8";
- case 0x79: return "DW_OP_breg9";
- case 0x7a: return "DW_OP_breg10";
- case 0x7b: return "DW_OP_breg11";
- case 0x7c: return "DW_OP_breg12";
- case 0x7d: return "DW_OP_breg13";
- case 0x7e: return "DW_OP_breg14";
- case 0x7f: return "DW_OP_breg15";
- case 0x80: return "DW_OP_breg16";
- case 0x81: return "DW_OP_breg17";
- case 0x82: return "DW_OP_breg18";
- case 0x83: return "DW_OP_breg19";
- case 0x84: return "DW_OP_breg20";
- case 0x85: return "DW_OP_breg21";
- case 0x86: return "DW_OP_breg22";
- case 0x87: return "DW_OP_breg23";
- case 0x88: return "DW_OP_breg24";
- case 0x89: return "DW_OP_breg25";
- case 0x8a: return "DW_OP_breg26";
- case 0x8b: return "DW_OP_breg27";
- case 0x8c: return "DW_OP_breg28";
- case 0x8d: return "DW_OP_breg29";
- case 0x8e: return "DW_OP_breg30";
- case 0x8f: return "DW_OP_breg31";
- case 0x90: return "DW_OP_regx";
- case 0x91: return "DW_OP_fbreg";
- case 0x92: return "DW_OP_bregx";
- case 0x93: return "DW_OP_piece";
- case 0x94: return "DW_OP_deref_size";
- case 0x95: return "DW_OP_xderef_size";
- case 0x96: return "DW_OP_nop";
- case 0x97: return "DW_OP_push_object_address";
- case 0x98: return "DW_OP_call2";
- case 0x99: return "DW_OP_call4";
- case 0x9a: return "DW_OP_call_ref";
-// case DW_OP_APPLE_array_ref: return "DW_OP_APPLE_array_ref";
-// case DW_OP_APPLE_extern: return "DW_OP_APPLE_extern";
- case DW_OP_APPLE_uninit: return "DW_OP_APPLE_uninit";
-// case DW_OP_APPLE_assign: return "DW_OP_APPLE_assign";
-// case DW_OP_APPLE_address_of: return "DW_OP_APPLE_address_of";
-// case DW_OP_APPLE_value_of: return "DW_OP_APPLE_value_of";
-// case DW_OP_APPLE_deref_type: return "DW_OP_APPLE_deref_type";
-// case DW_OP_APPLE_expr_local: return "DW_OP_APPLE_expr_local";
-// case DW_OP_APPLE_constf: return "DW_OP_APPLE_constf";
-// case DW_OP_APPLE_scalar_cast: return "DW_OP_APPLE_scalar_cast";
-// case DW_OP_APPLE_clang_cast: return "DW_OP_APPLE_clang_cast";
-// case DW_OP_APPLE_clear: return "DW_OP_APPLE_clear";
-// case DW_OP_APPLE_error: return "DW_OP_APPLE_error";
- default:
- snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
- return invalid;
- }
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size);
}
-
//----------------------------------------------------------------------
// DWARFExpression constructor
//----------------------------------------------------------------------
-DWARFExpression::DWARFExpression() :
+DWARFExpression::DWARFExpression(DWARFCompileUnit* dwarf_cu) :
m_module_wp(),
m_data(),
+ m_dwarf_cu(dwarf_cu),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide (LLDB_INVALID_ADDRESS)
{
@@ -230,15 +67,21 @@ DWARFExpression::DWARFExpression() :
DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
m_module_wp(rhs.m_module_wp),
m_data(rhs.m_data),
+ m_dwarf_cu(rhs.m_dwarf_cu),
m_reg_kind (rhs.m_reg_kind),
m_loclist_slide(rhs.m_loclist_slide)
{
}
-DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
+ const DataExtractor& data,
+ DWARFCompileUnit* dwarf_cu,
+ lldb::offset_t data_offset,
+ lldb::offset_t data_length) :
m_module_wp(),
m_data(data, data_offset, data_length),
+ m_dwarf_cu(dwarf_cu),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide(LLDB_INVALID_ADDRESS)
{
@@ -624,6 +467,12 @@ DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t
case DW_OP_form_tls_address:
s->PutCString("DW_OP_form_tls_address"); // 0x9b
break;
+ case DW_OP_GNU_addr_index: // 0xfb
+ s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
+ break;
+ case DW_OP_GNU_const_index: // 0xfc
+ s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
+ break;
case DW_OP_GNU_push_tls_address:
s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0
break;
@@ -709,8 +558,14 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t
addr_t curr_base_addr = location_list_base_addr;
while (m_data.ValidOffset(offset))
{
- lldb::addr_t begin_addr_offset = m_data.GetAddress(&offset);
- lldb::addr_t end_addr_offset = m_data.GetAddress(&offset);
+ addr_t begin_addr_offset = LLDB_INVALID_ADDRESS;
+ addr_t end_addr_offset = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, begin_addr_offset, end_addr_offset))
+ break;
+
+ if (begin_addr_offset == 0 && end_addr_offset == 0)
+ break;
+
if (begin_addr_offset < end_addr_offset)
{
if (count > 0)
@@ -723,11 +578,6 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t
s->PutChar('}');
offset += location_length;
}
- else if (begin_addr_offset == 0 && end_addr_offset == 0)
- {
- // The end of the location list is marked by both the start and end offset being zero
- break;
- }
else
{
if ((m_data.GetAddressByteSize() == 4 && (begin_addr_offset == UINT32_MAX)) ||
@@ -1027,8 +877,10 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset,
case DW_OP_regx: // 0x90 1 ULEB128 register
case DW_OP_fbreg: // 0x91 1 SLEB128 offset
case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed
+ case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index
+ case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index
data.Skip_LEB128(&offset);
- return offset - data_offset;
+ return offset - data_offset;
// All opcodes that have a 2 ULEB (signed or unsigned) arguments
case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset
@@ -1070,6 +922,22 @@ DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) cons
else
++curr_op_addr_idx;
}
+ else if (op == DW_OP_GNU_addr_index)
+ {
+ uint64_t index = m_data.GetULEB128(&offset);
+ if (curr_op_addr_idx == op_addr_idx)
+ {
+ if (!m_dwarf_cu)
+ {
+ error = true;
+ break;
+ }
+
+ return ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
+ }
+ else
+ ++curr_op_addr_idx;
+ }
else
{
const offset_t op_arg_size = GetOpcodeDataSize (m_data, offset, op);
@@ -1104,7 +972,7 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr)
// So first we copy the data into a heap buffer
std::unique_ptr<DataBufferHeap> head_data_ap (new DataBufferHeap (m_data.GetDataStart(),
- m_data.GetByteSize()));
+ m_data.GetByteSize()));
// Make en encoder so we can write the address into the buffer using
// the correct byte order (endianness)
@@ -1150,20 +1018,21 @@ DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, ll
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
break;
- else
- {
- lo_pc += loclist_base_addr - m_loclist_slide;
- hi_pc += loclist_base_addr - m_loclist_slide;
- if (lo_pc <= addr && addr < hi_pc)
- return true;
+ lo_pc += loclist_base_addr - m_loclist_slide;
+ hi_pc += loclist_base_addr - m_loclist_slide;
- offset += m_data.GetU16(&offset);
- }
+ if (lo_pc <= addr && addr < hi_pc)
+ return true;
+
+ offset += m_data.GetU16(&offset);
}
}
return false;
@@ -1186,24 +1055,23 @@ DWARFExpression::GetLocation (addr_t base_addr, addr_t pc, lldb::offset_t &offse
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
- {
break;
- }
- else
- {
- lo_pc += curr_base_addr - m_loclist_slide;
- hi_pc += curr_base_addr - m_loclist_slide;
-
- length = m_data.GetU16(&offset);
-
- if (length > 0 && lo_pc <= pc && pc < hi_pc)
- return true;
- offset += length;
- }
+ lo_pc += curr_base_addr - m_loclist_slide;
+ hi_pc += curr_base_addr - m_loclist_slide;
+
+ length = m_data.GetU16(&offset);
+
+ if (length > 0 && lo_pc <= pc && pc < hi_pc)
+ return true;
+
+ offset += length;
}
}
offset = LLDB_INVALID_OFFSET;
@@ -1295,25 +1163,36 @@ DWARFExpression::Evaluate
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
- {
break;
- }
- else
- {
- lo_pc += curr_loclist_base_load_addr - m_loclist_slide;
- hi_pc += curr_loclist_base_load_addr - m_loclist_slide;
- uint16_t length = m_data.GetU16(&offset);
+ lo_pc += curr_loclist_base_load_addr - m_loclist_slide;
+ hi_pc += curr_loclist_base_load_addr - m_loclist_slide;
- if (length > 0 && lo_pc <= pc && pc < hi_pc)
- {
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
- }
- offset += length;
+ uint16_t length = m_data.GetU16(&offset);
+
+ if (length > 0 && lo_pc <= pc && pc < hi_pc)
+ {
+ return DWARFExpression::Evaluate (exe_ctx,
+ expr_locals,
+ decl_map,
+ reg_ctx,
+ module_sp,
+ m_data,
+ m_dwarf_cu,
+ offset,
+ length,
+ m_reg_kind,
+ initial_value_ptr,
+ result,
+ error_ptr);
}
+ offset += length;
}
}
if (error_ptr)
@@ -1322,7 +1201,19 @@ DWARFExpression::Evaluate
}
// Not a location list, just a single expression.
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx,
+ expr_locals,
+ decl_map,
+ reg_ctx,
+ module_sp,
+ m_data,
+ m_dwarf_cu,
+ 0,
+ m_data.GetByteSize(),
+ m_reg_kind,
+ initial_value_ptr,
+ result,
+ error_ptr);
}
@@ -1336,6 +1227,7 @@ DWARFExpression::Evaluate
RegisterContext *reg_ctx,
lldb::ModuleSP module_sp,
const DataExtractor& opcodes,
+ DWARFCompileUnit* dwarf_cu,
const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length,
const lldb::RegisterKind reg_kind,
@@ -2711,7 +2603,7 @@ DWARFExpression::Evaluate
return false;
}
}
- else if (!stack.empty())
+ else
{
// If this is the second or later piece there should be a value on the stack
if (pieces.GetBuffer().GetByteSize() != op_piece_offset)
@@ -2950,6 +2842,69 @@ DWARFExpression::Evaluate
}
break;
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_addr_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an address to the stack from the .debug_addr
+ // section with the base address specified by the DW_AT_addr_base
+ // attribute and the 0 based index is the ULEB128 encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_addr_index:
+ {
+ if (!dwarf_cu)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("DW_OP_GNU_addr_index found without a compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ uint64_t value = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size);
+ stack.push_back(Scalar(value));
+ stack.back().SetValueType(Value::eValueTypeFileAddress);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_const_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an constant with the size of a machine address to
+ // the stack from the .debug_addr section with the base address specified
+ // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128
+ // encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_const_index:
+ {
+ if (!dwarf_cu)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("DW_OP_GNU_const_index found without a compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ const DWARFDataExtractor& debug_addr = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data();
+ switch (index_size)
+ {
+ case 4:
+ stack.push_back(Scalar(debug_addr.GetU32(&offset)));
+ break;
+ case 8:
+ stack.push_back(Scalar(debug_addr.GetU64(&offset)));
+ break;
+ default:
+ assert(false && "Unhandled index size");
+ return false;
+ }
+ }
+ break;
+
default:
if (log)
log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op));
@@ -2990,3 +2945,255 @@ DWARFExpression::Evaluate
return true; // Return true on success
}
+size_t
+DWARFExpression::LocationListSize(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset)
+{
+ const lldb::offset_t debug_loc_offset = offset;
+ while (debug_loc_data.ValidOffset(offset))
+ {
+ lldb::addr_t start_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, start_addr, end_addr))
+ break;
+
+ if (start_addr == 0 && end_addr == 0)
+ break;
+
+ uint16_t loc_length = debug_loc_data.GetU16(&offset);
+ offset += loc_length;
+ }
+
+ if (offset > debug_loc_offset)
+ return offset - debug_loc_offset;
+ return 0;
+}
+
+bool
+DWARFExpression::AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t* offset_ptr,
+ lldb::addr_t& low_pc,
+ lldb::addr_t& high_pc)
+{
+ if (!debug_loc_data.ValidOffset(*offset_ptr))
+ return false;
+
+ switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat())
+ {
+ case NonLocationList:
+ return false;
+ case RegularLocationList:
+ low_pc = debug_loc_data.GetAddress(offset_ptr);
+ high_pc = debug_loc_data.GetAddress(offset_ptr);
+ return true;
+ case SplitDwarfLocationList:
+ switch (debug_loc_data.GetU8(offset_ptr))
+ {
+ case DW_LLE_end_of_list_entry:
+ return false;
+ case DW_LLE_start_end_entry:
+ {
+ uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
+ low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ index = debug_loc_data.GetULEB128(offset_ptr);
+ high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ return true;
+ }
+ case DW_LLE_start_length_entry:
+ {
+ uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
+ low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ uint32_t length = debug_loc_data.GetU32(offset_ptr);
+ high_pc = low_pc + length;
+ return true;
+ }
+ default:
+ // Not supported entry type
+ return false;
+ }
+ }
+ assert (false && "Not supported location list type");
+ return false;
+}
+
+static bool
+print_dwarf_exp_op (Stream &s,
+ const DataExtractor& data,
+ lldb::offset_t *offset_ptr,
+ int address_size,
+ int dwarf_ref_size)
+{
+ uint8_t opcode = data.GetU8(offset_ptr);
+ DRC_class opcode_class;
+ uint64_t uint;
+ int64_t sint;
+
+ int size;
+
+ opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
+
+ s.Printf("%s ", DW_OP_value_to_name (opcode));
+
+ /* Does this take zero parameters? If so we can shortcut this function. */
+ if (opcode_class == DRC_ZEROOPERANDS)
+ return true;
+
+ if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
+ {
+ uint = data.GetULEB128(offset_ptr);
+ sint = data.GetSLEB128(offset_ptr);
+ s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
+ return true;
+ }
+ if (opcode_class != DRC_ONEOPERAND)
+ {
+ s.Printf("UNKNOWN OP %u", opcode);
+ return false;
+ }
+
+ switch (opcode)
+ {
+ case DW_OP_addr: size = address_size; break;
+ case DW_OP_const1u: size = 1; break;
+ case DW_OP_const1s: size = -1; break;
+ case DW_OP_const2u: size = 2; break;
+ case DW_OP_const2s: size = -2; break;
+ case DW_OP_const4u: size = 4; break;
+ case DW_OP_const4s: size = -4; break;
+ case DW_OP_const8u: size = 8; break;
+ case DW_OP_const8s: size = -8; break;
+ case DW_OP_constu: size = 128; break;
+ case DW_OP_consts: size = -128; break;
+ case DW_OP_fbreg: size = -128; break;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ size = -128; break;
+ case DW_OP_pick:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ size = 1; break;
+ case DW_OP_skip:
+ case DW_OP_bra:
+ size = -2; break;
+ case DW_OP_call2:
+ size = 2; break;
+ case DW_OP_call4:
+ size = 4; break;
+ case DW_OP_call_ref:
+ size = dwarf_ref_size; break;
+ case DW_OP_piece:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_GNU_addr_index:
+ case DW_OP_GNU_const_index:
+ size = 128; break;
+ default:
+ s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
+ return true;
+ }
+
+ switch (size)
+ {
+ case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break;
+ case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break;
+ case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break;
+ case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break;
+ case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break;
+ }
+
+ return false;
+}
+
+bool
+DWARFExpression::PrintDWARFExpression(Stream &s,
+ const DataExtractor& data,
+ int address_size,
+ int dwarf_ref_size,
+ bool location_expression)
+{
+ int op_count = 0;
+ lldb::offset_t offset = 0;
+ while (data.ValidOffset(offset))
+ {
+ if (location_expression && op_count > 0)
+ return false;
+ if (op_count > 0)
+ s.PutCString(", ");
+ if (!print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size))
+ return false;
+ op_count++;
+ }
+
+ return true;
+}
+
+void
+DWARFExpression::PrintDWARFLocationList(Stream &s,
+ const DWARFCompileUnit* cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset)
+{
+ uint64_t start_addr, end_addr;
+ uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
+ s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
+ dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+ while (debug_loc_data.ValidOffset(offset))
+ {
+ start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+ end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+
+ if (start_addr == 0 && end_addr == 0)
+ break;
+
+ s.PutCString("\n ");
+ s.Indent();
+ if (cu)
+ s.AddressRange (start_addr + base_addr,
+ end_addr + base_addr,
+ cu->GetAddressByteSize(),
+ NULL,
+ ": ");
+ uint32_t loc_length = debug_loc_data.GetU16(&offset);
+
+ DataExtractor locationData(debug_loc_data, offset, loc_length);
+ PrintDWARFExpression (s, locationData, addr_size, 4, false);
+ offset += loc_length;
+ }
+}
diff --git a/source/Expression/Expression.cpp b/source/Expression/Expression.cpp
new file mode 100644
index 0000000..e5dd9c0
--- /dev/null
+++ b/source/Expression/Expression.cpp
@@ -0,0 +1,32 @@
+//===-- Expression.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/Expression.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+Expression::Expression (Target &target) :
+ m_target_wp (target.shared_from_this()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ // Can't make any kind of expression without a target.
+ assert (m_target_wp.lock());
+}
+
+Expression::Expression (ExecutionContextScope &exe_scope) :
+ m_target_wp (exe_scope.CalculateTarget()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ assert (m_target_wp.lock());
+}
+
diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp
index 9a42510..c4ab7a9 100644
--- a/source/Expression/ExpressionSourceCode.cpp
+++ b/source/Expression/ExpressionSourceCode.cpp
@@ -10,9 +10,12 @@
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/StackFrame.h"
@@ -56,6 +59,121 @@ extern "C"
}
)";
+namespace {
+
+class AddMacroState
+{
+ enum State
+ {
+ CURRENT_FILE_NOT_YET_PUSHED,
+ CURRENT_FILE_PUSHED,
+ CURRENT_FILE_POPPED
+ };
+
+public:
+ AddMacroState(const FileSpec &current_file, const uint32_t current_file_line)
+ : m_state(CURRENT_FILE_NOT_YET_PUSHED),
+ m_current_file(current_file),
+ m_current_file_line(current_file_line)
+ { }
+
+ void
+ StartFile(const FileSpec &file)
+ {
+ m_file_stack.push_back(file);
+ if (file == m_current_file)
+ m_state = CURRENT_FILE_PUSHED;
+ }
+
+ void
+ EndFile()
+ {
+ if (m_file_stack.size() == 0)
+ return;
+
+ FileSpec old_top = m_file_stack.back();
+ m_file_stack.pop_back();
+ if (old_top == m_current_file)
+ m_state = CURRENT_FILE_POPPED;
+ }
+
+ // An entry is valid if it occurs before the current line in
+ // the current file.
+ bool
+ IsValidEntry(uint32_t line)
+ {
+ switch (m_state)
+ {
+ case CURRENT_FILE_NOT_YET_PUSHED:
+ return true;
+ case CURRENT_FILE_POPPED:
+ return false;
+ case CURRENT_FILE_PUSHED:
+ // If we are in file included in the current file,
+ // the entry should be added.
+ if (m_file_stack.back() != m_current_file)
+ return true;
+
+ if (line >= m_current_file_line)
+ return false;
+ else
+ return true;
+ }
+ }
+
+private:
+ std::vector<FileSpec> m_file_stack;
+ State m_state;
+ FileSpec m_current_file;
+ uint32_t m_current_file_line;
+};
+
+} // anonymous namespace
+
+static void
+AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
+{
+ if (dm == nullptr)
+ return;
+
+ for (size_t i = 0; i < dm->GetNumMacroEntries(); i++)
+ {
+ const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
+ uint32_t line;
+
+ switch (entry.GetType())
+ {
+ case DebugMacroEntry::DEFINE:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
+ else
+ return;
+ break;
+ case DebugMacroEntry::UNDEF:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
+ else
+ return;
+ break;
+ case DebugMacroEntry::START_FILE:
+ line = entry.GetLineNumber();
+ if (state.IsValidEntry(line))
+ state.StartFile(entry.GetFileSpec(comp_unit));
+ else
+ return;
+ break;
+ case DebugMacroEntry::END_FILE:
+ state.EndFile();
+ break;
+ case DebugMacroEntry::INDIRECT:
+ AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
+ break;
+ default:
+ // This is an unknown/invalid entry. Ignore.
+ break;
+ }
+ }
+}
bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const
{
@@ -82,7 +200,8 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
{
- const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = target->GetPersistentVariables().GetHandLoadedClangModules();
+ ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
@@ -118,6 +237,23 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
}
}
+
+ StreamString debug_macros_stream;
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ {
+ const SymbolContext &sc = frame->GetSymbolContext(
+ lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
+
+ if (sc.comp_unit && sc.line_entry.IsValid())
+ {
+ DebugMacros *dm = sc.comp_unit->GetDebugMacros();
+ if (dm)
+ {
+ AddMacroState state(sc.line_entry.file, sc.line_entry.line);
+ AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
+ }
+ }
+ }
if (m_wrap)
{
@@ -133,8 +269,9 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
StreamString wrap_stream;
- wrap_stream.Printf("%s\n%s\n%s\n%s\n",
+ wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",
module_macros.c_str(),
+ debug_macros_stream.GetData(),
g_expression_prefix,
target_specific_defines,
m_prefix.c_str());
diff --git a/source/Expression/ExpressionVariable.cpp b/source/Expression/ExpressionVariable.cpp
new file mode 100644
index 0000000..8bef60f
--- /dev/null
+++ b/source/Expression/ExpressionVariable.cpp
@@ -0,0 +1,36 @@
+//===-- ExpressionVariable.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ExpressionVariable.h"
+
+using namespace lldb_private;
+
+ExpressionVariable::~ExpressionVariable()
+{
+}
+
+uint8_t *
+ExpressionVariable::GetValueBytes()
+{
+ const size_t byte_size = m_frozen_sp->GetByteSize();
+ if (byte_size > 0)
+ {
+ if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
+ {
+ m_frozen_sp->GetValue().ResizeData(byte_size);
+ m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
+ }
+ return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
+ }
+ return NULL;
+}
+
+PersistentExpressionState::~PersistentExpressionState ()
+{
+}
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/FunctionCaller.cpp
index b438dac..ddc378d 100644
--- a/source/Expression/ClangFunction.cpp
+++ b/source/Expression/FunctionCaller.cpp
@@ -1,4 +1,4 @@
-//===-- ClangFunction.cpp ---------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,15 +11,6 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/IR/Module.h"
// Project includes
#include "lldb/Core/DataExtractor.h"
@@ -28,12 +19,9 @@
#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Expression/ASTStructExtractor.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
@@ -47,16 +35,17 @@
using namespace lldb_private;
//----------------------------------------------------------------------
-// ClangFunction constructor
+// FunctionCaller constructor
//----------------------------------------------------------------------
-ClangFunction::ClangFunction
+FunctionCaller::FunctionCaller
(
ExecutionContextScope &exe_scope,
- const ClangASTType &return_type,
+ const CompilerType &return_type,
const Address& functionAddress,
const ValueList &arg_value_list,
const char *name
) :
+ Expression (exe_scope),
m_execution_unit_sp(),
m_parser(),
m_jit_module_wp(),
@@ -72,41 +61,14 @@ ClangFunction::ClangFunction
m_JITted (false)
{
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
- // Can't make a ClangFunction without a process.
+ // Can't make a FunctionCaller without a process.
assert (m_jit_process_wp.lock());
}
-ClangFunction::ClangFunction
-(
- ExecutionContextScope &exe_scope,
- Function &function,
- ClangASTContext *ast_context,
- const ValueList &arg_value_list,
- const char *name
-) :
- m_name (name ? name : "<unknown>"),
- m_function_ptr (&function),
- m_function_addr (),
- m_function_return_type (),
- m_wrapper_function_name ("__lldb_function_caller"),
- m_wrapper_struct_name ("__lldb_caller_struct"),
- m_wrapper_args_addrs (),
- m_arg_values (arg_value_list),
- m_compiled (false),
- m_JITted (false)
-{
- m_jit_process_wp = exe_scope.CalculateProcess();
- // Can't make a ClangFunction without a process.
- assert (m_jit_process_wp.lock());
-
- m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress();
- m_function_return_type = m_function_ptr->GetClangType().GetFunctionReturnType();
-}
-
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ClangFunction::~ClangFunction()
+FunctionCaller::~FunctionCaller()
{
lldb::ProcessSP process_sp (m_jit_process_wp.lock());
if (process_sp)
@@ -117,147 +79,8 @@ ClangFunction::~ClangFunction()
}
}
-unsigned
-ClangFunction::CompileFunction (Stream &errors)
-{
- if (m_compiled)
- return 0;
-
- // FIXME: How does clang tell us there's no return value? We need to handle that case.
- unsigned num_errors = 0;
-
- std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
-
- // Cons up the function we're going to wrap our call in, then compile it...
- // We declare the function "extern "C"" because the compiler might be in C++
- // mode which would mangle the name and then we couldn't find it again...
- m_wrapper_function_text.clear();
- m_wrapper_function_text.append ("extern \"C\" void ");
- m_wrapper_function_text.append (m_wrapper_function_name);
- m_wrapper_function_text.append (" (void *input)\n{\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" \n {\n");
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" (*fn_ptr) (");
-
- // Get the number of arguments. If we have a function type and it is prototyped,
- // trust that, otherwise use the values we were given.
-
- // FIXME: This will need to be extended to handle Variadic functions. We'll need
- // to pull the defined arguments out of the function, then add the types from the
- // arguments list for the variable arguments.
-
- uint32_t num_args = UINT32_MAX;
- bool trust_function = false;
- // GetArgumentCount returns -1 for an unprototyped function.
- ClangASTType function_clang_type;
- if (m_function_ptr)
- {
- function_clang_type = m_function_ptr->GetClangType();
- if (function_clang_type)
- {
- int num_func_args = function_clang_type.GetFunctionArgumentCount();
- if (num_func_args >= 0)
- {
- trust_function = true;
- num_args = num_func_args;
- }
- }
- }
-
- if (num_args == UINT32_MAX)
- num_args = m_arg_values.GetSize();
-
- std::string args_buffer; // This one stores the definition of all the args in "struct caller".
- std::string args_list_buffer; // This one stores the argument list called from the structure.
- for (size_t i = 0; i < num_args; i++)
- {
- std::string type_name;
-
- if (trust_function)
- {
- type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
- }
- else
- {
- ClangASTType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetClangType ();
- if (clang_qual_type)
- {
- type_name = clang_qual_type.GetTypeName().AsCString("");
- }
- else
- {
- errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
- return 1;
- }
- }
-
- m_wrapper_function_text.append (type_name);
- if (i < num_args - 1)
- m_wrapper_function_text.append (", ");
-
- char arg_buf[32];
- args_buffer.append (" ");
- args_buffer.append (type_name);
- snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
- args_buffer.push_back (' ');
- args_buffer.append (arg_buf);
- args_buffer.append (";\n");
-
- args_list_buffer.append ("__lldb_fn_data->");
- args_list_buffer.append (arg_buf);
- if (i < num_args - 1)
- args_list_buffer.append (", ");
-
- }
- m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
-
- m_wrapper_function_text.append (args_buffer);
-
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" return_value;");
- m_wrapper_function_text.append ("\n };\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" *) input;\n");
-
- m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
- m_wrapper_function_text.append (args_list_buffer);
- m_wrapper_function_text.append (");\n}\n");
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (log)
- log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
-
- // Okay, now compile this expression
-
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
- if (jit_process_sp)
- {
- const bool generate_debug_info = true;
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
-
- num_errors = m_parser->Parse (errors);
- }
- else
- {
- errors.Printf("no process - unable to inject function");
- num_errors = 1;
- }
-
- m_compiled = (num_errors == 0);
-
- if (!m_compiled)
- return num_errors;
-
- return num_errors;
-}
-
bool
-ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
+FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
Process *process = exe_ctx.GetProcessPtr();
@@ -310,18 +133,17 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
}
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
- return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors);
+ return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors);
}
// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
- Address function_address,
- ValueList &arg_values,
+ ValueList &arg_values,
Stream &errors)
{
// All the information to reconstruct the struct is provided by the
@@ -333,7 +155,6 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
Error error;
- using namespace clang;
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
Process *process = exe_ctx.GetProcessPtr();
@@ -363,7 +184,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
// TODO: verify fun_addr needs to be a callable address
- Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
+ Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
uint64_t first_offset = m_member_offsets[0];
process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
@@ -391,7 +212,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
arg_value->GetContextType() == Value::eContextTypeInvalid &&
- arg_value->GetClangType().IsPointerType())
+ arg_value->GetCompilerType().IsPointerType())
continue;
const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
@@ -404,10 +225,8 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
- using namespace clang;
-
if (CompileFunction(errors) != 0)
return false;
if (!WriteFunctionWrapper(exe_ctx, errors))
@@ -423,7 +242,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
}
lldb::ThreadPlanSP
-ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
+FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
const EvaluateExpressionOptions &options,
Stream &errors)
@@ -431,7 +250,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
+ log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
// FIXME: Use the errors Stream for better error reporting.
Thread *thread = exe_ctx.GetThreadPtr();
@@ -449,7 +268,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
wrapper_address,
- ClangASTType(),
+ CompilerType(),
args,
options));
new_plan_sp->SetIsMasterPlan(true);
@@ -458,17 +277,17 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
+FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
// Read the return value - it is the last field in the struct:
// FIXME: How does clang tell us there's no return value? We need to handle that case.
- // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject
+ // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject
// to fetch the value. That way we can fetch any values we need.
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
+ log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
Process *process = exe_ctx.GetProcessPtr();
@@ -486,13 +305,13 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
if (error.Fail())
return false;
- ret_value.SetClangType(m_function_return_type);
+ ret_value.SetCompilerType(m_function_return_type);
ret_value.SetValueType(Value::eValueTypeScalar);
return true;
}
void
-ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
+FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
{
std::list<lldb::addr_t>::iterator pos;
pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
@@ -503,17 +322,16 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
}
lldb::ExpressionResults
-ClangFunction::ExecuteFunction(
+FunctionCaller::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
const EvaluateExpressionOptions &options,
Stream &errors,
Value &results)
{
- using namespace clang;
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
- // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
+ // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore
// breakpoints, unwind on error, and don't try to debug it.
EvaluateExpressionOptions real_options = options;
real_options.SetDebug(false);
@@ -539,7 +357,7 @@ ClangFunction::ExecuteFunction(
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
args_addr,
@@ -562,11 +380,11 @@ ClangFunction::ExecuteFunction(
{
if (return_value != lldb::eExpressionCompleted)
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
}
else
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
}
}
@@ -586,11 +404,3 @@ ClangFunction::ExecuteFunction(
return lldb::eExpressionCompleted;
}
-
-clang::ASTConsumer *
-ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this));
-
- return m_struct_extractor.get();
-}
diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp
index aa5d28b..30d7f63 100644
--- a/source/Expression/IRDynamicChecks.cpp
+++ b/source/Expression/IRDynamicChecks.cpp
@@ -1,4 +1,4 @@
-//===-- IRDynamicChecks.cpp -------------------------------------------*- C++ -*-===//
+//===-- IRDynamicChecks.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,28 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Value.h"
+
+// Project includes
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
-
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/Value.h"
+#include "lldb/Target/Target.h"
using namespace llvm;
using namespace lldb_private;
@@ -40,20 +45,22 @@ static const char g_valid_pointer_check_text[] =
" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
"}";
-DynamicCheckerFunctions::DynamicCheckerFunctions ()
-{
-}
+DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
-DynamicCheckerFunctions::~DynamicCheckerFunctions ()
-{
-}
+DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
bool
DynamicCheckerFunctions::Install(Stream &error_stream,
ExecutionContext &exe_ctx)
{
- m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text,
- VALID_POINTER_CHECK_NAME));
+ Error error;
+ m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text,
+ lldb::eLanguageTypeC,
+ VALID_POINTER_CHECK_NAME,
+ error));
+ if (error.Fail())
+ return false;
+
if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
return false;
@@ -80,12 +87,12 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa
{
// FIXME: We have to get the checkers to know why they scotched the call in more detail,
// so we can print a better message here.
- if (m_valid_pointer_check.get() != NULL && m_valid_pointer_check->ContainsAddress(addr))
+ if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr))
{
message.Printf ("Attempted to dereference an invalid pointer.");
return true;
}
- else if (m_objc_object_check.get() != NULL && m_objc_object_check->ContainsAddress(addr))
+ else if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr))
{
message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector");
return true;
@@ -93,7 +100,6 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa
return false;
}
-
static std::string
PrintValue(llvm::Value *V, bool truncate = false)
{
@@ -146,14 +152,12 @@ public:
DynamicCheckerFunctions &checker_functions) :
m_module(module),
m_checker_functions(checker_functions),
- m_i8ptr_ty(NULL),
- m_intptr_ty(NULL)
+ m_i8ptr_ty(nullptr),
+ m_intptr_ty(nullptr)
{
}
- virtual~Instrumenter ()
- {
- }
+ virtual ~Instrumenter() = default;
//------------------------------------------------------------------
/// Inspect a function to find instructions to instrument
@@ -187,6 +191,7 @@ public:
return true;
}
+
protected:
//------------------------------------------------------------------
/// Add instrumentation to a single instruction
@@ -344,6 +349,7 @@ protected:
InstVector m_to_instrument; ///< List of instructions the inspector found
llvm::Module &m_module; ///< The module which is being instrumented
DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process
+
private:
PointerType *m_i8ptr_ty;
IntegerType *m_intptr_ty;
@@ -355,15 +361,14 @@ public:
ValidPointerChecker (llvm::Module &module,
DynamicCheckerFunctions &checker_functions) :
Instrumenter(module, checker_functions),
- m_valid_pointer_check_func(NULL)
+ m_valid_pointer_check_func(nullptr)
{
}
- virtual ~ValidPointerChecker ()
- {
- }
-private:
- bool InstrumentInstruction(llvm::Instruction *inst)
+ ~ValidPointerChecker() override = default;
+
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -374,7 +379,7 @@ private:
if (!m_valid_pointer_check_func)
m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
- llvm::Value *dereferenced_ptr = NULL;
+ llvm::Value *dereferenced_ptr = nullptr;
if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
dereferenced_ptr = li->getPointerOperand();
@@ -406,7 +411,7 @@ private:
return true;
}
- bool InspectInstruction(llvm::Instruction &i)
+ bool InspectInstruction(llvm::Instruction &i) override
{
if (dyn_cast<llvm::LoadInst> (&i) ||
dyn_cast<llvm::StoreInst> (&i))
@@ -415,6 +420,7 @@ private:
return true;
}
+private:
llvm::Value *m_valid_pointer_check_func;
};
@@ -424,14 +430,11 @@ public:
ObjcObjectChecker(llvm::Module &module,
DynamicCheckerFunctions &checker_functions) :
Instrumenter(module, checker_functions),
- m_objc_object_check_func(NULL)
+ m_objc_object_check_func(nullptr)
{
}
- virtual
- ~ObjcObjectChecker ()
- {
- }
+ ~ObjcObjectChecker() override = default;
enum msgSend_type
{
@@ -444,13 +447,13 @@ public:
std::map <llvm::Instruction *, msgSend_type> msgSend_types;
-private:
- bool InstrumentInstruction(llvm::Instruction *inst)
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override
{
CallInst *call_inst = dyn_cast<CallInst>(inst);
if (!call_inst)
- return false; // call_inst really shouldn't be NULL, because otherwise InspectInstruction wouldn't have registered it
+ return false; // call_inst really shouldn't be nullptr, because otherwise InspectInstruction wouldn't have registered it
if (!m_objc_object_check_func)
m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress());
@@ -504,7 +507,7 @@ private:
return true;
}
- bool InspectInstruction(llvm::Instruction &i)
+ bool InspectInstruction(llvm::Instruction &i) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -593,6 +596,7 @@ private:
return true;
}
+private:
llvm::Value *m_objc_object_check_func;
};
@@ -604,9 +608,7 @@ IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
{
}
-IRDynamicChecks::~IRDynamicChecks()
-{
-}
+IRDynamicChecks::~IRDynamicChecks() = default;
bool
IRDynamicChecks::runOnModule(llvm::Module &M)
@@ -623,7 +625,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
return false;
}
- if (m_checker_functions.m_valid_pointer_check.get())
+ if (m_checker_functions.m_valid_pointer_check)
{
ValidPointerChecker vpc(M, m_checker_functions);
@@ -634,7 +636,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
return false;
}
- if (m_checker_functions.m_objc_object_check.get())
+ if (m_checker_functions.m_objc_object_check)
{
ObjcObjectChecker ooc(M, m_checker_functions);
@@ -650,7 +652,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
std::string s;
raw_string_ostream oss(s);
- M.print(oss, NULL);
+ M.print(oss, nullptr);
oss.flush();
diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp
index 59c7fb6..3f19c50 100644
--- a/source/Expression/IRExecutionUnit.cpp
+++ b/source/Expression/IRExecutionUnit.cpp
@@ -50,10 +50,12 @@ IRExecutionUnit::WriteNow (const uint8_t *bytes,
size_t size,
Error &error)
{
+ const bool zero_memory = false;
lldb::addr_t allocation_process_addr = Malloc (size,
8,
lldb::ePermissionsWritable | lldb::ePermissionsReadable,
eAllocationPolicyMirror,
+ zero_memory,
error);
if (!error.Success())
@@ -432,6 +434,13 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
}
}
+ else
+ {
+ record.dump(log);
+
+ DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8);
+ my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8);
+ }
}
}
@@ -488,6 +497,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE
sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
else if (dwarf_name.equals("aranges"))
sect_type = lldb::eSectionTypeDWARFDebugAranges;
+ else if (dwarf_name.equals("addr"))
+ sect_type = lldb::eSectionTypeDWARFDebugAddr;
break;
case 'f':
@@ -522,6 +533,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE
case 's':
if (dwarf_name.equals("str"))
sect_type = lldb::eSectionTypeDWARFDebugStr;
+ else if (dwarf_name.equals("str_offsets"))
+ sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
break;
case 'r':
@@ -789,6 +802,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
{
case lldb::eSectionTypeInvalid:
case lldb::eSectionTypeDWARFDebugAbbrev:
+ case lldb::eSectionTypeDWARFDebugAddr:
case lldb::eSectionTypeDWARFDebugAranges:
case lldb::eSectionTypeDWARFDebugFrame:
case lldb::eSectionTypeDWARFDebugInfo:
@@ -799,6 +813,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
case lldb::eSectionTypeDWARFDebugPubTypes:
case lldb::eSectionTypeDWARFDebugRanges:
case lldb::eSectionTypeDWARFDebugStr:
+ case lldb::eSectionTypeDWARFDebugStrOffsets:
case lldb::eSectionTypeDWARFAppleNames:
case lldb::eSectionTypeDWARFAppleTypes:
case lldb::eSectionTypeDWARFAppleNamespaces:
@@ -806,10 +821,12 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
err.Clear();
break;
default:
+ const bool zero_memory = false;
record.m_process_address = Malloc (record.m_size,
record.m_alignment,
record.m_permissions,
eAllocationPolicyProcessOnly,
+ zero_memory,
err);
break;
}
@@ -877,12 +894,13 @@ IRExecutionUnit::AllocationRecord::dump (Log *log)
if (!log)
return;
- log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
+ log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
(unsigned long long)m_host_address,
(unsigned long long)m_size,
(unsigned long long)m_process_address,
(unsigned)m_alignment,
- (unsigned)m_section_id);
+ (unsigned)m_section_id,
+ m_name.c_str());
}
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
deleted file mode 100644
index cf2a93b..0000000
--- a/source/Expression/IRForTarget.cpp
+++ /dev/null
@@ -1,2819 +0,0 @@
-//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/IRForTarget.h"
-
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/InstrTypes.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/ValueSymbolTable.h"
-
-#include "clang/AST/ASTContext.h"
-
-#include "lldb/Core/dwarf.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
-
-#include <map>
-
-using namespace llvm;
-
-static char ID;
-
-IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) :
- m_execution_unit(execution_unit),
- m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()),
- m_allocation(LLDB_INVALID_ADDRESS)
-{
-}
-
-IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) :
- m_maker(maker),
- m_values()
-{
-}
-
-IRForTarget::FunctionValueCache::~FunctionValueCache()
-{
-}
-
-llvm::Value *
-IRForTarget::FunctionValueCache::GetValue(llvm::Function *function)
-{
- if (!m_values.count(function))
- {
- llvm::Value *ret = m_maker(function);
- m_values[function] = ret;
- return ret;
- }
- return m_values[function];
-}
-
-lldb::addr_t
-IRForTarget::StaticDataAllocator::Allocate()
-{
- lldb_private::Error err;
-
- if (m_allocation != LLDB_INVALID_ADDRESS)
- {
- m_execution_unit.FreeNow(m_allocation);
- m_allocation = LLDB_INVALID_ADDRESS;
- }
-
- m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err);
-
- return m_allocation;
-}
-
-lldb::TargetSP
-IRForTarget::StaticDataAllocator::GetTarget()
-{
- return m_execution_unit.GetTarget();
-}
-
-static llvm::Value *
-FindEntryInstruction (llvm::Function *function)
-{
- if (function->empty())
- return NULL;
-
- return function->getEntryBlock().getFirstNonPHIOrDbg();
-}
-
-IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
- bool resolve_vars,
- lldb_private::IRExecutionUnit &execution_unit,
- lldb_private::Stream *error_stream,
- const char *func_name) :
- ModulePass(ID),
- m_resolve_vars(resolve_vars),
- m_func_name(func_name),
- m_module(NULL),
- m_decl_map(decl_map),
- m_data_allocator(execution_unit),
- m_CFStringCreateWithBytes(NULL),
- m_sel_registerName(NULL),
- m_intptr_ty(NULL),
- m_error_stream(error_stream),
- m_result_store(NULL),
- m_result_is_pointer(false),
- m_reloc_placeholder(NULL),
- m_entry_instruction_finder (FindEntryInstruction)
-{
-}
-
-/* Handy utility functions used at several places in the code */
-
-static std::string
-PrintValue(const Value *value, bool truncate = false)
-{
- std::string s;
- if (value)
- {
- raw_string_ostream rso(s);
- value->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
- }
- return s;
-}
-
-static std::string
-PrintType(const llvm::Type *type, bool truncate = false)
-{
- std::string s;
- raw_string_ostream rso(s);
- type->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
- return s;
-}
-
-IRForTarget::~IRForTarget()
-{
-}
-
-bool
-IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function)
-{
- llvm_function.setLinkage(GlobalValue::ExternalLinkage);
-
- std::string name = llvm_function.getName().str();
-
- return true;
-}
-
-IRForTarget::LookupResult
-IRForTarget::GetFunctionAddress (llvm::Function *fun,
- uint64_t &fun_addr,
- lldb_private::ConstString &name,
- Constant **&value_ptr)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- fun_addr = LLDB_INVALID_ADDRESS;
- name.Clear();
- value_ptr = NULL;
-
- if (fun->isIntrinsic())
- {
- Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
-
- switch (intrinsic_id)
- {
- default:
- if (log)
- log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
-
- return LookupResult::Fail;
- case Intrinsic::memcpy:
- {
- static lldb_private::ConstString g_memcpy_str ("memcpy");
- name = g_memcpy_str;
- }
- break;
- case Intrinsic::memset:
- {
- static lldb_private::ConstString g_memset_str ("memset");
- name = g_memset_str;
- }
- break;
- case Intrinsic::dbg_declare:
- case Intrinsic::dbg_value:
- return LookupResult::Ignore;
- }
-
- if (log && name)
- log->Printf("Resolved intrinsic name \"%s\"", name.GetCString());
- }
- else
- {
- name.SetCStringWithLength (fun->getName().data(), fun->getName().size());
- }
-
- // Find the address of the function.
-
- clang::NamedDecl *fun_decl = DeclForGlobal (fun);
-
- if (fun_decl)
- {
- if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr))
- {
- std::vector<lldb_private::ConstString> alternates;
- bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
- if (!found_it)
- {
- if (log)
- log->Printf("Address of function \"%s\" not found.\n", name.GetCString());
- // Check for an alternate mangling for names from the standard library.
- // For example, "std::basic_string<...>" has an alternate mangling scheme per
- // the Itanium C++ ABI.
- lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP();
- if (process_sp)
- {
- lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime();
- if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates))
- {
- for (size_t i = 0; i < alternates.size(); ++i)
- {
- const lldb_private::ConstString &alternate_name = alternates[i];
- if (log)
- log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr)))
- {
- if (log)
- log->Printf("Found address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- break;
- }
- }
- }
- }
- }
-
- if (!found_it)
- {
- lldb_private::Mangled mangled_name(name);
- if (m_error_stream)
- {
- if (mangled_name.GetMangledName())
- m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n",
- mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(),
- mangled_name.GetMangledName().GetCString());
- else
- m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
- mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString());
- }
- return LookupResult::Fail;
- }
- }
- }
- else
- {
- if (!m_decl_map->GetFunctionAddress (name, fun_addr))
- {
- if (log)
- log->Printf ("Metadataless function \"%s\" had no address", name.GetCString());
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
-
- return LookupResult::Fail;
- }
- }
-
- if (log)
- log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr);
-
- return LookupResult::Success;
-}
-
-llvm::Constant *
-IRForTarget::BuildFunctionPointer (llvm::Type *type,
- uint64_t ptr)
-{
- PointerType *fun_ptr_ty = PointerType::getUnqual(type);
- Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false);
- return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
-}
-
-void
-IRForTarget::RegisterFunctionMetadata(LLVMContext &context,
- llvm::Value *function_ptr,
- const char *name)
-{
- for (llvm::User *user : function_ptr->users())
- {
- if (Instruction *user_inst = dyn_cast<Instruction>(user))
- {
- MDString* md_name = MDString::get(context, StringRef(name));
-
- MDNode *metadata = MDNode::get(context, md_name);
-
- user_inst->setMetadata("lldb.call.realName", metadata);
- }
- else
- {
- RegisterFunctionMetadata (context, user, name);
- }
- }
-}
-
-bool
-IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- for (llvm::Module::iterator fi = llvm_module.begin();
- fi != llvm_module.end();
- ++fi)
- {
- Function *fun = fi;
-
- bool is_decl = fun->isDeclaration();
-
- if (log)
- log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str());
-
- if (!is_decl)
- continue;
-
- if (fun->use_empty())
- continue; // ignore
-
- uint64_t addr = LLDB_INVALID_ADDRESS;
- lldb_private::ConstString name;
- Constant **value_ptr = NULL;
-
- LookupResult result = GetFunctionAddress(fun,
- addr,
- name,
- value_ptr);
-
- switch (result)
- {
- case LookupResult::Fail:
- return false; // GetFunctionAddress reports its own errors
-
- case LookupResult::Ignore:
- break; // Nothing to do
-
- case LookupResult::Success:
- {
- Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
-
- RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
-
- if (value_ptr)
- *value_ptr = value;
-
- // If we are replacing a function with the nobuiltin attribute, it may
- // be called with the builtin attribute on call sites. Remove any such
- // attributes since it's illegal to have a builtin call to something
- // other than a nobuiltin function.
- if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
- llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
-
- for (auto u : fun->users()) {
- if (auto call = dyn_cast<CallInst>(u)) {
- call->removeAttribute(AttributeSet::FunctionIndex, builtin);
- }
- }
- }
-
- fun->replaceAllUsesWith(value);
- }
- break;
- }
- }
-
- return true;
-}
-
-
-clang::NamedDecl *
-IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
-{
- NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
-
- if (!named_metadata)
- return NULL;
-
- unsigned num_nodes = named_metadata->getNumOperands();
- unsigned node_index;
-
- for (node_index = 0;
- node_index < num_nodes;
- ++node_index)
- {
- llvm::MDNode *metadata_node = dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));
- if (!metadata_node)
- return NULL;
-
- if (metadata_node->getNumOperands() != 2)
- continue;
-
- if (mdconst::dyn_extract_or_null<GlobalValue>(metadata_node->getOperand(0)) != global_val)
- continue;
-
- ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));
-
- if (!constant_int)
- return NULL;
-
- uintptr_t ptr = constant_int->getZExtValue();
-
- return reinterpret_cast<clang::NamedDecl *>(ptr);
- }
-
- return NULL;
-}
-
-clang::NamedDecl *
-IRForTarget::DeclForGlobal (GlobalValue *global_val)
-{
- return DeclForGlobal(global_val, m_module);
-}
-
-bool
-IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_resolve_vars)
- return true;
-
- // Find the result variable. If it doesn't exist, we can give up right here.
-
- ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
-
- std::string result_name_str;
- const char *result_name = NULL;
-
- for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
- vi != ve;
- ++vi)
- {
- result_name_str = vi->first().str();
- const char *value_name = result_name_str.c_str();
-
- if (strstr(value_name, "$__lldb_expr_result_ptr") &&
- strncmp(value_name, "_ZGV", 4))
- {
- result_name = value_name;
- m_result_is_pointer = true;
- break;
- }
-
- if (strstr(value_name, "$__lldb_expr_result") &&
- strncmp(value_name, "_ZGV", 4))
- {
- result_name = value_name;
- m_result_is_pointer = false;
- break;
- }
- }
-
- if (!result_name)
- {
- if (log)
- log->PutCString("Couldn't find result variable");
-
- return true;
- }
-
- if (log)
- log->Printf("Result name: \"%s\"", result_name);
-
- Value *result_value = m_module->getNamedValue(result_name);
-
- if (!result_value)
- {
- if (log)
- log->PutCString("Result variable had no data");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name);
-
- return false;
- }
-
- if (log)
- log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str());
-
- GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
-
- if (!result_global)
- {
- if (log)
- log->PutCString("Result variable isn't a GlobalVariable");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name);
-
- return false;
- }
-
- clang::NamedDecl *result_decl = DeclForGlobal (result_global);
- if (!result_decl)
- {
- if (log)
- log->PutCString("Result variable doesn't have a corresponding Decl");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name);
-
- return false;
- }
-
- if (log)
- {
- std::string decl_desc_str;
- raw_string_ostream decl_desc_stream(decl_desc_str);
- result_decl->print(decl_desc_stream);
- decl_desc_stream.flush();
-
- log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str());
- }
-
- clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
- if (!result_var)
- {
- if (log)
- log->PutCString("Result variable Decl isn't a VarDecl");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name);
-
- return false;
- }
-
- // Get the next available result name from m_decl_map and create the persistent
- // variable for it
-
- // If the result is an Lvalue, it is emitted as a pointer; see
- // ASTResultSynthesizer::SynthesizeBodyResult.
- if (m_result_is_pointer)
- {
- clang::QualType pointer_qual_type = result_var->getType();
- const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
-
- const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>();
- const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>();
-
- if (pointer_pointertype)
- {
- clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
-
- m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
- &result_decl->getASTContext());
- }
- else if (pointer_objcobjpointertype)
- {
- clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
-
- m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
- &result_decl->getASTContext());
- }
- else
- {
- if (log)
- log->PutCString("Expected result to have pointer type, but it did not");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name);
-
- return false;
- }
- }
- else
- {
- m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
- &result_decl->getASTContext());
- }
-
-
- lldb::TargetSP target_sp (m_data_allocator.GetTarget());
- lldb_private::ExecutionContext exe_ctx (target_sp, true);
- if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0)
- {
- lldb_private::StreamString type_desc_stream;
- m_result_type.DumpTypeDescription(&type_desc_stream);
-
- if (log)
- log->Printf("Result type has size 0");
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n",
- type_desc_stream.GetData());
- return false;
- }
-
- if (log)
- {
- lldb_private::StreamString type_desc_stream;
- m_result_type.DumpTypeDescription(&type_desc_stream);
-
- log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
- }
-
- m_result_name = lldb_private::ConstString("$RESULT_NAME");
-
- if (log)
- log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
- m_result_name.GetCString(),
- m_result_type.GetByteSize(nullptr));
-
- // Construct a new result global and set up its metadata
-
- GlobalVariable *new_result_global = new GlobalVariable((*m_module),
- result_global->getType()->getElementType(),
- false, /* not constant */
- GlobalValue::ExternalLinkage,
- NULL, /* no initializer */
- m_result_name.GetCString ());
-
- // It's too late in compilation to create a new VarDecl for this, but we don't
- // need to. We point the metadata at the old VarDecl. This creates an odd
- // anomaly: a variable with a Value whose name is something like $0 and a
- // Decl whose name is $__lldb_expr_result. This condition is handled in
- // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
- // fixed up.
-
- ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
- reinterpret_cast<uint64_t>(result_decl),
- false);
-
- llvm::Metadata *values[2];
- values[0] = ConstantAsMetadata::get(new_result_global);
- values[1] = ConstantAsMetadata::get(new_constant_int);
-
- ArrayRef<Metadata *> value_ref(values, 2);
-
- MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
- NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs");
- named_metadata->addOperand(persistent_global_md);
-
- if (log)
- log->Printf("Replacing \"%s\" with \"%s\"",
- PrintValue(result_global).c_str(),
- PrintValue(new_result_global).c_str());
-
- if (result_global->use_empty())
- {
- // We need to synthesize a store for this variable, because otherwise
- // there's nothing to put into its equivalent persistent variable.
-
- BasicBlock &entry_block(llvm_function.getEntryBlock());
- Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
-
- if (!first_entry_instruction)
- return false;
-
- if (!result_global->hasInitializer())
- {
- if (log)
- log->Printf("Couldn't find initializer for unused variable");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name);
-
- return false;
- }
-
- Constant *initializer = result_global->getInitializer();
-
- StoreInst *synthesized_store = new StoreInst(initializer,
- new_result_global,
- first_entry_instruction);
-
- if (log)
- log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str());
- }
- else
- {
- result_global->replaceAllUsesWith(new_result_global);
- }
-
- if (!m_decl_map->AddPersistentVariable(result_decl,
- m_result_name,
- m_result_type,
- true,
- m_result_is_pointer))
- return false;
-
- result_global->eraseFromParent();
-
- return true;
-}
-
-bool
-IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
- llvm::GlobalVariable *cstr)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Type *ns_str_ty = ns_str->getType();
-
- Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
- Type *i32_ty = Type::getInt32Ty(m_module->getContext());
- Type *i8_ty = Type::getInt8Ty(m_module->getContext());
-
- if (!m_CFStringCreateWithBytes)
- {
- lldb::addr_t CFStringCreateWithBytes_addr;
-
- static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes");
-
- if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr))
- {
- if (log)
- log->PutCString("Couldn't find CFStringCreateWithBytes in the target");
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n");
-
- return false;
- }
-
- if (log)
- log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr);
-
- // Build the function type:
- //
- // CFStringRef CFStringCreateWithBytes (
- // CFAllocatorRef alloc,
- // const UInt8 *bytes,
- // CFIndex numBytes,
- // CFStringEncoding encoding,
- // Boolean isExternalRepresentation
- // );
- //
- // We make the following substitutions:
- //
- // CFStringRef -> i8*
- // CFAllocatorRef -> i8*
- // UInt8 * -> i8*
- // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now)
- // CFStringEncoding -> i32
- // Boolean -> i8
-
- Type *arg_type_array[5];
-
- arg_type_array[0] = i8_ptr_ty;
- arg_type_array[1] = i8_ptr_ty;
- arg_type_array[2] = m_intptr_ty;
- arg_type_array[3] = i32_ty;
- arg_type_array[4] = i8_ty;
-
- ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
-
- llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
-
- // Build the constant containing the pointer to the function
- PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
- Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
- m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty);
- }
-
- ConstantDataSequential *string_array = NULL;
-
- if (cstr)
- string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
-
- Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
- Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty);
- Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false);
- Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */
- Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
-
- Value *argument_array[5];
-
- argument_array[0] = alloc_arg;
- argument_array[1] = bytes_arg;
- argument_array[2] = numBytes_arg;
- argument_array[3] = encoding_arg;
- argument_array[4] = isExternal_arg;
-
- ArrayRef <Value *> CFSCWB_arguments(argument_array, 5);
-
- FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * {
- return CallInst::Create(m_CFStringCreateWithBytes,
- CFSCWB_arguments,
- "CFStringCreateWithBytes",
- llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)));
- });
-
- if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder))
- {
- if (log)
- log->PutCString("Couldn't replace the NSString with the result of the call");
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n");
-
- return false;
- }
-
- ns_str->eraseFromParent();
-
- return true;
-}
-
-bool
-IRForTarget::RewriteObjCConstStrings()
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
-
- for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
- vi != ve;
- ++vi)
- {
- std::string value_name = vi->first().str();
- const char *value_name_cstr = value_name.c_str();
-
- if (strstr(value_name_cstr, "_unnamed_cfstring_"))
- {
- Value *nsstring_value = vi->second;
-
- GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value);
-
- if (!nsstring_global)
- {
- if (log)
- log->PutCString("NSString variable is not a GlobalVariable");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n");
-
- return false;
- }
-
- if (!nsstring_global->hasInitializer())
- {
- if (log)
- log->PutCString("NSString variable does not have an initializer");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n");
-
- return false;
- }
-
- ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
-
- if (!nsstring_struct)
- {
- if (log)
- log->PutCString("NSString variable's initializer is not a ConstantStruct");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n");
-
- return false;
- }
-
- // We expect the following structure:
- //
- // struct {
- // int *isa;
- // int flags;
- // char *str;
- // long length;
- // };
-
- if (nsstring_struct->getNumOperands() != 4)
- {
- if (log)
- log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands());
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n");
-
- return false;
- }
-
- Constant *nsstring_member = nsstring_struct->getOperand(2);
-
- if (!nsstring_member)
- {
- if (log)
- log->PutCString("NSString initializer's str element was empty");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n");
-
- return false;
- }
-
- ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member);
-
- if (!nsstring_expr)
- {
- if (log)
- log->PutCString("NSString initializer's str element is not a ConstantExpr");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n");
-
- return false;
- }
-
- if (nsstring_expr->getOpcode() != Instruction::GetElementPtr)
- {
- if (log)
- log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName());
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n");
-
- return false;
- }
-
- Constant *nsstring_cstr = nsstring_expr->getOperand(0);
-
- GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
-
- if (!cstr_global)
- {
- if (log)
- log->PutCString("NSString initializer's str element is not a GlobalVariable");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n");
-
- return false;
- }
-
- if (!cstr_global->hasInitializer())
- {
- if (log)
- log->PutCString("NSString initializer's str element does not have an initializer");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n");
-
- return false;
- }
-
- /*
- if (!cstr_array)
- {
- if (log)
- log->PutCString("NSString initializer's str element is not a ConstantArray");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n");
-
- return false;
- }
-
- if (!cstr_array->isCString())
- {
- if (log)
- log->PutCString("NSString initializer's str element is not a C string array");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n");
-
- return false;
- }
- */
-
- ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
-
- if (log)
- {
- if (cstr_array)
- log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str());
- else
- log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr);
- }
-
- if (!cstr_array)
- cstr_global = NULL;
-
- if (!RewriteObjCConstString(nsstring_global, cstr_global))
- {
- if (log)
- log->PutCString("Error rewriting the constant string");
-
- // We don't print an error message here because RewriteObjCConstString has done so for us.
-
- return false;
- }
- }
- }
-
- for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
- vi != ve;
- ++vi)
- {
- std::string value_name = vi->first().str();
- const char *value_name_cstr = value_name.c_str();
-
- if (!strcmp(value_name_cstr, "__CFConstantStringClassReference"))
- {
- GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second);
-
- if (!gv)
- {
- if (log)
- log->PutCString("__CFConstantStringClassReference is not a global variable");
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n");
-
- return false;
- }
-
- gv->eraseFromParent();
-
- break;
- }
- }
-
- return true;
-}
-
-static bool IsObjCSelectorRef (Value *value)
-{
- GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
-
- if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"))
- return false;
-
- return true;
-}
-
-// This function does not report errors; its callers are responsible.
-bool
-IRForTarget::RewriteObjCSelector (Instruction* selector_load)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- LoadInst *load = dyn_cast<LoadInst>(selector_load);
-
- if (!load)
- return false;
-
- // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
- //
- // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*>
- // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
- //
- // where %obj is the object pointer and %tmp is the selector.
- //
- // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
- // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
-
- // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target
-
- GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand());
-
- if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer())
- return false;
-
- Constant *osr_initializer = _objc_selector_references_->getInitializer();
-
- ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer);
-
- if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr)
- return false;
-
- Value *osr_initializer_base = osr_initializer_expr->getOperand(0);
-
- if (!osr_initializer_base)
- return false;
-
- // Find the string's initializer (a ConstantArray) and get the string from it
-
- GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base);
-
- if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
- return false;
-
- Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
-
- ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer);
-
- if (!omvn_initializer_array->isString())
- return false;
-
- std::string omvn_initializer_string = omvn_initializer_array->getAsString();
-
- if (log)
- log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str());
-
- // Construct a call to sel_registerName
-
- if (!m_sel_registerName)
- {
- lldb::addr_t sel_registerName_addr;
-
- static lldb_private::ConstString g_sel_registerName_str ("sel_registerName");
- if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr))
- return false;
-
- if (log)
- log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr);
-
- // Build the function type: struct objc_selector *sel_registerName(uint8_t*)
-
- // The below code would be "more correct," but in actuality what's required is uint8_t*
- //Type *sel_type = StructType::get(m_module->getContext());
- //Type *sel_ptr_type = PointerType::getUnqual(sel_type);
- Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
-
- Type *type_array[1];
-
- type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
-
- ArrayRef<Type *> srN_arg_types(type_array, 1);
-
- llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false);
-
- // Build the constant containing the pointer to the function
- PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
- Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
- m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty);
- }
-
- Value *argument_array[1];
-
- Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
-
- argument_array[0] = omvn_pointer;
-
- ArrayRef<Value *> srN_arguments(argument_array, 1);
-
- CallInst *srN_call = CallInst::Create(m_sel_registerName,
- srN_arguments,
- "sel_registerName",
- selector_load);
-
- // Replace the load with the call in all users
-
- selector_load->replaceAllUsesWith(srN_call);
-
- selector_load->eraseFromParent();
-
- return true;
-}
-
-bool
-IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- BasicBlock::iterator ii;
-
- typedef SmallVector <Instruction*, 2> InstrList;
- typedef InstrList::iterator InstrIterator;
-
- InstrList selector_loads;
-
- for (ii = basic_block.begin();
- ii != basic_block.end();
- ++ii)
- {
- Instruction &inst = *ii;
-
- if (LoadInst *load = dyn_cast<LoadInst>(&inst))
- if (IsObjCSelectorRef(load->getPointerOperand()))
- selector_loads.push_back(&inst);
- }
-
- InstrIterator iter;
-
- for (iter = selector_loads.begin();
- iter != selector_loads.end();
- ++iter)
- {
- if (!RewriteObjCSelector(*iter))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n");
-
- if (log)
- log->PutCString("Couldn't rewrite a reference to an Objective-C selector");
-
- return false;
- }
- }
-
- return true;
-}
-
-// This function does not report errors; its callers are responsible.
-bool
-IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
-
- MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
-
- if (!alloc_md || !alloc_md->getNumOperands())
- return false;
-
- ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));
-
- if (!constant_int)
- return false;
-
- // We attempt to register this as a new persistent variable with the DeclMap.
-
- uintptr_t ptr = constant_int->getZExtValue();
-
- clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
-
- lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
- &decl->getASTContext());
-
- StringRef decl_name (decl->getName());
- lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
- if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
- return false;
-
- GlobalVariable *persistent_global = new GlobalVariable((*m_module),
- alloc->getType(),
- false, /* not constant */
- GlobalValue::ExternalLinkage,
- NULL, /* no initializer */
- alloc->getName().str().c_str());
-
- // What we're going to do here is make believe this was a regular old external
- // variable. That means we need to make the metadata valid.
-
- NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
-
- llvm::Metadata *values[2];
- values[0] = ConstantAsMetadata::get(persistent_global);
- values[1] = ConstantAsMetadata::get(constant_int);
-
- ArrayRef<llvm::Metadata *> value_ref(values, 2);
-
- MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
- named_metadata->addOperand(persistent_global_md);
-
- // Now, since the variable is a pointer variable, we will drop in a load of that
- // pointer variable.
-
- LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc);
-
- if (log)
- log->Printf("Replacing \"%s\" with \"%s\"",
- PrintValue(alloc).c_str(),
- PrintValue(persistent_load).c_str());
-
- alloc->replaceAllUsesWith(persistent_load);
- alloc->eraseFromParent();
-
- return true;
-}
-
-bool
-IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block)
-{
- if (!m_resolve_vars)
- return true;
-
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- BasicBlock::iterator ii;
-
- typedef SmallVector <Instruction*, 2> InstrList;
- typedef InstrList::iterator InstrIterator;
-
- InstrList pvar_allocs;
-
- for (ii = basic_block.begin();
- ii != basic_block.end();
- ++ii)
- {
- Instruction &inst = *ii;
-
- if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst))
- {
- llvm::StringRef alloc_name = alloc->getName();
-
- if (alloc_name.startswith("$") &&
- !alloc_name.startswith("$__lldb"))
- {
- if (alloc_name.find_first_of("0123456789") == 1)
- {
- if (log)
- log->Printf("Rejecting a numeric persistent variable.");
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n");
-
- return false;
- }
-
- pvar_allocs.push_back(alloc);
- }
- }
- }
-
- InstrIterator iter;
-
- for (iter = pvar_allocs.begin();
- iter != pvar_allocs.end();
- ++iter)
- {
- if (!RewritePersistentAlloc(*iter))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n");
-
- if (log)
- log->PutCString("Couldn't rewrite the creation of a persistent variable");
-
- return false;
- }
- }
-
- return true;
-}
-
-bool
-IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer)
-{
- if (!initializer)
- return true;
-
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log && log->GetVerbose())
- log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str());
-
- Type *initializer_type = initializer->getType();
-
- if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer))
- {
- memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type));
- return true;
- }
- else if (ConstantDataArray *array_initializer = dyn_cast<ConstantDataArray>(initializer))
- {
- if (array_initializer->isString())
- {
- std::string array_initializer_string = array_initializer->getAsString();
- memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type));
- }
- else
- {
- ArrayType *array_initializer_type = array_initializer->getType();
- Type *array_element_type = array_initializer_type->getElementType();
-
- size_t element_size = m_target_data->getTypeAllocSize(array_element_type);
-
- for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i)
- {
- Value *operand_value = array_initializer->getOperand(i);
- Constant *operand_constant = dyn_cast<Constant>(operand_value);
-
- if (!operand_constant)
- return false;
-
- if (!MaterializeInitializer(data + (i * element_size), operand_constant))
- return false;
- }
- }
- return true;
- }
- else if (ConstantStruct *struct_initializer = dyn_cast<ConstantStruct>(initializer))
- {
- StructType *struct_initializer_type = struct_initializer->getType();
- const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type);
-
- for (unsigned i = 0;
- i < struct_initializer->getNumOperands();
- ++i)
- {
- if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i)))
- return false;
- }
- return true;
- }
- else if (isa<ConstantAggregateZero>(initializer))
- {
- memset(data, 0, m_target_data->getTypeStoreSize(initializer_type));
- return true;
- }
- return false;
-}
-
-bool
-IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
-{
- if (GlobalVariable::isExternalLinkage(global_variable->getLinkage()))
- return false;
-
- if (global_variable == m_reloc_placeholder)
- return true;
-
- uint64_t offset = m_data_allocator.GetStream().GetSize();
-
- llvm::Type *variable_type = global_variable->getType();
-
- Constant *initializer = global_variable->getInitializer();
-
- llvm::Type *initializer_type = initializer->getType();
-
- size_t size = m_target_data->getTypeAllocSize(initializer_type);
- size_t align = m_target_data->getPrefTypeAlignment(initializer_type);
-
- const size_t mask = (align - 1);
- uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
- offset = aligned_offset;
-
- lldb_private::DataBufferHeap data(size, '\0');
-
- if (initializer)
- if (!MaterializeInitializer(data.GetBytes(), initializer))
- return false;
-
- m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize());
-
- Constant *new_pointer = BuildRelocation(variable_type, offset);
-
- global_variable->replaceAllUsesWith(new_pointer);
-
- global_variable->eraseFromParent();
-
- return true;
-}
-
-// This function does not report errors; its callers are responsible.
-bool
-IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str());
-
- if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr))
- {
- switch (constant_expr->getOpcode())
- {
- default:
- break;
- case Instruction::GetElementPtr:
- case Instruction::BitCast:
- Value *s = constant_expr->getOperand(0);
- if (!MaybeHandleVariable(s))
- return false;
- }
- }
- else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr))
- {
- if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
- return MaterializeInternalVariable(global_variable);
-
- clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
-
- if (!named_decl)
- {
- if (IsObjCSelectorRef(llvm_value_ptr))
- return true;
-
- if (!global_variable->hasExternalLinkage())
- return true;
-
- if (log)
- log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str());
-
- return false;
- }
-
- std::string name (named_decl->getName().str());
-
- clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
- if (value_decl == NULL)
- return false;
-
- lldb_private::ClangASTType clang_type(&value_decl->getASTContext(), value_decl->getType());
-
- const Type *value_type = NULL;
-
- if (name[0] == '$')
- {
- // The $__lldb_expr_result name indicates the return value has allocated as
- // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
- // accesses to this static variable need to be redirected to the result of dereferencing
- // a pointer that is passed in as one of the arguments.
- //
- // Consequently, when reporting the size of the type, we report a pointer type pointing
- // to the type of $__lldb_expr_result, not the type itself.
- //
- // We also do this for any user-declared persistent variables.
- clang_type = clang_type.GetPointerType();
- value_type = PointerType::get(global_variable->getType(), 0);
- }
- else
- {
- value_type = global_variable->getType();
- }
-
- const uint64_t value_size = clang_type.GetByteSize(nullptr);
- lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull;
-
- if (log)
- {
- log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]",
- name.c_str(),
- clang_type.GetQualType().getAsString().c_str(),
- PrintType(value_type).c_str(),
- value_size,
- value_alignment);
- }
-
-
- if (named_decl && !m_decl_map->AddValueToStruct(named_decl,
- lldb_private::ConstString (name.c_str()),
- llvm_value_ptr,
- value_size,
- value_alignment))
- {
- if (!global_variable->hasExternalLinkage())
- return true;
- else if (HandleSymbol (global_variable))
- return true;
- else
- return false;
- }
- }
- else if (dyn_cast<llvm::Function>(llvm_value_ptr))
- {
- if (log)
- log->Printf("Function pointers aren't handled right now");
-
- return false;
- }
-
- return true;
-}
-
-// This function does not report errors; its callers are responsible.
-bool
-IRForTarget::HandleSymbol (Value *symbol)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- lldb_private::ConstString name(symbol->getName().str().c_str());
-
- lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny);
-
- if (symbol_addr == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("Symbol \"%s\" had no address", name.GetCString());
-
- return false;
- }
-
- if (log)
- log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr);
-
- Type *symbol_type = symbol->getType();
-
- Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
-
- Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
-
- if (log)
- log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str());
-
- symbol->replaceAllUsesWith(symbol_addr_ptr);
-
- return true;
-}
-
-bool
-IRForTarget::MaybeHandleCallArguments (CallInst *Old)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str());
-
- for (unsigned op_index = 0, num_ops = Old->getNumArgOperands();
- op_index < num_ops;
- ++op_index)
- if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n");
-
- return false;
- }
-
- return true;
-}
-
-bool
-IRForTarget::HandleObjCClass(Value *classlist_reference)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference);
-
- if (!global_variable)
- return false;
-
- Constant *initializer = global_variable->getInitializer();
-
- if (!initializer)
- return false;
-
- if (!initializer->hasName())
- return false;
-
- StringRef name(initializer->getName());
- lldb_private::ConstString name_cstr(name.str().c_str());
- lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
-
- if (log)
- log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr);
-
- if (class_ptr == LLDB_INVALID_ADDRESS)
- return false;
-
- if (global_variable->use_empty())
- return false;
-
- SmallVector<LoadInst *, 2> load_instructions;
-
- for (llvm::User *u : global_variable->users())
- {
- if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
- load_instructions.push_back(load_instruction);
- }
-
- if (load_instructions.empty())
- return false;
-
- Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
-
- for (LoadInst *load_instruction : load_instructions)
- {
- Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
-
- load_instruction->replaceAllUsesWith(class_bitcast);
-
- load_instruction->eraseFromParent();
- }
-
- return true;
-}
-
-bool
-IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block)
-{
- BasicBlock::iterator ii;
-
- std::vector<CallInst *> calls_to_remove;
-
- for (ii = basic_block.begin();
- ii != basic_block.end();
- ++ii)
- {
- Instruction &inst = *ii;
-
- CallInst *call = dyn_cast<CallInst>(&inst);
-
- // MaybeHandleCallArguments handles error reporting; we are silent here
- if (!call)
- continue;
-
- bool remove = false;
-
- llvm::Function *func = call->getCalledFunction();
-
- if (func && func->getName() == "__cxa_atexit")
- remove = true;
-
- llvm::Value *val = call->getCalledValue();
-
- if (val && val->getName() == "__cxa_atexit")
- remove = true;
-
- if (remove)
- calls_to_remove.push_back(call);
- }
-
- for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end();
- ci != ce;
- ++ci)
- {
- (*ci)->eraseFromParent();
- }
-
- return true;
-}
-
-bool
-IRForTarget::ResolveCalls(BasicBlock &basic_block)
-{
- /////////////////////////////////////////////////////////////////////////
- // Prepare the current basic block for execution in the remote process
- //
-
- BasicBlock::iterator ii;
-
- for (ii = basic_block.begin();
- ii != basic_block.end();
- ++ii)
- {
- Instruction &inst = *ii;
-
- CallInst *call = dyn_cast<CallInst>(&inst);
-
- // MaybeHandleCallArguments handles error reporting; we are silent here
- if (call && !MaybeHandleCallArguments(call))
- return false;
- }
-
- return true;
-}
-
-bool
-IRForTarget::ResolveExternals (Function &llvm_function)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- for (GlobalVariable &global_var : m_module->globals())
- {
- std::string global_name = global_var.getName().str();
-
- if (log)
- log->Printf("Examining %s, DeclForGlobalValue returns %p",
- global_name.c_str(),
- static_cast<void*>(DeclForGlobal(&global_var)));
-
- if (global_name.find("OBJC_IVAR") == 0)
- {
- if (!HandleSymbol(&global_var))
- {
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str());
-
- return false;
- }
- }
- else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos)
- {
- if (!HandleObjCClass(&global_var))
- {
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
-
- return false;
- }
- }
- else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos)
- {
- if (!HandleObjCClass(&global_var))
- {
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
-
- return false;
- }
- }
- else if (DeclForGlobal(&global_var))
- {
- if (!MaybeHandleVariable (&global_var))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str());
-
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool
-IRForTarget::ReplaceStrings ()
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- typedef std::map <GlobalVariable *, size_t> OffsetsTy;
-
- OffsetsTy offsets;
-
- for (GlobalVariable &gv : m_module->globals())
- {
- if (!gv.hasInitializer())
- continue;
-
- Constant *gc = gv.getInitializer();
-
- std::string str;
-
- if (gc->isNullValue())
- {
- Type *gc_type = gc->getType();
-
- ArrayType *gc_array_type = dyn_cast<ArrayType>(gc_type);
-
- if (!gc_array_type)
- continue;
-
- Type *gc_element_type = gc_array_type->getElementType();
-
- IntegerType *gc_integer_type = dyn_cast<IntegerType>(gc_element_type);
-
- if (gc_integer_type->getBitWidth() != 8)
- continue;
-
- str = "";
- }
- else
- {
- ConstantDataArray *gc_array = dyn_cast<ConstantDataArray>(gc);
-
- if (!gc_array)
- continue;
-
- if (!gc_array->isCString())
- continue;
-
- if (log)
- log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str());
-
- str = gc_array->getAsString();
- }
-
- offsets[&gv] = m_data_allocator.GetStream().GetSize();
-
- m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1);
- }
-
- Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
-
- for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end();
- oi != oe;
- ++oi)
- {
- GlobalVariable *gv = oi->first;
- size_t offset = oi->second;
-
- Constant *new_initializer = BuildRelocation(char_ptr_ty, offset);
-
- if (log)
- log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str());
-
- for (llvm::User *u : gv->users())
- {
- if (log)
- log->Printf("Found use %s", PrintValue(u).c_str());
-
- ConstantExpr *const_expr = dyn_cast<ConstantExpr>(u);
- StoreInst *store_inst = dyn_cast<StoreInst>(u);
-
- if (const_expr)
- {
- if (const_expr->getOpcode() != Instruction::GetElementPtr)
- {
- if (log)
- log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str());
-
- return false;
- }
-
- Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType());
- Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast);
-
- const_expr->replaceAllUsesWith(new_gep);
- }
- else if (store_inst)
- {
- Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType());
-
- store_inst->setOperand(0, bit_cast);
- }
- else
- {
- if (log)
- log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str());
-
- return false;
- }
- }
-
- gv->eraseFromParent();
- }
-
- return true;
-}
-
-bool
-IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- typedef SmallVector <Value*, 2> ConstantList;
- typedef SmallVector <llvm::Instruction*, 2> UserList;
- typedef ConstantList::iterator ConstantIterator;
- typedef UserList::iterator UserIterator;
-
- ConstantList static_constants;
- UserList static_users;
-
- for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end();
- ii != ie;
- ++ii)
- {
- llvm::Instruction &inst = *ii;
-
- for (Value *operand_val : inst.operand_values())
- {
- ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
-
- if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/)
- {
- static_constants.push_back(operand_val);
- static_users.push_back(ii);
- }
- }
- }
-
- ConstantIterator constant_iter;
- UserIterator user_iter;
-
- for (constant_iter = static_constants.begin(), user_iter = static_users.begin();
- constant_iter != static_constants.end();
- ++constant_iter, ++user_iter)
- {
- Value *operand_val = *constant_iter;
- llvm::Instruction *inst = *user_iter;
-
- ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
-
- if (operand_constant_fp)
- {
- Type *operand_type = operand_constant_fp->getType();
-
- APFloat operand_apfloat = operand_constant_fp->getValueAPF();
- APInt operand_apint = operand_apfloat.bitcastToAPInt();
-
- const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData();
- size_t operand_data_size = operand_apint.getBitWidth() / 8;
-
- if (log)
- {
- std::string s;
- raw_string_ostream ss(s);
- for (size_t index = 0;
- index < operand_data_size;
- ++index)
- {
- ss << (uint32_t)operand_raw_data[index];
- ss << " ";
- }
- ss.flush();
-
- log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str());
- }
-
- lldb_private::DataBufferHeap data(operand_data_size, 0);
-
- if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
- {
- uint8_t *data_bytes = data.GetBytes();
-
- for (size_t index = 0;
- index < operand_data_size;
- ++index)
- {
- data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)];
- }
- }
- else
- {
- memcpy(data.GetBytes(), operand_raw_data, operand_data_size);
- }
-
- uint64_t offset = m_data_allocator.GetStream().GetSize();
-
- size_t align = m_target_data->getPrefTypeAlignment(operand_type);
-
- const size_t mask = (align - 1);
- uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
-
- m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size);
-
- llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
-
- Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset);
-
- llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst);
-
- operand_constant_fp->replaceAllUsesWith(fp_load);
- }
- }
-
- return true;
-}
-
-static bool isGuardVariableRef(Value *V)
-{
- Constant *Old = NULL;
-
- if (!(Old = dyn_cast<Constant>(V)))
- return false;
-
- ConstantExpr *CE = NULL;
-
- if ((CE = dyn_cast<ConstantExpr>(V)))
- {
- if (CE->getOpcode() != Instruction::BitCast)
- return false;
-
- Old = CE->getOperand(0);
- }
-
- GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
-
- if (!GV || !GV->hasName() ||
- (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable
- !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable
- {
- return false;
- }
-
- return true;
-}
-
-void
-IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load)
-{
- Constant *zero(Constant::getNullValue(guard_load->getType()));
- guard_load->replaceAllUsesWith(zero);
- guard_load->eraseFromParent();
-}
-
-static void ExciseGuardStore(Instruction* guard_store)
-{
- guard_store->eraseFromParent();
-}
-
-bool
-IRForTarget::RemoveGuards(BasicBlock &basic_block)
-{
- ///////////////////////////////////////////////////////
- // Eliminate any reference to guard variables found.
- //
-
- BasicBlock::iterator ii;
-
- typedef SmallVector <Instruction*, 2> InstrList;
- typedef InstrList::iterator InstrIterator;
-
- InstrList guard_loads;
- InstrList guard_stores;
-
- for (ii = basic_block.begin();
- ii != basic_block.end();
- ++ii)
- {
- Instruction &inst = *ii;
-
- if (LoadInst *load = dyn_cast<LoadInst>(&inst))
- if (isGuardVariableRef(load->getPointerOperand()))
- guard_loads.push_back(&inst);
-
- if (StoreInst *store = dyn_cast<StoreInst>(&inst))
- if (isGuardVariableRef(store->getPointerOperand()))
- guard_stores.push_back(&inst);
- }
-
- InstrIterator iter;
-
- for (iter = guard_loads.begin();
- iter != guard_loads.end();
- ++iter)
- TurnGuardLoadIntoZero(*iter);
-
- for (iter = guard_stores.begin();
- iter != guard_stores.end();
- ++iter)
- ExciseGuardStore(*iter);
-
- return true;
-}
-
-// This function does not report errors; its callers are responsible.
-bool
-IRForTarget::UnfoldConstant(Constant *old_constant,
- FunctionValueCache &value_maker,
- FunctionValueCache &entry_instruction_finder)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- SmallVector<User*, 16> users;
-
- // We do this because the use list might change, invalidating our iterator.
- // Much better to keep a work list ourselves.
- for (llvm::User *u : old_constant->users())
- users.push_back(u);
-
- for (size_t i = 0;
- i < users.size();
- ++i)
- {
- User *user = users[i];
-
- if (Constant *constant = dyn_cast<Constant>(user))
- {
- // synthesize a new non-constant equivalent of the constant
-
- if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
- {
- switch (constant_expr->getOpcode())
- {
- default:
- if (log)
- log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str());
- return false;
- case Instruction::BitCast:
- {
- FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
- // UnaryExpr
- // OperandList[0] is value
-
- if (constant_expr->getOperand(0) != old_constant)
- return constant_expr;
-
- return new BitCastInst(value_maker.GetValue(function),
- constant_expr->getType(),
- "",
- llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
- });
-
- if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder))
- return false;
- }
- break;
- case Instruction::GetElementPtr:
- {
- // GetElementPtrConstantExpr
- // OperandList[0] is base
- // OperandList[1]... are indices
-
- FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
- Value *ptr = constant_expr->getOperand(0);
-
- if (ptr == old_constant)
- ptr = value_maker.GetValue(function);
-
- std::vector<Value*> index_vector;
-
- unsigned operand_index;
- unsigned num_operands = constant_expr->getNumOperands();
-
- for (operand_index = 1;
- operand_index < num_operands;
- ++operand_index)
- {
- Value *operand = constant_expr->getOperand(operand_index);
-
- if (operand == old_constant)
- operand = value_maker.GetValue(function);
-
- index_vector.push_back(operand);
- }
-
- ArrayRef <Value*> indices(index_vector);
-
- return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
- });
-
- if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder))
- return false;
- }
- break;
- }
- }
- else
- {
- if (log)
- log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str());
- return false;
- }
- }
- else
- {
- if (Instruction *inst = llvm::dyn_cast<Instruction>(user))
- {
- inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent()));
- }
- else
- {
- if (log)
- log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str());
- return false;
- }
- }
- }
-
- if (!isa<GlobalValue>(old_constant))
- {
- old_constant->destroyConstant();
- }
-
- return true;
-}
-
-bool
-IRForTarget::ReplaceVariables (Function &llvm_function)
-{
- if (!m_resolve_vars)
- return true;
-
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- m_decl_map->DoStructLayout();
-
- if (log)
- log->Printf("Element arrangement:");
-
- uint32_t num_elements;
- uint32_t element_index;
-
- size_t size;
- lldb::offset_t alignment;
-
- if (!m_decl_map->GetStructInfo (num_elements, size, alignment))
- return false;
-
- Function::arg_iterator iter(llvm_function.getArgumentList().begin());
-
- if (iter == llvm_function.getArgumentList().end())
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)");
-
- return false;
- }
-
- Argument *argument = iter;
-
- if (argument->getName().equals("this"))
- {
- ++iter;
-
- if (iter == llvm_function.getArgumentList().end())
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)");
-
- return false;
- }
-
- argument = iter;
- }
- else if (argument->getName().equals("self"))
- {
- ++iter;
-
- if (iter == llvm_function.getArgumentList().end())
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)");
-
- return false;
- }
-
- if (!iter->getName().equals("_cmd"))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str());
-
- return false;
- }
-
- ++iter;
-
- if (iter == llvm_function.getArgumentList().end())
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)");
-
- return false;
- }
-
- argument = iter;
- }
-
- if (!argument->getName().equals("$__lldb_arg"))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str());
-
- return false;
- }
-
- if (log)
- log->Printf("Arg: \"%s\"", PrintValue(argument).c_str());
-
- BasicBlock &entry_block(llvm_function.getEntryBlock());
- Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
-
- if (!FirstEntryInstruction)
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting");
-
- return false;
- }
-
- LLVMContext &context(m_module->getContext());
- IntegerType *offset_type(Type::getInt32Ty(context));
-
- if (!offset_type)
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type");
-
- return false;
- }
-
- for (element_index = 0; element_index < num_elements; ++element_index)
- {
- const clang::NamedDecl *decl = NULL;
- Value *value = NULL;
- lldb::offset_t offset;
- lldb_private::ConstString name;
-
- if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index))
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete");
-
- return false;
- }
-
- if (log)
- log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64,
- name.GetCString(),
- decl->getNameAsString().c_str(),
- offset);
-
- if (value)
- {
- if (log)
- log->Printf(" Replacing [%s]", PrintValue(value).c_str());
-
- FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * {
- // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
- // variable is an rvalue, we have to synthesize a dereference of the appropriate structure
- // entry in order to produce the static variable that the AST thinks it is accessing.
-
- llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function));
-
- ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true));
- GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr,
- argument,
- offset_int,
- "",
- entry_instruction);
-
- if (name == m_result_name && !m_result_is_pointer)
- {
- BitCastInst *bit_cast = new BitCastInst(get_element_ptr,
- value->getType()->getPointerTo(),
- "",
- entry_instruction);
-
- LoadInst *load = new LoadInst(bit_cast, "", entry_instruction);
-
- return load;
- }
- else
- {
- BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction);
-
- return bit_cast;
- }
- });
-
- if (Constant *constant = dyn_cast<Constant>(value))
- {
- UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder);
- }
- else if (Instruction *instruction = dyn_cast<Instruction>(value))
- {
- value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent()));
- }
- else
- {
- if (log)
- log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str());
- return false;
- }
-
- if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
- var->eraseFromParent();
- }
- }
-
- if (log)
- log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size);
-
- return true;
-}
-
-llvm::Constant *
-IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset)
-{
- llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset);
-
- llvm::Constant *offset_array[1];
-
- offset_array[0] = offset_int;
-
- llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1);
- llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext());
- llvm::Type *char_pointer_type = char_type->getPointerTo();
-
- llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type);
- llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets);
- llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type);
-
- return reloc_bitcast;
-}
-
-bool
-IRForTarget::CompleteDataAllocation ()
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_data_allocator.GetStream().GetSize())
- return true;
-
- lldb::addr_t allocation = m_data_allocator.Allocate();
-
- if (log)
- {
- if (allocation)
- log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation);
- else
- log->Printf("Failed to allocate static data");
- }
-
- if (!allocation || allocation == LLDB_INVALID_ADDRESS)
- return false;
-
- Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation);
- Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext()));
-
- m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast);
-
- m_reloc_placeholder->eraseFromParent();
-
- return true;
-}
-
-bool
-IRForTarget::StripAllGVs (Module &llvm_module)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- std::vector<GlobalVariable *> global_vars;
- std::set<GlobalVariable *>erased_vars;
-
- bool erased = true;
-
- while (erased)
- {
- erased = false;
-
- for (GlobalVariable &global_var : llvm_module.globals())
- {
- global_var.removeDeadConstantUsers();
-
- if (global_var.use_empty())
- {
- if (log)
- log->Printf("Did remove %s",
- PrintValue(&global_var).c_str());
- global_var.eraseFromParent();
- erased = true;
- break;
- }
- }
- }
-
- for (GlobalVariable &global_var : llvm_module.globals())
- {
- GlobalValue::user_iterator ui = global_var.user_begin();
-
- if (log)
- log->Printf("Couldn't remove %s because of %s",
- PrintValue(&global_var).c_str(),
- PrintValue(*ui).c_str());
- }
-
- return true;
-}
-
-bool
-IRForTarget::runOnModule (Module &llvm_module)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- m_module = &llvm_module;
- m_target_data.reset(new DataLayout(m_module));
- m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits());
-
- if (log)
- {
- std::string s;
- raw_string_ostream oss(s);
-
- m_module->print(oss, NULL);
-
- oss.flush();
-
- log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
- }
-
- Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str()));
-
- if (!main_function)
- {
- if (log)
- log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
-
- return false;
- }
-
- if (!FixFunctionLinkage (*main_function))
- {
- if (log)
- log->Printf("Couldn't fix the linkage for the function");
-
- return false;
- }
-
- llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
-
- m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
- int8_ty,
- false /* IsConstant */,
- GlobalVariable::InternalLinkage,
- Constant::getNullValue(int8_ty),
- "reloc_placeholder",
- NULL /* InsertBefore */,
- GlobalVariable::NotThreadLocal /* ThreadLocal */,
- 0 /* AddressSpace */);
-
- ////////////////////////////////////////////////////////////
- // Replace $__lldb_expr_result with a persistent variable
- //
-
- if (!CreateResultVariable(*main_function))
- {
- if (log)
- log->Printf("CreateResultVariable() failed");
-
- // CreateResultVariable() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream oss(s);
-
- m_module->print(oss, NULL);
-
- oss.flush();
-
- log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
- }
-
- for (Module::iterator fi = m_module->begin(), fe = m_module->end();
- fi != fe;
- ++fi)
- {
- llvm::Function *function = fi;
-
- if (function->begin() == function->end())
- continue;
-
- Function::iterator bbi;
-
- for (bbi = function->begin();
- bbi != function->end();
- ++bbi)
- {
- if (!RemoveGuards(*bbi))
- {
- if (log)
- log->Printf("RemoveGuards() failed");
-
- // RemoveGuards() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!RewritePersistentAllocs(*bbi))
- {
- if (log)
- log->Printf("RewritePersistentAllocs() failed");
-
- // RewritePersistentAllocs() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!RemoveCXAAtExit(*bbi))
- {
- if (log)
- log->Printf("RemoveCXAAtExit() failed");
-
- // RemoveCXAAtExit() reports its own errors, so we don't do so here
-
- return false;
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
- //
-
- if (!RewriteObjCConstStrings())
- {
- if (log)
- log->Printf("RewriteObjCConstStrings() failed");
-
- // RewriteObjCConstStrings() reports its own errors, so we don't do so here
-
- return false;
- }
-
- ///////////////////////////////
- // Resolve function pointers
- //
-
- if (!ResolveFunctionPointers(llvm_module))
- {
- if (log)
- log->Printf("ResolveFunctionPointers() failed");
-
- // ResolveFunctionPointers() reports its own errors, so we don't do so here
-
- return false;
- }
-
- for (Module::iterator fi = m_module->begin(), fe = m_module->end();
- fi != fe;
- ++fi)
- {
- llvm::Function *function = fi;
-
- for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
- bbi != bbe;
- ++bbi)
- {
- if (!RewriteObjCSelectors(*bbi))
- {
- if (log)
- log->Printf("RewriteObjCSelectors() failed");
-
- // RewriteObjCSelectors() reports its own errors, so we don't do so here
-
- return false;
- }
- }
- }
-
- for (Module::iterator fi = m_module->begin(), fe = m_module->end();
- fi != fe;
- ++fi)
- {
- llvm::Function *function = fi;
-
- for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
- bbi != bbe;
- ++bbi)
- {
- if (!ResolveCalls(*bbi))
- {
- if (log)
- log->Printf("ResolveCalls() failed");
-
- // ResolveCalls() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!ReplaceStaticLiterals(*bbi))
- {
- if (log)
- log->Printf("ReplaceStaticLiterals() failed");
-
- return false;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Run function-level passes that only make sense on the main function
- //
-
- if (!ResolveExternals(*main_function))
- {
- if (log)
- log->Printf("ResolveExternals() failed");
-
- // ResolveExternals() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!ReplaceVariables(*main_function))
- {
- if (log)
- log->Printf("ReplaceVariables() failed");
-
- // ReplaceVariables() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!ReplaceStrings())
- {
- if (log)
- log->Printf("ReplaceStrings() failed");
-
- return false;
- }
-
- if (!CompleteDataAllocation())
- {
- if (log)
- log->Printf("CompleteDataAllocation() failed");
-
- return false;
- }
-
- if (!StripAllGVs(llvm_module))
- {
- if (log)
- log->Printf("StripAllGVs() failed");
- }
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream oss(s);
-
- m_module->print(oss, NULL);
-
- oss.flush();
-
- log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str());
- }
-
- return true;
-}
-
-void
-IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type)
-{
-}
-
-PassManagerType
-IRForTarget::getPotentialPassManagerType() const
-{
- return PMT_ModulePassManager;
-}
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index 926d1f2..a2b0c5b 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -365,7 +365,7 @@ public:
const uint64_t *raw_data = resolved_value.getRawData();
- buffer.PutRawBytes(raw_data, constant_size, lldb::endian::InlHostByteOrder());
+ buffer.PutRawBytes(raw_data, constant_size, lldb_private::endian::InlHostByteOrder());
lldb_private::Error write_error;
@@ -498,7 +498,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
default:
{
if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -522,7 +522,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
if (!CanIgnoreCall(call_inst) && !support_function_calls)
{
if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -547,7 +547,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
default:
{
if (log)
- log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported ICmp predicate: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
@@ -655,7 +655,7 @@ IRInterpreter::Interpret (llvm::Module &module,
ai != ae;
++ai, ++arg_index)
{
- if (args.size() < static_cast<size_t>(arg_index))
+ if (args.size() <= static_cast<size_t>(arg_index))
{
error.SetErrorString ("Not enough arguments passed in to function");
return false;
@@ -663,16 +663,16 @@ IRInterpreter::Interpret (llvm::Module &module,
lldb::addr_t ptr = args[arg_index];
- frame.MakeArgument(ai, ptr);
+ frame.MakeArgument(&*ai, ptr);
}
uint32_t num_insts = 0;
- frame.Jump(function.begin());
+ frame.Jump(&function.front());
while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
{
- const Instruction *inst = frame.m_ii;
+ const Instruction *inst = &*frame.m_ii;
if (log)
log->Printf("Interpreting %s", PrintValue(inst).c_str());
diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp
index 4733b16..e96bddd 100644
--- a/source/Expression/IRMemoryMap.cpp
+++ b/source/Expression/IRMemoryMap.cpp
@@ -47,7 +47,7 @@ IRMemoryMap::~IRMemoryMap ()
}
lldb::addr_t
-IRMemoryMap::FindSpace (size_t size)
+IRMemoryMap::FindSpace (size_t size, bool zero_memory)
{
lldb::TargetSP target_sp = m_target_wp.lock();
lldb::ProcessSP process_sp = m_process_wp.lock();
@@ -60,7 +60,10 @@ IRMemoryMap::FindSpace (size_t size)
{
Error alloc_error;
- ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
+ if (!zero_memory)
+ ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
+ else
+ ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
if (!alloc_error.Success())
return LLDB_INVALID_ADDRESS;
@@ -225,7 +228,7 @@ IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
}
lldb::addr_t
-IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
+IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error)
{
lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
error.Clear();
@@ -263,7 +266,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
{
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!zero_memory)
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ else
+ allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
+
if (!error.Success())
return LLDB_INVALID_ADDRESS;
}
@@ -287,7 +294,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
{
if (process_sp->CanJIT() && process_sp->IsAlive())
{
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!zero_memory)
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ else
+ allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
+
if (!error.Success())
return LLDB_INVALID_ADDRESS;
}
diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp
new file mode 100644
index 0000000..eff0a2d
--- /dev/null
+++ b/source/Expression/LLVMUserExpression.cpp
@@ -0,0 +1,363 @@
+//===-- LLVMUserExpression.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
+
+// Project includes
+#include "lldb/Expression/LLVMUserExpression.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+using namespace lldb_private;
+
+LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
+ m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
+ m_stack_frame_top(LLDB_INVALID_ADDRESS),
+ m_transformed_text(),
+ m_execution_unit_sp(),
+ m_materializer_ap(),
+ m_jit_module_wp(),
+ m_enforce_valid_object(true),
+ m_in_cplusplus_method(false),
+ m_in_objectivec_method(false),
+ m_in_static_method(false),
+ m_needs_object_ptr(false),
+ m_const_object(false),
+ m_target(NULL),
+ m_can_interpret(false),
+ m_materialized_address(LLDB_INVALID_ADDRESS)
+{
+}
+
+LLVMUserExpression::~LLVMUserExpression()
+{
+ if (m_target)
+ {
+ lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+ if (jit_module_sp)
+ m_target->GetImages().Remove(jit_module_sp);
+ }
+}
+
+lldb::ExpressionResults
+LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+ // The expression log is quite verbose, and if you're just tracking the execution of the
+ // expression, it's quite convenient to have these logs come out with the STEP log as well.
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+
+ if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address))
+ {
+ error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+ if (m_can_interpret)
+ {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+ if (!module || !function)
+ {
+ error_stream.Printf("Supposed to interpret, but nothing is there");
+ return lldb::eExpressionSetupError;
+ }
+
+ Error interpreter_error;
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddArguments(exe_ctx, args, struct_address, error_stream))
+ {
+ error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ function_stack_bottom = m_stack_frame_bottom;
+ function_stack_top = m_stack_frame_top;
+
+ IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error,
+ function_stack_bottom, function_stack_top, exe_ctx);
+
+ if (!interpreter_error.Success())
+ {
+ error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+ return lldb::eExpressionDiscarded;
+ }
+ }
+ else
+ {
+ if (!exe_ctx.HasThreadScope())
+ {
+ error_stream.Printf("UserExpression::Execute called with no thread selected.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Address wrapper_address(m_jit_start_addr);
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddArguments(exe_ctx, args, struct_address, error_stream))
+ {
+ error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address,
+ args, options, shared_ptr_to_me));
+
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream))
+ return lldb::eExpressionSetupError;
+
+ ThreadPlanCallUserExpression *user_expression_plan =
+ static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
+ lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ lldb::ExpressionResults execution_result =
+ exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
+
+ if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
+ {
+ const char *error_desc = NULL;
+
+ if (call_plan_sp)
+ {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ error_stream.Printf("Execution was interrupted, reason: %s.", error_desc);
+ else
+ error_stream.PutCString("Execution was interrupted.");
+
+ if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) ||
+ (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+ error_stream.PutCString(
+ "\nThe process has been returned to the state before expression evaluation.");
+ else
+ {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ error_stream.PutCString(
+ "\nThe process has been left at the point where it was interrupted, "
+ "use \"thread return -x\" to return to the state before expression evaluation.");
+ }
+
+ return execution_result;
+ }
+ else if (execution_result == lldb::eExpressionStoppedForDebug)
+ {
+ error_stream.PutCString(
+ "Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression evaluation.");
+ return execution_result;
+ }
+ else if (execution_result != lldb::eExpressionCompleted)
+ {
+ error_stream.Printf("Couldn't execute function; result was %s\n",
+ Process::ExecutionResultAsCString(execution_result));
+ return execution_result;
+ }
+ }
+
+ if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
+ {
+ return lldb::eExpressionCompleted;
+ }
+ else
+ {
+ return lldb::eExpressionResultUnavailable;
+ }
+ }
+ else
+ {
+ error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
+ return lldb::eExpressionSetupError;
+ }
+}
+
+bool
+LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
+ lldb::addr_t function_stack_top)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
+
+ if (!m_dematerializer_sp)
+ {
+ error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present");
+ return false;
+ }
+
+ Error dematerialize_error;
+
+ m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
+
+ if (!dematerialize_error.Success())
+ {
+ error_stream.Printf("Couldn't apply expression side effects : %s\n",
+ dematerialize_error.AsCString("unknown error"));
+ return false;
+ }
+
+ result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
+
+ if (result)
+ result->TransferAddress();
+
+ m_dematerializer_sp.reset();
+
+ return true;
+}
+
+bool
+LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address)
+{
+ lldb::TargetSP target;
+ lldb::ProcessSP process;
+ lldb::StackFrameSP frame;
+
+ if (!LockAndCheckContext(exe_ctx, target, process, frame))
+ {
+ error_stream.Printf("The context has changed before we could JIT the expression!\n");
+ return false;
+ }
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ if (m_materialized_address == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ IRMemoryMap::AllocationPolicy policy =
+ m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
+
+ const bool zero_memory = false;
+
+ m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
+ m_materializer_ap->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ policy,
+ zero_memory,
+ alloc_error);
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ struct_address = m_materialized_address;
+
+ if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ const size_t stack_frame_size = 512 * 1024;
+
+ const bool zero_memory = false;
+
+ m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
+ 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyHostOnly,
+ zero_memory,
+ alloc_error);
+
+ m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ Error materialize_error;
+
+ m_dematerializer_sp =
+ m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+ if (!materialize_error.Success())
+ {
+ error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+lldb::ModuleSP
+LLVMUserExpression::GetJITModule()
+{
+ if (m_execution_unit_sp)
+ return m_execution_unit_sp->GetJITModule();
+ return lldb::ModuleSP();
+}
diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp
index ef01fee..8d68b4f 100644
--- a/source/Expression/Materializer.cpp
+++ b/source/Expression/Materializer.cpp
@@ -7,12 +7,15 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
@@ -48,7 +51,7 @@ Materializer::AddStructMember (Entity &entity)
}
void
-Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type)
+Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type)
{
m_size = type.GetByteSize(nullptr);
@@ -66,9 +69,11 @@ Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type)
class EntityPersistentVariable : public Materializer::Entity
{
public:
- EntityPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp) :
+ EntityPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
+ Materializer::PersistentVariableDelegate *delegate) :
Entity(),
- m_persistent_variable_sp(persistent_variable_sp)
+ m_persistent_variable_sp(persistent_variable_sp),
+ m_delegate(delegate)
{
// Hard-coding to maximum size of a pointer since persistent variables are materialized by reference
m_size = 8;
@@ -82,11 +87,13 @@ public:
// Allocate a spare memory area to store the persistent variable's contents.
Error allocate_error;
+ const bool zero_memory = false;
lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
8,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
allocate_error);
if (!allocate_error.Success())
@@ -99,21 +106,21 @@ public:
log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem);
// Put the location of the spare memory into the live data of the ValueObject.
-
+
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(),
- m_persistent_variable_sp->GetTypeFromUser(),
+ m_persistent_variable_sp->GetCompilerType(),
m_persistent_variable_sp->GetName(),
mem,
eAddressTypeLoad,
- m_persistent_variable_sp->GetByteSize());
+ map.GetAddressByteSize());
// Clear the flag if the variable will never be deallocated.
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
{
Error leak_error;
map.Leak(mem, leak_error);
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation;
}
// Write the contents of the variable to the area.
@@ -147,7 +154,10 @@ public:
}
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -161,17 +171,17 @@ public:
m_persistent_variable_sp->m_flags);
}
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation)
{
MakeAllocation(map, err);
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
if (!err.Success())
return;
}
- if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
- m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
+ if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
+ m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated)
{
Error write_error;
@@ -192,12 +202,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -211,10 +221,15 @@ public:
m_persistent_variable_sp->m_flags);
}
- if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
- (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
+ if (m_delegate)
+ {
+ m_delegate->DidDematerialize(m_persistent_variable_sp);
+ }
+
+ if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) ||
+ (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference))
{
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference &&
!m_persistent_variable_sp->m_live_sp)
{
// If the reference comes from the program, then the ClangExpressionVariable's
@@ -230,9 +245,9 @@ public:
err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
return;
}
-
+
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (),
- m_persistent_variable_sp->GetTypeFromUser(),
+ m_persistent_variable_sp.get()->GetCompilerType(),
m_persistent_variable_sp->GetName(),
location,
eAddressTypeLoad,
@@ -246,10 +261,10 @@ public:
// If the variable is resident in the stack frame created by the expression,
// then it cannot be relied upon to stay around. We treat it as needing
// reallocation.
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference;
}
}
@@ -267,8 +282,8 @@ public:
return;
}
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
- m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry ||
+ m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
{
if (log)
log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize());
@@ -290,7 +305,7 @@ public:
return;
}
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry;
}
}
else
@@ -305,14 +320,14 @@ public:
{
// Allocations are not persistent so persistent variables cannot stay materialized.
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
DestroyAllocation(map, err);
if (!err.Success())
return;
}
- else if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
- !(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
+ else if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation &&
+ !(m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget))
{
DestroyAllocation(map, err);
if (!err.Success())
@@ -320,7 +335,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -386,18 +401,22 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
- lldb::ClangExpressionVariableSP m_persistent_variable_sp;
+ lldb::ExpressionVariableSP m_persistent_variable_sp;
+ Materializer::PersistentVariableDelegate *m_delegate;
};
uint32_t
-Materializer::AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err)
+Materializer::AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
+ PersistentVariableDelegate *delegate,
+ Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityPersistentVariable (persistent_variable_sp));
+ iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
return ret;
@@ -416,10 +435,13 @@ public:
// Hard-coding to maximum size of a pointer since all variables are materialized by reference
m_size = 8;
m_alignment = 8;
- m_is_reference = m_variable_sp->GetType()->GetClangForwardType().IsReferenceType();
+ m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType();
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -525,15 +547,22 @@ public:
return;
}
- size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign();
+ size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign();
size_t byte_align = (bit_align + 7) / 8;
if (!byte_align)
byte_align = 1;
Error alloc_error;
+ const bool zero_memory = false;
+
+ m_temporary_allocation = map.Malloc(data.GetByteSize(),
+ byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
+ alloc_error);
- m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
m_temporary_allocation_size = data.GetByteSize();
m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
@@ -566,12 +595,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -650,7 +679,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -722,7 +751,7 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -735,6 +764,7 @@ public:
}
}
+
private:
lldb::VariableSP m_variable_sp;
bool m_is_reference;
@@ -756,20 +786,27 @@ Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
class EntityResultVariable : public Materializer::Entity
{
public:
- EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
+ EntityResultVariable (const CompilerType &type,
+ bool is_program_reference,
+ bool keep_in_memory,
+ Materializer::PersistentVariableDelegate *delegate) :
Entity(),
m_type(type),
m_is_program_reference(is_program_reference),
m_keep_in_memory(keep_in_memory),
m_temporary_allocation(LLDB_INVALID_ADDRESS),
- m_temporary_allocation_size(0)
+ m_temporary_allocation_size(0),
+ m_delegate(delegate)
{
// Hard-coding to maximum size of a pointer since all results are materialized by reference
m_size = 8;
m_alignment = 8;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
if (!m_is_program_reference)
{
@@ -789,8 +826,14 @@ public:
byte_align = 1;
Error alloc_error;
-
- m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
+ const bool zero_memory = true;
+
+ m_temporary_allocation = map.Malloc(byte_size,
+ byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
+ alloc_error);
m_temporary_allocation_size = byte_size;
if (!alloc_error.Success())
@@ -810,23 +853,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
- {
- err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
- }
-
- void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
- lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
err.Clear();
@@ -858,15 +890,30 @@ public:
return;
}
- ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
+ Error type_system_error;
+ TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage());
+
+ if (!type_system)
+ {
+ err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString());
+ return;
+ }
+
+ PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState();
+
+ if (!persistent_state)
+ {
+ err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables");
+ return;
+ }
- lldb::ClangExpressionVariableSP ret;
+ ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName();
- ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
- name,
- m_type,
- map.GetByteOrder(),
- map.GetAddressByteSize());
+ lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope,
+ name,
+ m_type,
+ map.GetByteOrder(),
+ map.GetAddressByteSize());
if (!ret)
{
@@ -876,6 +923,11 @@ public:
lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
+ if (m_delegate)
+ {
+ m_delegate->DidDematerialize(ret);
+ }
+
bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
if (can_persist && m_keep_in_memory)
@@ -900,12 +952,10 @@ public:
err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
return;
}
-
- result_variable_sp = ret;
if (!can_persist || !m_keep_in_memory)
{
- ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -915,14 +965,14 @@ public:
}
else
{
- ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
}
m_temporary_allocation = LLDB_INVALID_ADDRESS;
m_temporary_allocation_size = 0;
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -995,7 +1045,7 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -1007,23 +1057,28 @@ public:
m_temporary_allocation = LLDB_INVALID_ADDRESS;
m_temporary_allocation_size = 0;
}
+
private:
- TypeFromUser m_type;
+ CompilerType m_type;
bool m_is_program_reference;
bool m_keep_in_memory;
lldb::addr_t m_temporary_allocation;
size_t m_temporary_allocation_size;
+ Materializer::PersistentVariableDelegate *m_delegate;
};
uint32_t
-Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
+Materializer::AddResultVariable (const CompilerType &type,
+ bool is_program_reference,
+ bool keep_in_memory,
+ PersistentVariableDelegate *delegate,
+ Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
+ iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
- m_result_entity = iter->get();
return ret;
}
@@ -1039,7 +1094,10 @@ public:
m_alignment = 8;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1083,12 +1141,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1104,7 +1162,7 @@ public:
// no work needs to be done
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -1138,9 +1196,10 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
Symbol m_symbol;
};
@@ -1167,7 +1226,10 @@ public:
m_alignment = m_register_info.byte_size;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1223,12 +1285,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1280,7 +1342,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -1315,9 +1377,10 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
RegisterInfo m_register_info;
lldb::DataBufferSP m_register_contents;
@@ -1335,7 +1398,6 @@ Materializer::AddRegister (const RegisterInfo &register_info, Error &err)
Materializer::Materializer () :
m_dematerializer_wp(),
- m_result_entity(NULL),
m_current_offset(0),
m_struct_alignment(8)
{
@@ -1395,7 +1457,9 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb:
}
void
-Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
+Materializer::Dematerializer::Dematerialize (Error &error,
+ lldb::addr_t frame_bottom,
+ lldb::addr_t frame_top)
{
lldb::StackFrameSP frame_sp;
@@ -1428,14 +1492,7 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression
for (EntityUP &entity_up : m_materializer->m_entities)
{
- if (entity_up.get() == m_materializer->m_result_entity)
- {
- static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
- }
- else
- {
- entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
- }
+ entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
if (!error.Success())
break;
@@ -1456,7 +1513,9 @@ Materializer::Dematerializer::Wipe ()
entity_up->Wipe (*m_map, m_process_address);
}
- m_materializer = NULL;
- m_map = NULL;
+ m_materializer = nullptr;
+ m_map = nullptr;
m_process_address = LLDB_INVALID_ADDRESS;
}
+
+Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default;
diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp
new file mode 100644
index 0000000..1727a13
--- /dev/null
+++ b/source/Expression/REPL.cpp
@@ -0,0 +1,649 @@
+//===-- REPL.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
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Expression/REPL.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/AnsiTerminal.h"
+
+using namespace lldb_private;
+
+REPL::REPL(LLVMCastKind kind, Target &target) :
+ m_target(target),
+ m_kind(kind)
+{
+ // Make sure all option values have sane defaults
+ Debugger &debugger = m_target.GetDebugger();
+ CommandInterpreter &ci = debugger.GetCommandInterpreter();
+ m_format_options.OptionParsingStarting(ci);
+ m_varobj_options.OptionParsingStarting(ci);
+ m_command_options.OptionParsingStarting(ci);
+
+ // Default certain settings for REPL regardless of the global settings.
+ m_command_options.unwind_on_error = false;
+ m_command_options.ignore_breakpoints = false;
+ m_command_options.debug = false;
+}
+
+REPL::~REPL() = default;
+
+lldb::REPLSP
+REPL::Create(Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options)
+{
+ uint32_t idx = 0;
+ lldb::REPLSP ret;
+
+ while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++))
+ {
+ ret = (*create_instance)(err, language, debugger, target, repl_options);
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+std::string
+REPL::GetSourcePath()
+{
+ ConstString file_basename = GetSourceFileBasename();
+
+ FileSpec tmpdir_file_spec;
+ if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
+ m_repl_source_path = tmpdir_file_spec.GetPath();
+ }
+ else
+ {
+ tmpdir_file_spec = FileSpec("/tmp", false);
+ tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());
+ }
+
+ return tmpdir_file_spec.GetPath();
+}
+
+lldb::IOHandlerSP
+REPL::GetIOHandler()
+{
+ if (!m_io_handler_sp)
+ {
+ Debugger &debugger = m_target.GetDebugger();
+ m_io_handler_sp.reset (new IOHandlerEditline (debugger,
+ IOHandler::Type::REPL,
+ "lldb-repl", // Name of input reader for history
+ "> ", // prompt
+ ". ", // Continuation prompt
+ true, // Multi-line
+ true, // The REPL prompt is always colored
+ 1, // Line number
+ *this));
+
+ // Don't exit if CTRL+C is pressed
+ static_cast<IOHandlerEditline *>(m_io_handler_sp.get())->SetInterruptExits(false);
+
+ if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal())
+ {
+ m_indent_str.assign (debugger.GetTabSize(), ' ');
+ m_enable_auto_indent = debugger.GetAutoIndent();
+ }
+ else
+ {
+ m_indent_str.clear();
+ m_enable_auto_indent = false;
+ }
+
+ }
+ return m_io_handler_sp;
+}
+
+void
+REPL::IOHandlerActivated (IOHandler &io_handler)
+{
+ lldb::ProcessSP process_sp = m_target.GetProcessSP();
+ if (process_sp && process_sp->IsAlive())
+ return;
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ error_sp->Printf("REPL requires a running target process.\n");
+ io_handler.SetIsDone(true);
+}
+
+bool
+REPL::IOHandlerInterrupt (IOHandler &io_handler)
+{
+ return false;
+}
+
+void
+REPL::IOHandlerInputInterrupted (IOHandler &io_handler,
+ std::string &line)
+{
+}
+
+const char *
+REPL::IOHandlerGetFixIndentationCharacters()
+{
+ return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr);
+}
+
+ConstString
+REPL::IOHandlerGetControlSequence (char ch)
+{
+ if (ch == 'd')
+ return ConstString(":quit\n");
+ return ConstString();
+}
+
+const char *
+REPL::IOHandlerGetCommandPrefix ()
+{
+ return ":";
+}
+
+const char *
+REPL::IOHandlerGetHelpPrologue ()
+{
+ return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
+ "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n"
+ "The complete set of LLDB debugging commands are also available as described below. Commands "
+ "must be prefixed with a colon at the REPL prompt (:quit for example.) Typing just a colon "
+ "followed by return will switch to the LLDB prompt.\n\n";
+}
+
+bool
+REPL::IOHandlerIsInputComplete (IOHandler &io_handler,
+ StringList &lines)
+{
+ // Check for meta command
+ const size_t num_lines = lines.GetSize();
+ if (num_lines == 1)
+ {
+ const char *first_line = lines.GetStringAtIndex(0);
+ if (first_line[0] == ':')
+ return true; // Meta command is a single line where that starts with ':'
+ }
+
+ // Check if REPL input is done
+ std::string source_string (lines.CopyList());
+ return SourceIsComplete(source_string);
+}
+
+int
+REPL::CalculateActualIndentation (const StringList &lines)
+{
+ std::string last_line = lines[lines.GetSize() - 1];
+
+ int actual_indent = 0;
+ for (char &ch : last_line)
+ {
+ if (ch != ' ') break;
+ ++actual_indent;
+ }
+
+ return actual_indent;
+}
+
+int
+REPL::IOHandlerFixIndentation (IOHandler &io_handler,
+ const StringList &lines,
+ int cursor_position)
+{
+ if (!m_enable_auto_indent) return 0;
+
+ if (!lines.GetSize())
+ {
+ return 0;
+ }
+
+ int tab_size = io_handler.GetDebugger().GetTabSize();
+
+ lldb::offset_t desired_indent = GetDesiredIndentation(lines,
+ cursor_position,
+ tab_size);
+
+ int actual_indent = REPL::CalculateActualIndentation(lines);
+
+ if (desired_indent == LLDB_INVALID_OFFSET)
+ return 0;
+
+ return (int)desired_indent - actual_indent;
+}
+
+void
+REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code)
+{
+ lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ bool extra_line = false;
+ bool did_quit = false;
+
+ if (code.empty())
+ {
+ m_code.AppendString("");
+ static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
+ }
+ else
+ {
+ Debugger &debugger = m_target.GetDebugger();
+ CommandInterpreter &ci = debugger.GetCommandInterpreter();
+ extra_line = ci.GetSpaceReplPrompts();
+
+ ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get());
+
+ lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());
+
+ if (code[0] == ':')
+ {
+ // Meta command
+ // Strip the ':'
+ code.erase(0, 1);
+ if (Args::StripSpaces (code))
+ {
+ // "lldb" was followed by arguments, so just execute the command dump the results
+
+ // Turn off prompt on quit in case the user types ":quit"
+ const bool saved_prompt_on_quit = ci.GetPromptOnQuit();
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(false);
+
+ // Execute the command
+ CommandReturnObject result;
+ result.SetImmediateOutputStream(output_sp);
+ result.SetImmediateErrorStream(error_sp);
+ ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
+
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(true);
+
+ if (result.GetStatus() == lldb::eReturnStatusQuit)
+ {
+ did_quit = true;
+ io_handler.SetIsDone(true);
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
+ {
+ // We typed "quit" or an alias to quit so we need to check if the
+ // command interpreter is above us and tell it that it is done as well
+ // so we don't drop back into the command interpreter if we have already
+ // quit
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ io_handler_sp->SetIsDone(true);
+ }
+ }
+ }
+ else
+ {
+ // ":" was followed by no arguments, so push the LLDB command prompt
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
+ {
+ // If the user wants to get back to the command interpreter and the
+ // command interpreter is what launched the REPL, then just let the
+ // REPL exit and fall back to the command interpreter.
+ io_handler.SetIsDone(true);
+ }
+ else
+ {
+ // The REPL wasn't launched the by the command interpreter, it is the
+ // base IOHandler, so we need to get the command interpreter and
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ }
+ }
+ else
+ {
+ // Unwind any expression we might have been running in case our REPL
+ // expression crashed and the user was looking around
+ if (m_dedicated_repl_mode)
+ {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread && thread->UnwindInnermostExpression().Success())
+ {
+ thread->SetSelectedFrameByIndex(0, false);
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+
+ const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
+
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetCoerceToId(m_varobj_options.use_objc);
+ expr_options.SetUnwindOnError(m_command_options.unwind_on_error);
+ expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
+ expr_options.SetKeepInMemory(true);
+ expr_options.SetUseDynamic(m_varobj_options.use_dynamic);
+ expr_options.SetTryAllThreads(m_command_options.try_all_threads);
+ expr_options.SetGenerateDebugInfo(true);
+ expr_options.SetREPLEnabled (true);
+ expr_options.SetColorizeErrors(colorize_err);
+ expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1);
+ if (m_command_options.timeout > 0)
+ expr_options.SetTimeoutUsec(m_command_options.timeout);
+ else
+ expr_options.SetTimeoutUsec(0);
+
+ expr_options.SetLanguage(GetLanguage());
+
+ PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
+
+ const size_t var_count_before = persistent_state->GetSize();
+
+ const char *expr_prefix = nullptr;
+ lldb::ValueObjectSP result_valobj_sp;
+ Error error;
+ lldb::ModuleSP jit_module_sp;
+ lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ code.c_str(),
+ expr_prefix,
+ result_valobj_sp,
+ error,
+ 0, // Line offset
+ &jit_module_sp);
+
+ //CommandInterpreter &ci = debugger.GetCommandInterpreter();
+
+ if (process_sp && process_sp->IsAlive())
+ {
+ bool add_to_code = true;
+ bool handled = false;
+ if (result_valobj_sp)
+ {
+ lldb::Format format = m_format_options.GetFormat();
+
+ if (result_valobj_sp->GetError().Success())
+ {
+ handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp);
+ }
+ else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
+ {
+ if (format != lldb::eFormatVoid && debugger.GetNotifyVoid())
+ {
+ error_sp->PutCString("(void)\n");
+ handled = true;
+ }
+ }
+ }
+
+ if (debugger.GetPrintDecls())
+ {
+ for (size_t vi = var_count_before, ve = persistent_state->GetSize();
+ vi != ve;
+ ++vi)
+ {
+ lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi);
+ lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
+
+ PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get());
+ }
+ }
+
+ if (!handled)
+ {
+ bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
+ switch (execution_results)
+ {
+ case lldb::eExpressionSetupError:
+ case lldb::eExpressionParseError:
+ add_to_code = false;
+ // Fall through
+ case lldb::eExpressionDiscarded:
+ error_sp->Printf("%s\n", error.AsCString());
+ break;
+
+ case lldb::eExpressionCompleted:
+ break;
+ case lldb::eExpressionInterrupted:
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ error_sp->Printf("Execution interrupted. ");
+ if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n");
+ break;
+
+ case lldb::eExpressionHitBreakpoint:
+ // Breakpoint was hit, drop into LLDB command interpreter
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ output_sp->Printf("Execution stopped at breakpoint. ");
+ if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n");
+ {
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ break;
+
+ case lldb::eExpressionTimedOut:
+ error_sp->Printf("error: timeout\n");
+ if (error.AsCString())
+ error_sp->Printf("error: %s\n", error.AsCString());
+ break;
+ case lldb::eExpressionResultUnavailable:
+ // Shoulnd't happen???
+ error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString());
+ break;
+ case lldb::eExpressionStoppedForDebug:
+ // Shoulnd't happen???
+ error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString());
+ break;
+ }
+ }
+
+ if (add_to_code)
+ {
+ const uint32_t new_default_line = m_code.GetSize() + 1;
+
+ m_code.SplitIntoLines(code);
+
+ // Update our code on disk
+ if (!m_repl_source_path.empty())
+ {
+ lldb_private::File file (m_repl_source_path.c_str(),
+ File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCanCreate,
+ lldb::eFilePermissionsFileDefault);
+ std::string code (m_code.CopyList());
+ code.append(1, '\n');
+ size_t bytes_written = code.size();
+ file.Write(code.c_str(), bytes_written);
+ file.Close();
+
+ // Now set the default file and line to the REPL source file
+ m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line);
+ }
+ static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
+ }
+ if (extra_line)
+ {
+ fprintf(output_sp->GetFile().GetStream(), "\n");
+ }
+ }
+ }
+
+ // Don't complain about the REPL process going away if we are in the process of quitting.
+ if (!did_quit && (!process_sp || !process_sp->IsAlive()))
+ {
+ error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n");
+ io_handler.SetIsDone(true);
+ }
+ }
+}
+
+int
+REPL::IOHandlerComplete (IOHandler &io_handler,
+ const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches,
+ StringList &matches)
+{
+ matches.Clear();
+
+ llvm::StringRef line (current_line, cursor - current_line);
+
+ // Complete an LLDB command if the first character is a colon...
+ if (!line.empty() && line[0] == ':')
+ {
+ Debugger &debugger = m_target.GetDebugger();
+
+ // auto complete LLDB commands
+ const char *lldb_current_line = line.substr(1).data();
+ return debugger.GetCommandInterpreter().HandleCompletion (lldb_current_line,
+ cursor,
+ last_char,
+ skip_first_n_matches,
+ max_matches,
+ matches);
+ }
+
+ // Strip spaces from the line and see if we had only spaces
+ line = line.ltrim();
+ if (line.empty())
+ {
+ // Only spaces on this line, so just indent
+ matches.AppendString(m_indent_str);
+ return 1;
+ }
+
+ std::string current_code;
+ current_code.append(m_code.CopyList());
+
+ IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);
+ const StringList *current_lines = editline.GetCurrentLines();
+ if (current_lines)
+ {
+ const uint32_t current_line_idx = editline.GetCurrentLineIndex();
+
+ if (current_line_idx < current_lines->GetSize())
+ {
+ for (uint32_t i=0; i<current_line_idx; ++i)
+ {
+ const char *line_cstr = current_lines->GetStringAtIndex(i);
+ if (line_cstr)
+ {
+ current_code.append("\n");
+ current_code.append (line_cstr);
+ }
+ }
+ }
+ }
+
+ if (cursor > current_line)
+ {
+ current_code.append("\n");
+ current_code.append(current_line, cursor - current_line);
+ }
+
+ return CompleteCode(current_code, matches);
+}
+
+bool
+QuitCommandOverrideCallback(void *baton, const char **argv)
+{
+ Target *target = (Target *)baton;
+ lldb::ProcessSP process_sp (target->GetProcessSP());
+ if (process_sp)
+ {
+ process_sp->Destroy(false);
+ process_sp->GetTarget().GetDebugger().ClearIOHandlers();
+ }
+ return false;
+}
+
+Error
+REPL::RunLoop ()
+{
+ Error error;
+
+ error = DoInitialization();
+ m_repl_source_path = GetSourcePath();
+
+ if (!error.Success())
+ return error;
+
+ Debugger &debugger = m_target.GetDebugger();
+
+ lldb::IOHandlerSP io_handler_sp (GetIOHandler());
+
+ FileSpec save_default_file;
+ uint32_t save_default_line = 0;
+
+ if (!m_repl_source_path.empty())
+ {
+ // Save the current default file and line
+ m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line);
+ }
+
+ debugger.PushIOHandler(io_handler_sp);
+
+ // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option
+ // from the command line. Currently we know this by checking if the debugger already
+ // has a IOHandler thread.
+ if (!debugger.HasIOHandlerThread())
+ {
+ // The debugger doesn't have an existing IOHandler thread, so this must be
+ // dedicated REPL mode...
+ m_dedicated_repl_mode = true;
+ debugger.StartIOHandlerThread();
+ std::string command_name_str ("quit");
+ CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str);
+ if (cmd_obj)
+ {
+ assert(command_name_str.empty());
+ cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target);
+ }
+ }
+
+ // Wait for the REPL command interpreter to get popped
+ io_handler_sp->WaitForPop();
+
+ if (m_dedicated_repl_mode)
+ {
+ // If we were in dedicated REPL mode we would have started the
+ // IOHandler thread, and we should kill our process
+ lldb::ProcessSP process_sp = m_target.GetProcessSP();
+ if (process_sp && process_sp->IsAlive())
+ process_sp->Destroy(false);
+
+ // Wait for the IO handler thread to exit (TODO: don't do this if the IO handler thread already exists...)
+ debugger.JoinIOHandlerThread();
+ }
+
+ // Restore the default file and line
+ if (save_default_file && save_default_line != 0)
+ m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, save_default_line);
+ return error;
+}
diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp
new file mode 100644
index 0000000..70f004b
--- /dev/null
+++ b/source/Expression/UserExpression.cpp
@@ -0,0 +1,348 @@
+//===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Expression/UserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+using namespace lldb_private;
+
+UserExpression::UserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options) :
+ Expression(exe_scope),
+ m_expr_text(expr),
+ m_expr_prefix(expr_prefix ? expr_prefix : ""),
+ m_language(language),
+ m_desired_type(desired_type),
+ m_options (options)
+{
+}
+
+UserExpression::~UserExpression ()
+{
+}
+
+void
+UserExpression::InstallContext (ExecutionContext &exe_ctx)
+{
+ m_jit_process_wp = exe_ctx.GetProcessSP();
+
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+
+ if (frame_sp)
+ m_address = frame_sp->GetFrameCodeAddress();
+}
+
+bool
+UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
+ lldb::TargetSP &target_sp,
+ lldb::ProcessSP &process_sp,
+ lldb::StackFrameSP &frame_sp)
+{
+ lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
+ process_sp = exe_ctx.GetProcessSP();
+
+ if (process_sp != expected_process_sp)
+ return false;
+
+ process_sp = exe_ctx.GetProcessSP();
+ target_sp = exe_ctx.GetTargetSP();
+ frame_sp = exe_ctx.GetFrameSP();
+
+ if (m_address.IsValid())
+ {
+ if (!frame_sp)
+ return false;
+ else
+ return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
+ }
+
+ return true;
+}
+
+bool
+UserExpression::MatchesContext (ExecutionContext &exe_ctx)
+{
+ lldb::TargetSP target_sp;
+ lldb::ProcessSP process_sp;
+ lldb::StackFrameSP frame_sp;
+
+ return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
+}
+
+lldb::addr_t
+UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err)
+{
+ err.Clear();
+
+ if (!frame_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::VariableSP var_sp;
+ lldb::ValueObjectSP valobj_sp;
+
+ valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
+ lldb::eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+ StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+ var_sp,
+ err);
+
+ if (!err.Success() || !valobj_sp.get())
+ return LLDB_INVALID_ADDRESS;
+
+ lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ret == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return ret;
+}
+
+lldb::ExpressionResults
+UserExpression::Evaluate (ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error,
+ uint32_t line_offset,
+ lldb::ModuleSP *jit_module_sp_ptr)
+{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ lldb::LanguageType language = options.GetLanguage();
+ const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == NULL || process->GetState() != lldb::eStateStopped)
+ {
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ error.SetErrorString ("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ if (process == NULL || !process->CanJIT())
+ execution_policy = eExecutionPolicyNever;
+
+ const char *full_prefix = NULL;
+ const char *option_prefix = options.GetPrefix();
+ std::string full_prefix_storage;
+ if (expr_prefix && option_prefix)
+ {
+ full_prefix_storage.assign(expr_prefix);
+ full_prefix_storage.append(option_prefix);
+ if (!full_prefix_storage.empty())
+ full_prefix = full_prefix_storage.c_str();
+ }
+ else if (expr_prefix)
+ full_prefix = expr_prefix;
+ else
+ full_prefix = option_prefix;
+
+ // If the language was not specified in the expression command,
+ // set it to the language in the target's properties if
+ // specified, else default to the langage for the frame.
+ if (language == lldb::eLanguageTypeUnknown)
+ {
+ if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
+ language = target->GetLanguage();
+ else if (StackFrame *frame = exe_ctx.GetFramePtr())
+ language = frame->GetLanguage();
+ }
+
+ lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
+ full_prefix,
+ language,
+ desired_type,
+ options,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
+ return lldb::eExpressionSetupError;
+ }
+
+ StreamString error_stream;
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
+
+ const bool keep_expression_in_memory = true;
+ const bool generate_debug_info = options.GetGenerateDebugInfo();
+
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
+ {
+ error.SetErrorString ("expression interrupted by callback before parse");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (!user_expression_sp->Parse (error_stream,
+ exe_ctx,
+ execution_policy,
+ keep_expression_in_memory,
+ generate_debug_info))
+ {
+ execution_results = lldb::eExpressionParseError;
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
+ if (jit_module_sp_ptr)
+ *jit_module_sp_ptr = user_expression_sp->GetJITModule();
+
+ lldb::ExpressionVariableSP expr_result;
+
+ if (execution_policy == eExecutionPolicyNever &&
+ !user_expression_sp->CanInterpret())
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
+ }
+ else
+ {
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ error_stream.GetString().clear();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Executing expression ==");
+
+ execution_results = user_expression_sp->Execute (error_stream,
+ exe_ctx,
+ options,
+ user_expression_sp,
+ expr_result);
+
+ if (options.GetResultIsInternal() && expr_result && process)
+ {
+ process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
+ }
+
+ if (execution_results != lldb::eExpressionCompleted)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ if (expr_result)
+ {
+ result_valobj_sp = expr_result->GetValueObject();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
+ result_valobj_sp->GetValueAsCString());
+ }
+ else
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
+
+ error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
+ }
+ }
+ }
+ }
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (result_valobj_sp.get() == NULL)
+ {
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ }
+
+ return execution_results;
+}
diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp
new file mode 100644
index 0000000..f93e358
--- /dev/null
+++ b/source/Expression/UtilityFunction.cpp
@@ -0,0 +1,124 @@
+//===-- ClangUserExpression.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
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+// C++ Includes
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+//------------------------------------------------------------------
+/// Constructor
+///
+/// @param[in] text
+/// The text of the function. Must be a full translation unit.
+///
+/// @param[in] name
+/// The name of the function, as used in the text.
+//------------------------------------------------------------------
+UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name) :
+ Expression (exe_scope),
+ m_execution_unit_sp (),
+ m_jit_module_wp (),
+ m_function_text (ExpressionSourceCode::g_expression_prefix),
+ m_function_name (name)
+{
+ if (text && text[0])
+ m_function_text.append (text);
+}
+
+UtilityFunction::~UtilityFunction ()
+{
+ lldb::ProcessSP process_sp (m_jit_process_wp.lock());
+ if (process_sp)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
+
+}
+
+// FIXME: We should check that every time this is called it is called with the same return type & arguments...
+
+FunctionCaller *
+UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error)
+{
+ if (m_caller_up)
+ return m_caller_up.get();
+
+ ProcessSP process_sp = m_jit_process_wp.lock();
+ if (!process_sp)
+ return nullptr;
+
+ Address impl_code_address;
+ impl_code_address.SetOffset(StartAddress());
+ std::string name(m_function_name);
+ name.append("-caller");
+
+ m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(),
+ return_type,
+ impl_code_address,
+ arg_value_list,
+ name.c_str(),
+ error));
+ if (error.Fail())
+ {
+
+ return nullptr;
+ }
+ if (m_caller_up)
+ {
+ StreamString errors;
+ errors.Clear();
+ unsigned num_errors = m_caller_up->CompileFunction(errors);
+ if (num_errors)
+ {
+ error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+
+ errors.Clear();
+ ExecutionContext exe_ctx(process_sp);
+
+ if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors))
+ {
+ error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+ }
+ return m_caller_up.get();
+}
OpenPOWER on IntegriCloud