diff options
author | emaste <emaste@FreeBSD.org> | 2014-11-26 16:48:12 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2014-11-26 16:48:12 +0000 |
commit | 0147dda7de9580d13778ecb4c9e92b83b7a63911 (patch) | |
tree | b16dc95f693ed59342b6141cd3fd9f59a6cd7e7e /contrib/llvm/tools/lldb/source/Expression | |
parent | bfd4c39c61ae9b29542625bb12b6f7f4b1f8c727 (diff) | |
parent | 01ee1789d6aa7294e5966a97f8d29387f6f81699 (diff) | |
download | FreeBSD-src-0147dda7de9580d13778ecb4c9e92b83b7a63911.zip FreeBSD-src-0147dda7de9580d13778ecb4c9e92b83b7a63911.tar.gz |
Update LLDB snapshot to upstream r216948 (git 50f7fe44)
This is approximately "LLDB 3.5" although with a little bit of skew,
and will go along with the Clang 3.5 import.
Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Expression')
17 files changed, 3554 insertions, 3013 deletions
diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp b/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp index 76c2577..2f14721 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp @@ -40,7 +40,7 @@ ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, { if (!m_passthrough) return; - + m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } @@ -49,10 +49,10 @@ ASTResultSynthesizer::~ASTResultSynthesizer() } void -ASTResultSynthesizer::Initialize(ASTContext &Context) +ASTResultSynthesizer::Initialize(ASTContext &Context) { m_ast_context = &Context; - + if (m_passthrough) m_passthrough->Initialize(Context); } @@ -75,11 +75,11 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) } } - + 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) @@ -107,53 +107,53 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) } } -bool +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 +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); @@ -161,14 +161,14 @@ ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) { 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; } @@ -176,67 +176,67 @@ 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, +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()) @@ -249,28 +249,28 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, 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. // @@ -302,7 +302,7 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, // // - 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 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 @@ -310,46 +310,46 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, // // - During dematerialization, $0 is ignored. - bool is_lvalue = + 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(), @@ -358,69 +358,69 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, 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.take(), true, false); + + 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, + + result_decl = VarDecl::Create(Ctx, + DC, SourceLocation(), SourceLocation(), - &result_id, - expr_qual_type, - NULL, + &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.take()); + + *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); } @@ -429,8 +429,8 @@ void ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) { typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator; - - for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), + + for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), e = TypeDeclIterator(FunDeclCtx->decls_end()); i != e; ++i) @@ -439,35 +439,35 @@ ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) } } -void +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(), + + 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 +void ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) -{ +{ if (m_passthrough) m_passthrough->HandleTagDeclDefinition(D); } @@ -479,15 +479,15 @@ ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) m_passthrough->CompleteTentativeDefinition(D); } -void -ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) +void +ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { if (m_passthrough) m_passthrough->HandleVTable(RD, DefinitionRequired); } void -ASTResultSynthesizer::PrintStats() +ASTResultSynthesizer::PrintStats() { if (m_passthrough) m_passthrough->PrintStats(); @@ -497,16 +497,16 @@ void ASTResultSynthesizer::InitializeSema(Sema &S) { m_sema = &S; - + if (m_passthrough_sema) m_passthrough_sema->InitializeSema(S); } -void -ASTResultSynthesizer::ForgetSema() +void +ASTResultSynthesizer::ForgetSema() { m_sema = NULL; - + if (m_passthrough_sema) m_passthrough_sema->ForgetSema(); } diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp b/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp index d1f2192..2a8b7bc 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp @@ -39,7 +39,7 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, { if (!m_passthrough) return; - + m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } @@ -48,10 +48,10 @@ ASTStructExtractor::~ASTStructExtractor() } void -ASTStructExtractor::Initialize(ASTContext &Context) +ASTStructExtractor::Initialize(ASTContext &Context) { m_ast_context = &Context; - + if (m_passthrough) m_passthrough->Initialize(Context); } @@ -61,17 +61,17 @@ 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) @@ -95,26 +95,26 @@ ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) 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_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; } @@ -122,11 +122,11 @@ 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) @@ -134,9 +134,9 @@ ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) 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())) @@ -145,20 +145,20 @@ ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) } } -bool +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; @@ -166,12 +166,12 @@ ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) -{ +{ if (m_passthrough) m_passthrough->HandleTranslationUnit(Ctx); } -void +void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) { if (m_passthrough) @@ -185,15 +185,15 @@ ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) m_passthrough->CompleteTentativeDefinition(D); } -void -ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) +void +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { if (m_passthrough) m_passthrough->HandleVTable(RD, DefinitionRequired); } void -ASTStructExtractor::PrintStats() +ASTStructExtractor::PrintStats() { if (m_passthrough) m_passthrough->PrintStats(); @@ -204,17 +204,17 @@ 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() +void +ASTStructExtractor::ForgetSema() { m_sema = NULL; m_action = NULL; - + if (m_passthrough_sema) m_passthrough_sema->ForgetSema(); } diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp index 853d102..d488993 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp @@ -25,32 +25,32 @@ using namespace clang; using namespace lldb_private; -ClangASTSource::~ClangASTSource() +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) +ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) { if (!m_ast_context) return; - + m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); } @@ -59,33 +59,33 @@ ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) bool ClangASTSource::FindExternalVisibleDeclsByName ( - const DeclContext *decl_ctx, + 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) { @@ -94,27 +94,27 @@ ClangASTSource::FindExternalVisibleDeclsByName } } 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; + 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); @@ -131,21 +131,21 @@ ClangASTSource::FindExternalVisibleDeclsByName if (!GetLookupsEnabled()) { - // Wait until we see a '$' at the start of a name before we start doing + // 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()) { @@ -157,7 +157,7 @@ ClangASTSource::FindExternalVisibleDeclsByName // 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; + 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); @@ -168,50 +168,48 @@ ClangASTSource::FindExternalVisibleDeclsByName 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, - m_ast_context, - tag_decl, + 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] "); } - + 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, - namespace_map.get(), - (int)namespace_map->size()); - + 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) @@ -221,80 +219,80 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) 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 + 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:"); @@ -305,28 +303,46 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) 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", m_ast_context, interface_decl->getName().str().c_str()); + 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] "); + 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] "); + dumper.ToLog(log, " [COID] "); } } @@ -334,36 +350,36 @@ 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; } @@ -375,83 +391,82 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, 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; - + 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, - m_ast_context, + current_id, static_cast<void*>(m_ast_context), context_named_decl->getNameAsString().c_str(), context_decl->getDeclKindName(), - context_decl, + 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, - m_ast_context, - context_decl->getDeclKindName(), - context_decl, + 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, - m_ast_context, + 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, original_ctx, original_decl); + { + 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) @@ -462,35 +477,35 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, 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; } @@ -498,41 +513,48 @@ 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, m_ast_context, name.GetCString()); + 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, m_ast_context, name.GetCString(), context_named_decl->getNameAsString().c_str()); + 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, m_ast_context, name.GetCString(), context.m_decl_context->getDeclKindName()); + 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, - namespace_map.get(), - (int)namespace_map->size()); - + 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) @@ -542,7 +564,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) current_id, i->second.GetNamespaceDecl()->getNameAsString().c_str(), i->first->GetFileSpec().GetFilename().GetCString()); - + FindExternalVisibleDecls(context, i->first, i->second, @@ -561,158 +583,158 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) 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)", + log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", current_id, - context.m_namespace_map.get(), - (int)context.m_namespace_map->size()); - + 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, +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(), + name.GetCString(), module_sp->GetFileSpec().GetFilename().GetCString()); } } } - else + 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(), + name.GetCString(), image->GetFileSpec().GetFilename().GetCString()); } } } - - do + + 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 + else m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); - + 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(), + + 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); } else @@ -720,55 +742,55 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, 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; - + TypeVendor *type_vendor = language_runtime->GetTypeVendor(); - + if (!type_vendor) break; - + bool append = false; uint32_t max_matches = 1; std::vector <ClangASTType> types; - + if (!type_vendor->FindTypes(name, append, max_matches, types)) break; - + if (log) - { + { log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", current_id, name.GetCString()); } - + ClangASTType copied_clang_type (GuardedCopyType(types[0])); - + if (!copied_clang_type) { if (log) log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", current_id); - + break; } - + context.AddTypeDecl(copied_clang_type); } while(0); } - + } while(0); } @@ -782,7 +804,7 @@ public: D *decl; }; -template <class D2, template <class D> class TD, class D1> +template <class D2, template <class D> class TD, class D1> TD<D2> DynCast(TD<D1> source) { @@ -792,19 +814,19 @@ DynCast(TD<D1> source) template <class D = Decl> class DeclFromParser; template <class D = Decl> class DeclFromUser; -template <class D> class DeclFromParser : public TaggedASTDecl<D> { +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> { +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); }; @@ -841,7 +863,7 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id, clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); Selector original_selector; - + if (decl_name.isObjCZeroArgSelector()) { IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); @@ -857,59 +879,59 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id, 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); - + ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name); - + if (result.empty()) return false; - + if (!result[0]) return false; - + for (NamedDecl *named_decl : result) { ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl); - + if (!result_method) return false; - + Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); - + if (!copied_decl) return false; - + ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); - + if (!copied_method_decl) return false; - + 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; } @@ -917,30 +939,30 @@ 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, @@ -949,9 +971,9 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) "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()); @@ -961,234 +983,232 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) 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.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, - m_ast_context, - interface_decl->getNameAsString().c_str(), + 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, - complete_interface_decl, - &complete_iface_decl->getASTContext()); - + 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 runtime only if the debug information didn't have a complete interface. - + lldb::ProcessSP process(m_target->GetProcessSP()); - + if (!process) break; - + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - + if (!language_runtime) break; - + TypeVendor *type_vendor = language_runtime->GetTypeVendor(); - + if (!type_vendor) break; - + ConstString interface_name(interface_decl->getNameAsString().c_str()); bool append = false; uint32_t max_matches = 1; std::vector <ClangASTType> types; - + if (!type_vendor->FindTypes(interface_name, append, max_matches, types)) break; - + const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); - + const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type); - + if (!runtime_interface_type) break; - + ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl(); - + FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, @@ -1200,7 +1220,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) } static bool -FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, +FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, NameSearchContext &context, clang::ASTContext &ast_context, ClangASTImporter *ast_importer, @@ -1210,15 +1230,15 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, 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)); @@ -1229,14 +1249,14 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, 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)); @@ -1247,12 +1267,12 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, 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; } @@ -1263,109 +1283,107 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) 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, - m_ast_context, - parser_iface_decl->getNameAsString().c_str(), + 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, + + 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, - origin_iface_decl.decl, - &origin_iface_decl->getASTContext()); - + 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, - complete_iface_decl.decl, - &complete_iface_decl->getASTContext()); - - FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, + 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 runtime only if the debug information didn't have a complete interface. - + lldb::ProcessSP process(m_target->GetProcessSP()); - + if (!process) return; - + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - + if (!language_runtime) return; - + TypeVendor *type_vendor = language_runtime->GetTypeVendor(); - + if (!type_vendor) break; - + bool append = false; uint32_t max_matches = 1; std::vector <ClangASTType> types; - + if (!type_vendor->FindTypes(class_name, append, max_matches, types)) break; - + const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type); - + if (!runtime_interface_type) break; - + DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(runtime_interface_type->getDecl()); - + if (log) log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", current_id, - runtime_iface_decl.decl, - &runtime_iface_decl->getASTContext()); - + static_cast<const void*>(runtime_iface_decl.decl), + static_cast<void*>(&runtime_iface_decl->getASTContext())); + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *m_ast_context, @@ -1381,13 +1399,13 @@ typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap; template <class D, class O> static bool -ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, +ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, llvm::DenseMap <const D*, O> &source_map, ClangASTImporter *importer, ASTContext &dest_ctx) { typedef llvm::DenseMap <const D*, O> MapType; - + for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end(); fi != fe; ++fi) @@ -1398,7 +1416,7 @@ ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, return false; destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second)); } - + return true; } @@ -1406,102 +1424,98 @@ template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record DeclFromUser<const CXXRecordDecl> &record, BaseOffsetMap &base_offsets) { - for (CXXRecordDecl::base_class_const_iterator - bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), + 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 + +bool ClangASTSource::layoutRecordType(const RecordDecl *record, - uint64_t &size, + 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, - m_ast_context, - record, + 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)); @@ -1517,14 +1531,15 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, !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, origin_record.decl); + 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); @@ -1533,10 +1548,8 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, ++fi) { log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", - current_id, - *fi, - fi->getNameAsString().c_str(), - field_offsets[*fi]); + 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()) @@ -1547,19 +1560,19 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, ++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 " : ""), - base_cxx_record.decl, + 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())); + (is_virtual + ? virtual_base_offsets[base_cxx_record.decl].getQuantity() + : base_offsets[base_cxx_record.decl].getQuantity())); } } else @@ -1567,36 +1580,33 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); } } - + return true; } -void +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, - m_ast_context, + 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, - m_ast_context, + 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(); @@ -1604,28 +1614,28 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac ++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(), + name.GetCString(), module_sp->GetFileSpec().GetFilename().GetCString()); } } @@ -1633,36 +1643,36 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac { 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(), + name.GetCString(), image->GetFileSpec().GetFilename().GetCString()); } } @@ -1673,23 +1683,23 @@ ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::Name { 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); } @@ -1697,18 +1707,18 @@ 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); } @@ -1719,39 +1729,39 @@ NameSearchContext::AddVarDecl(const ClangASTType &type) 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(), + const_cast<DeclContext*>(m_decl_context), + SourceLocation(), SourceLocation(), - ii, + ii, type.GetQualType(), - 0, + 0, SC_Static); m_decls.push_back(Decl); - + return Decl; } clang::NamedDecl * -NameSearchContext::AddFunDecl (const ClangASTType &type) +NameSearchContext::AddFunDecl (const ClangASTType &type) { 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; @@ -1773,20 +1783,20 @@ NameSearchContext::AddFunDecl (const ClangASTType &type) // 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*>(m_decl_context), SourceLocation(), @@ -1797,7 +1807,7 @@ NameSearchContext::AddFunDecl (const ClangASTType &type) SC_Static, NULL)); } - + func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls)); } else @@ -1807,9 +1817,9 @@ NameSearchContext::AddFunDecl (const ClangASTType &type) if (log) log->Printf("Function type wasn't a FunctionProtoType"); } - + m_decls.push_back(func_decl); - + return func_decl; } @@ -1817,13 +1827,13 @@ 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)); } @@ -1837,32 +1847,32 @@ NameSearchContext::AddTypeDecl(const ClangASTType &clang_type) 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 +void NameSearchContext::AddLookupResult (clang::DeclContextLookupConstResult result) { for (clang::NamedDecl *decl : result) diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp index 198fde9..43c8a5f 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -8,11 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/ClangExpressionDeclMap.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Decl.h" @@ -68,21 +63,21 @@ 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 - + // that valuable lookup data (like namespaces) doesn't vanish, but + DidParse(); DisableStructVars(); } -bool +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); @@ -98,18 +93,18 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, 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; } @@ -120,7 +115,7 @@ ClangExpressionDeclMap::DidParse() if (log) ClangASTMetrics::DumpCounters(log); - + if (m_parser_vars.get()) { for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); @@ -131,7 +126,7 @@ ClangExpressionDeclMap::DidParse() 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) @@ -140,20 +135,20 @@ ClangExpressionDeclMap::DidParse() if (pvar_sp) pvar_sp->DisableParserVars(GetParserID()); } - + DisableParserVars(); } } // Interface for IRForTarget -ClangExpressionDeclMap::TargetInfo +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(); @@ -162,7 +157,7 @@ ClangExpressionDeclMap::GetTargetInfo() ret.byte_order = process->GetByteOrder(); ret.address_byte_size = process->GetAddressByteSize(); } - else + else { Target *target = exe_ctx.GetTargetPtr(); if (target) @@ -175,61 +170,61 @@ ClangExpressionDeclMap::GetTargetInfo() return ret; } -bool -ClangExpressionDeclMap::AddPersistentVariable +bool +ClangExpressionDeclMap::AddPersistentVariable ( - const NamedDecl *decl, - const ConstString &name, + 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(); @@ -237,38 +232,38 @@ ClangExpressionDeclMap::AddPersistentVariable return false; ASTContext *context(target->GetScratchClangASTContext()->getASTContext()); - - TypeFromUser user_type(m_ast_importer->DeportType(context, + + 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; @@ -278,88 +273,87 @@ ClangExpressionDeclMap::AddPersistentVariable 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 +bool +ClangExpressionDeclMap::AddValueToStruct ( const NamedDecl *decl, const ConstString &name, llvm::Value *value, size_t size, - off_t alignment + 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", - decl, - name.GetCString(), + 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; @@ -379,16 +373,16 @@ ClangExpressionDeclMap::AddValueToStruct 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; } @@ -396,81 +390,81 @@ 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 +bool ClangExpressionDeclMap::GetStructInfo ( uint32_t &num_elements, size_t &size, - off_t &alignment + 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 +bool +ClangExpressionDeclMap::GetStructElement ( const NamedDecl *&decl, llvm::Value *&value, - off_t &offset, + 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 +ClangExpressionDeclMap::GetFunctionInfo ( - const NamedDecl *decl, + const NamedDecl *decl, uint64_t &ptr ) { @@ -478,14 +472,14 @@ ClangExpressionDeclMap::GetFunctionInfo 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; } @@ -500,7 +494,7 @@ FindCodeSymbolInContext SymbolContextList temp_sc_list; if (sym_ctx.module_sp) sym_ctx.module_sp->FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list); - + if (!sc_list.GetSize() && sym_ctx.target_sp) sym_ctx.target_sp->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list); @@ -527,14 +521,14 @@ FindCodeSymbolInContext } bool -ClangExpressionDeclMap::GetFunctionAddress +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(); @@ -545,25 +539,25 @@ ClangExpressionDeclMap::GetFunctionAddress 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 + // 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(); } @@ -574,37 +568,25 @@ ClangExpressionDeclMap::GetFunctionAddress SymbolContext sym_ctx; sc_list.GetContextAtIndex(i, sym_ctx); - const Address *func_so_addr = NULL; - bool is_indirect_function = false; + lldb::addr_t callable_load_addr = LLDB_INVALID_ADDRESS; + if (sym_ctx.function) - func_so_addr = &sym_ctx.function->GetAddressRange().GetBaseAddress(); - else if (sym_ctx.symbol) { - if (sym_ctx.symbol->GetType() == eSymbolTypeReExported) - { - Symbol *reexported_symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); - if (reexported_symbol) - { - func_so_addr = &reexported_symbol->GetAddress(); - is_indirect_function = reexported_symbol->IsIndirect(); - } - } - else + const Address func_so_addr = sym_ctx.function->GetAddressRange().GetBaseAddress(); + if (func_so_addr.IsValid()) { - func_so_addr = &sym_ctx.symbol->GetAddress(); - is_indirect_function = sym_ctx.symbol->IsIndirect(); + callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false); } } + else if (sym_ctx.symbol) + { + callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); + } - if (func_so_addr && func_so_addr->IsValid()) + if (callable_load_addr != LLDB_INVALID_ADDRESS) { - lldb::addr_t load_addr = func_so_addr->GetCallableLoadAddress (target, is_indirect_function); - - if (load_addr != LLDB_INVALID_ADDRESS) - { - func_addr = load_addr; - return true; - } + func_addr = callable_load_addr; + return true; } } return false; @@ -618,12 +600,12 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, 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; @@ -631,12 +613,12 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, { SymbolContext sym_ctx; sc_list.GetContextAtIndex(i, sym_ctx); - + const Address *sym_address = &sym_ctx.symbol->GetAddress(); - + if (!sym_address || !sym_address->IsValid()) continue; - + if (sym_address) { switch (sym_ctx.symbol->GetType()) @@ -702,17 +684,17 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, } } } - + if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) { ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); - + if (runtime) { symbol_load_addr = runtime->LookupRuntimeSymbol(name); } } - + return symbol_load_addr; } @@ -720,10 +702,10 @@ 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); } @@ -733,12 +715,12 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, 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) { @@ -748,7 +730,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, { const Symbol *symbol = sym_ctx.symbol; const Address *sym_address = &symbol->GetAddress(); - + if (sym_address && sym_address->IsValid()) { switch (symbol->GetType()) @@ -790,7 +772,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, } } break; - + case eSymbolTypeCode: // We already lookup functions elsewhere case eSymbolTypeVariable: case eSymbolTypeLocal: @@ -818,7 +800,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, } } } - + return NULL; } @@ -833,12 +815,12 @@ ClangExpressionDeclMap::FindGlobalVariable ) { 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) @@ -846,7 +828,7 @@ ClangExpressionDeclMap::FindGlobalVariable 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; } @@ -856,7 +838,7 @@ ClangExpressionDeclMap::FindGlobalVariable return vars.GetVariableAtIndex(0); } } - + return VariableSP(); } @@ -866,23 +848,23 @@ 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) @@ -892,20 +874,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) 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, - namespace_map.get(), + 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) @@ -915,7 +896,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) current_id, i->second.GetNamespaceDecl()->getNameAsString().c_str(), i->first->GetFileSpec().GetFilename().GetCString()); - + FindExternalVisibleDecls(context, i->first, i->second, @@ -925,65 +906,65 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) 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, +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 + + // 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(); @@ -991,59 +972,59 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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; } } @@ -1055,22 +1036,22 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, // 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) @@ -1078,89 +1059,89 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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; } @@ -1172,22 +1153,22 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, // 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 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->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; @@ -1198,19 +1179,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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; } @@ -1219,66 +1200,66 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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); } } @@ -1288,11 +1269,11 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, ValueObjectSP valobj; VariableSP var; Error err; - + if (frame && !namespace_decl) { - valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr, - eNoDynamicValues, + valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr, + eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember || StackFrame::eExpressionPathOptionsAllowDirectIVarAccess || StackFrame::eExpressionPathOptionsNoFragileObjcIvar || @@ -1300,7 +1281,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var, err); - + // If we found a variable in scope, no need to pull up function names if (err.Success() && var) { @@ -1309,7 +1290,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, return; } } - + if (target) { var = FindGlobalVariable (*target, @@ -1317,7 +1298,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, name, &namespace_decl, NULL); - + if (var) { valobj = ValueObjectVariable::Create(target, var); @@ -1326,19 +1307,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, return; } } - + 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, + eFunctionNameTypeBase, include_symbols, include_inlines, append, @@ -1347,63 +1328,63 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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, + 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) + 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) { if (extern_symbol) @@ -1418,14 +1399,14 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, } } } - + 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 + // 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: "); @@ -1440,43 +1421,43 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, } } -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(); -} +//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, @@ -1485,25 +1466,25 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var, TypeFromParser *parser_type) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + Type *var_type = var->GetType(); - - if (!var_type) + + 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) @@ -1513,25 +1494,16 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var, return false; } //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); - + DWARFExpression &var_location_expr = var->LocationExpression(); - - lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; - - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - if (var_location_expr.IsLocationList()) - { - SymbolContext var_sc; - var->CalculateSymbolContext (&var_sc); - loclist_base_load_addr = var_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); - } + 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()); @@ -1544,45 +1516,45 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var, 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; } @@ -1590,21 +1562,21 @@ 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)) @@ -1612,8 +1584,8 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v 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; @@ -1621,11 +1593,11 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v 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()); @@ -1634,45 +1606,45 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v 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); + 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, + 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); @@ -1681,59 +1653,59 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, } void -ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, +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, + 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 +bool ClangExpressionDeclMap::ResolveUnknownTypes() { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1746,82 +1718,82 @@ ClangExpressionDeclMap::ResolveUnknownTypes() ++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, + 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); @@ -1832,7 +1804,7 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, parser_vars->m_llvm_value = NULL; parser_vars->m_lldb_value.Clear(); entity->m_flags |= ClangExpressionVariable::EVBareRegister; - + if (log) { ASTDumper ast_dumper(var_decl); @@ -1847,9 +1819,9 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, unsigned int current_id) { assert (m_parser_vars.get()); - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + NamedDecl *function_decl = NULL; const Address *fun_address = NULL; ClangASTType function_clang_type; @@ -1859,30 +1831,30 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, 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) @@ -1891,7 +1863,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, function_type->GetName().GetCString(), function_type->GetID()); } - + return; } } @@ -1904,7 +1876,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, function_type->GetName().GetCString(), function_type->GetID()); } - + return; } } @@ -1920,11 +1892,11 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, 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)); @@ -1936,7 +1908,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, entity->EnableParserVars(GetParserID()); ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - + if (load_addr != LLDB_INVALID_ADDRESS) { parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); @@ -1945,25 +1917,25 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, 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"), @@ -1978,14 +1950,14 @@ 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(); } @@ -1993,21 +1965,21 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut, { 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, @@ -2018,26 +1990,26 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut, is_attr_used, is_artificial); } - + return TypeFromParser(copied_clang_type); } -void -ClangExpressionDeclMap::AddOneType(NameSearchContext &context, +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/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp index 615f29f..f32ca3a 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" +#include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" @@ -24,6 +25,9 @@ #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" @@ -55,11 +59,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/TargetSelect.h" -#if defined (USE_STANDARD_JIT) -#include "llvm/ExecutionEngine/JIT.h" -#else #include "llvm/ExecutionEngine/MCJIT.h" -#endif #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" @@ -88,89 +88,8 @@ std::string GetBuiltinIncludePath(const char *Argv0) { llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, "include"); } - - return P.str(); -} - - -//===----------------------------------------------------------------------===// -// Main driver for Clang -//===----------------------------------------------------------------------===// - -static void LLVMErrorHandler(void *UserData, const std::string &Message) { - DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); - - Diags.Report(diag::err_fe_error_backend) << Message; - - // We cannot recover from llvm errors. - assert(0); -} -static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { - using namespace clang::frontend; - - switch (CI.getFrontendOpts().ProgramAction) { - default: - llvm_unreachable("Invalid program action!"); - - case ASTDump: return new ASTDumpAction(); - case ASTPrint: return new ASTPrintAction(); - case ASTView: return new ASTViewAction(); - case DumpRawTokens: return new DumpRawTokensAction(); - case DumpTokens: return new DumpTokensAction(); - case EmitAssembly: return new EmitAssemblyAction(); - case EmitBC: return new EmitBCAction(); - case EmitHTML: return new HTMLPrintAction(); - case EmitLLVM: return new EmitLLVMAction(); - case EmitLLVMOnly: return new EmitLLVMOnlyAction(); - case EmitCodeGenOnly: return new EmitCodeGenOnlyAction(); - case EmitObj: return new EmitObjAction(); - case FixIt: return new FixItAction(); - case GeneratePCH: return new GeneratePCHAction(); - case GeneratePTH: return new GeneratePTHAction(); - case InitOnly: return new InitOnlyAction(); - case ParseSyntaxOnly: return new SyntaxOnlyAction(); - - case PluginAction: { - for (FrontendPluginRegistry::iterator it = - FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); - it != ie; ++it) { - if (it->getName() == CI.getFrontendOpts().ActionName) { - llvm::OwningPtr<PluginASTAction> P(it->instantiate()); - if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs)) - return 0; - return P.take(); - } - } - - CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) - << CI.getFrontendOpts().ActionName; - return 0; - } - - case PrintDeclContext: return new DeclContextPrintAction(); - case PrintPreamble: return new PrintPreambleAction(); - case PrintPreprocessedInput: return new PrintPreprocessedAction(); - case RewriteMacros: return new RewriteMacrosAction(); - case RewriteObjC: return new RewriteObjCAction(); - case RewriteTest: return new RewriteTestAction(); - //case RunAnalysis: return new AnalysisAction(); - case RunPreprocessorOnly: return new PreprocessOnlyAction(); - } -} - -static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { - // Create the underlying action. - FrontendAction *Act = CreateFrontendBaseAction(CI); - if (!Act) - return 0; - - // If there are any AST files to merge, create a frontend action - // adaptor to perform the merge. - if (!CI.getFrontendOpts().ASTMergeFiles.empty()) - Act = new ASTMergeAction(Act, CI.getFrontendOpts().ASTMergeFiles); - - return Act; + return P.str(); } //===----------------------------------------------------------------------===// @@ -178,30 +97,21 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { //===----------------------------------------------------------------------===// ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, - ClangExpression &expr) : + ClangExpression &expr, + bool generate_debug_info) : m_expr (expr), m_compiler (), m_code_generator () { - // Initialize targets first, so that --version shows registered targets. - static struct InitializeLLVM { - InitializeLLVM() { - llvm::InitializeAllTargets(); - llvm::InitializeAllAsmPrinters(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllDisassemblers(); - } - } InitializeLLVM; - // 1. Create a new compiler instance. - m_compiler.reset(new CompilerInstance()); - + 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 @@ -210,48 +120,40 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, if (target_sp && target_sp->GetArchitecture().IsValid()) { std::string triple = target_sp->GetArchitecture().GetTriple().str(); - - int dash_count = 0; - for (size_t i = 0; i < triple.size(); ++i) - { - if (triple[i] == '-') - dash_count++; - if (dash_count == 3) - { - triple.resize(i); - break; - } - } - 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"); } - - if (m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) + + // 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->getTargetOpts())); - + 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: @@ -272,20 +174,20 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getLangOpts().CPlusPlus11 = 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; - + // 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; - + m_compiler->getLangOpts().SpellChecking = false; + lldb::ProcessSP process_sp; if (exe_scope) process_sp = exe_scope->CalculateProcess(); @@ -298,7 +200,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, 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; } @@ -307,62 +209,67 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, 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().setDiagnosticGroupMapping("unused-value", clang::diag::MAP_IGNORE, SourceLocation()); - m_compiler->getDiagnostics().setDiagnosticGroupMapping("odr", clang::diag::MAP_IGNORE, SourceLocation()); - + 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().setForcedLangOptions(m_compiler->getLangOpts()); - + 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(); - - // 6. Most of this we get from the CompilerInstance, but we + m_compiler->createPreprocessor(TU_Complete); + + // 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->getTarget(), m_compiler->getPreprocessor().getIdentifierTable(), *m_selector_table.get(), - *m_builtin_context.get(), - 0)); - + *m_builtin_context.get())); + ast_context->InitBuiltinTypes(m_compiler->getTarget()); + ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); - + if (decl_map) { - llvm::OwningPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy()); + 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()); @@ -381,34 +288,77 @@ unsigned ClangExpressionParser::Parse (Stream &stream) { TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient()); - + diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); - - MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__); - m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer); - + + 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; + + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + tmpdir_file_spec.AppendPathComponent("expr.XXXXXX"); + temp_source_path = std::move(tmpdir_file_spec.GetPath()); + } + else + { + temp_source_path = "/tmp/expr.XXXXXX"; + } + + if (mktemp(&temp_source_path[0])) + { + lldb_private::File file (temp_source_path.c_str(), + File::eOpenOptionWrite | File::eOpenOptionCanCreateNewOnly, + lldb::eFilePermissionsFileDefault); + 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(temp_source_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 (ast_transformer) ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); - else - ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), 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; - + 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()); - + num_errors = 0; - + for (diag_iterator = diag_buf->err_begin(); diag_iterator != diag_buf->err_end(); ++diag_iterator) @@ -416,12 +366,12 @@ ClangExpressionParser::Parse (Stream &stream) 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()) @@ -430,7 +380,7 @@ ClangExpressionParser::Parse (Stream &stream) num_errors++; } } - + return num_errors; } @@ -441,21 +391,21 @@ static bool FindFunctionInModule (ConstString &mangled_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, +ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, - std::unique_ptr<IRExecutionUnit> &execution_unit_ap, + std::shared_ptr<IRExecutionUnit> &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) @@ -464,24 +414,22 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - std::unique_ptr<llvm::ExecutionEngine> execution_engine_ap; - Error err; - - std::unique_ptr<llvm::Module> module_ap (m_code_generator->ReleaseModule()); - if (!module_ap.get()) + 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, module_ap.get(), m_expr.FunctionName())) + + 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()); @@ -492,54 +440,54 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } - - m_execution_unit.reset(new IRExecutionUnit(m_llvm_context, // handed off here - module_ap, // handed off here - function_name, - exe_ctx.GetTargetSP(), - m_compiler->getTargetOpts().Features)); - + + 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(), - *m_execution_unit, + *execution_unit_sp, error_stream, function_name.AsCString()); - - bool ir_can_run = ir_for_target.runOnModule(*m_execution_unit->GetModule()); - + + bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); + Error interpret_error; - - can_interpret = IRInterpreter::CanInterpret(*m_execution_unit->GetModule(), *m_execution_unit->GetFunction(), interpret_error); - + + can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); + Process *process = exe_ctx.GetProcessPtr(); - + 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) @@ -547,44 +495,50 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, 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(*m_execution_unit->GetModule())) + + if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } - - m_execution_unit->GetRunnableInfo(err, func_addr, func_end); + + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { - m_execution_unit->GetRunnableInfo(err, func_addr, func_end); + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } - - execution_unit_ap.reset (m_execution_unit.release()); - + return err; } + +bool +ClangExpressionParser::GetGenerateDebugInfo () const +{ + if (m_compiler) + return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo; + return false; +} diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp index 0d355ce..c3eae41 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp @@ -8,11 +8,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/ClangExpressionVariable.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "clang/AST/ASTContext.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" @@ -44,17 +39,17 @@ ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &val //---------------------------------------------------------------------- /// Return the variable's size in bytes //---------------------------------------------------------------------- -size_t +size_t ClangExpressionVariable::GetByteSize () { return m_frozen_sp->GetByteSize(); -} +} const ConstString & ClangExpressionVariable::GetName () { return m_frozen_sp->GetName(); -} +} lldb::ValueObjectSP ClangExpressionVariable::GetValueObject() @@ -78,13 +73,13 @@ ClangASTType ClangExpressionVariable::GetClangType() { return m_frozen_sp->GetClangType(); -} +} void ClangExpressionVariable::SetClangType(const ClangASTType &clang_type) { m_frozen_sp->GetValue().SetClangType(clang_type); -} +} TypeFromUser @@ -92,7 +87,7 @@ ClangExpressionVariable::GetTypeFromUser() { TypeFromUser tfu (m_frozen_sp->GetClangType()); return tfu; -} +} uint8_t * ClangExpressionVariable::GetValueBytes() @@ -130,7 +125,7 @@ ClangExpressionVariable::TransferAddress (bool force) 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/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp index e707c60..27afba2 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp @@ -22,18 +22,20 @@ #include "llvm/IR/Module.h" // Project includes -#include "lldb/Expression/ASTStructExtractor.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Symbol/Type.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #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/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" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -41,7 +43,6 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" -#include "lldb/Core/Log.h" using namespace lldb_private; @@ -53,8 +54,13 @@ ClangFunction::ClangFunction ExecutionContextScope &exe_scope, const ClangASTType &return_type, const Address& functionAddress, - const ValueList &arg_value_list + const ValueList &arg_value_list, + const char *name ) : + m_parser(), + m_execution_unit_sp(), + m_jit_module_wp(), + m_name (name ? name : "<unknown>"), m_function_ptr (NULL), m_function_addr (functionAddress), m_function_return_type(return_type), @@ -75,8 +81,10 @@ ClangFunction::ClangFunction ExecutionContextScope &exe_scope, Function &function, ClangASTContext *ast_context, - const ValueList &arg_value_list + const ValueList &arg_value_list, + const char *name ) : + m_name (name ? name : "<unknown>"), m_function_ptr (&function), m_function_addr (), m_function_return_type (), @@ -87,7 +95,7 @@ ClangFunction::ClangFunction m_compiled (false), m_JITted (false) { - m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + m_jit_process_wp = exe_scope.CalculateProcess(); // Can't make a ClangFunction without a process. assert (m_jit_process_wp.lock()); @@ -100,6 +108,13 @@ ClangFunction::ClangFunction //---------------------------------------------------------------------- ClangFunction::~ClangFunction() { + 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); + } } unsigned @@ -173,7 +188,7 @@ ClangFunction::CompileFunction (Stream &errors) } else { - errors.Printf("Could not determine type of input value %zu.", i); + errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); return 1; } } @@ -222,7 +237,8 @@ ClangFunction::CompileFunction (Stream &errors) lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (jit_process_sp) { - m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this)); + 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); } @@ -263,7 +279,7 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, m_jit_end_addr, - m_execution_unit_ap, + m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways)); @@ -271,8 +287,22 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) if (!jit_error.Success()) return false; + if (m_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; + process->GetTarget().GetImages().Append(jit_module_sp); + } + } if (process && m_jit_start_addr) - m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + m_jit_process_wp = process->shared_from_this(); m_JITted = true; @@ -304,7 +334,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, Error error; using namespace clang; - ExecutionResults return_value = eExecutionSetupError; + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); @@ -344,7 +374,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { - errors.Printf ("Wrong number of arguments - was: %zu should be: %zu", num_args, m_arg_values.GetSize()); + errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } @@ -401,7 +431,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 --"); + log->Printf("-- [ClangFunction::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(); @@ -438,7 +468,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) - log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results --"); + log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); Process *process = exe_ctx.GetProcessPtr(); @@ -472,7 +502,7 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_ exe_ctx.GetProcessRef().DeallocateMemory(args_addr); } -ExecutionResults +lldb::ExpressionResults ClangFunction::ExecuteFunction( ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, @@ -481,7 +511,7 @@ ClangFunction::ExecuteFunction( Value &results) { using namespace clang; - ExecutionResults return_value = eExecutionSetupError; + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; // ClangFunction::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. @@ -498,27 +528,27 @@ ClangFunction::ExecuteFunction( args_addr = LLDB_INVALID_ADDRESS; if (CompileFunction(errors) != 0) - return eExecutionSetupError; + return lldb::eExpressionSetupError; if (args_addr == LLDB_INVALID_ADDRESS) { if (!InsertFunction(exe_ctx, args_addr, errors)) - return eExecutionSetupError; + return lldb::eExpressionSetupError; } Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) - log->Printf("== [ClangFunction::ExecuteFunction] Executing function =="); + log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx, args_addr, real_options, errors)); if (!call_plan_sp) - return eExecutionSetupError; + return lldb::eExpressionSetupError; - // <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here + // We need to make sure we record the fact that we are running an expression here // otherwise this fact will fail to be recorded when fetching an Objective-C object description if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); @@ -530,13 +560,13 @@ ClangFunction::ExecuteFunction( if (log) { - if (return_value != eExecutionCompleted) + if (return_value != lldb::eExpressionCompleted) { - log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally =="); + log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); } else { - log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally =="); + log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); } } @@ -546,7 +576,7 @@ ClangFunction::ExecuteFunction( if (args_addr_ptr != NULL) *args_addr_ptr = args_addr; - if (return_value != eExecutionCompleted) + if (return_value != lldb::eExpressionCompleted) return return_value; FetchFunctionResults(exe_ctx, args_addr, results); @@ -554,7 +584,7 @@ ClangFunction::ExecuteFunction( if (args_addr_ptr == NULL) DeallocateFunctionResults(exe_ctx, args_addr); - return eExecutionCompleted; + return lldb::eExpressionCompleted; } clang::ASTConsumer * diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp index 6b0eee8..52ef4d3 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp @@ -7,19 +7,18 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <stdio.h> #if HAVE_SYS_TYPES_H # include <sys/types.h> #endif -// C++ Includes #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" @@ -32,10 +31,12 @@ #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" -#include "lldb/Host/Host.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" @@ -63,6 +64,11 @@ ClangUserExpression::ClangUserExpression (const char *expr, 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_cplusplus (false), m_objectivec (false), @@ -91,6 +97,12 @@ ClangUserExpression::ClangUserExpression (const char *expr, 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 * @@ -98,7 +110,7 @@ ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) { m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough, *m_target)); - + return m_result_synthesizer.get(); } @@ -109,16 +121,16 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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) { @@ -126,19 +138,19 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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) @@ -154,7 +166,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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()) @@ -162,60 +174,60 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } - + m_cplusplus = 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) || + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } } - + m_objectivec = true; m_needs_object_ptr = true; - + if (!method_decl->isInstanceMethod()) m_static_method = true; } @@ -226,7 +238,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) // object pointer. The best way to deal with getting to the ivars at present it 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()) { @@ -236,17 +248,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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)) @@ -255,7 +267,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) return; } } - + m_cplusplus = true; m_needs_object_ptr = true; } @@ -264,17 +276,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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)) @@ -282,23 +294,23 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) 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; @@ -328,9 +340,9 @@ 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(); } @@ -346,11 +358,11 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, 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) @@ -358,7 +370,7 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, else return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); } - + return true; } @@ -368,7 +380,7 @@ 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); } @@ -383,7 +395,7 @@ ApplyObjcCastHack(std::string &expr) #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); @@ -396,99 +408,100 @@ ApplyObjcCastHack(std::string &expr) // 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 -} +//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, +ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory) + 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::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str())); - + lldb::LanguageType lang_type; - + if (m_cplusplus) lang_type = lldb::eLanguageTypeC_plus_plus; else if(m_objectivec) lang_type = lldb::eLanguageTypeObjC; else lang_type = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method)) + + if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_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(); @@ -496,50 +509,81 @@ ClangUserExpression::Parse (Stream &error_stream, 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); - + + 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_ap, + 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) @@ -563,16 +607,16 @@ GetObjectPointer (lldb::StackFrameSP frame_sp, 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 || @@ -582,18 +626,18 @@ GetObjectPointer (lldb::StackFrameSP frame_sp, StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var_sp, err); - + if (!err.Success()) 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; } @@ -607,22 +651,22 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, lldb::TargetSP target; lldb::ProcessSP process; lldb::StackFrameSP frame; - + if (!LockAndCheckContext(exe_ctx, target, - process, + 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_cplusplus) { object_name.SetCString("this"); @@ -636,23 +680,23 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, 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_objectivec) { 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()); @@ -660,56 +704,56 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, } } } - + 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_ap->Malloc(m_materializer_ap->GetStructByteSize(), + + 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_ap->Malloc(stack_frame_size, + + 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_ap, struct_address, 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 struct: %s\n", materialize_error.AsCString()); + error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); return false; } } @@ -724,18 +768,18 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, 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()) @@ -743,16 +787,16 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, 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; -} +} -ExecutionResults +lldb::ExpressionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, @@ -766,110 +810,118 @@ ClangUserExpression::Execute (Stream &error_stream, 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 eExecutionSetupError; + 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_ap->GetModule(); - llvm::Function *function = m_execution_unit_ap->GetFunction(); - + { + 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 eExecutionSetupError; + 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_objectivec) 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_ap.get(), + *m_execution_unit_sp.get(), interpreter_error, function_stack_bottom, function_stack_top); - + if (!interpreter_error.Success()) { error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); - return eExecutionDiscarded; + 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_objectivec) 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)); - + + ThreadPlanCallUserExpression *user_expression_plan = + new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), + wrapper_address, + args, + options, + shared_ptr_to_me); + lldb::ThreadPlanSP call_plan_sp(user_expression_plan); + if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) - return eExecutionSetupError; - - lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer(); + return lldb::eExpressionSetupError; - function_stack_bottom = function_stack_pointer - Host::GetPageSize(); + 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); - - ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, + + 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 == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint) + 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(); @@ -880,45 +932,51 @@ ClangUserExpression::Execute (Stream &error_stream, error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); else error_stream.PutCString ("Execution was interrupted."); - - if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError()) - || (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints())) + + 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 - 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."); + { + 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 == eExecutionStoppedForDebug) + 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" + 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 != eExecutionCompleted) + 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 eExecutionCompleted; + return lldb::eExpressionCompleted; } else { - return eExecutionSetupError; + return lldb::eExpressionResultUnavailable; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); - return eExecutionSetupError; + return lldb::eExpressionSetupError; } } -ExecutionResults +lldb::ExpressionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, @@ -931,8 +989,8 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); const lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; - ExecutionResults execution_results = eExecutionSetupError; - + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) @@ -941,31 +999,43 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, { 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; - + ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_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; - - if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory)) + 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)) { if (error_stream.GetString().empty()) - error.SetErrorString ("expression failed to parse, unknown error"); + error.SetExpressionError (lldb::eExpressionParseError, "expression failed to parse, unknown error"); else - error.SetErrorString (error_stream.GetString().c_str()); + error.SetExpressionError (lldb::eExpressionParseError, error_stream.GetString().c_str()); } else { @@ -976,53 +1046,72 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - + if (error_stream.GetString().empty()) - error.SetErrorString ("expression needed to run but couldn't"); + 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, + execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); - - if (execution_results != eExecutionCompleted) + + if (options.GetResultIsInternal()) + { + 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.SetErrorString ("expression failed to execute, unknown error"); + error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else - error.SetErrorString (error_stream.GetString().c_str()); + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } - else + 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()); + 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); diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp index c911c27..de5b0c1 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp @@ -17,6 +17,7 @@ #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" @@ -42,6 +43,9 @@ using namespace lldb_private; 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) { @@ -51,6 +55,14 @@ ClangUtilityFunction::ClangUtilityFunction (const char *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); + } + } //------------------------------------------------------------------ @@ -108,8 +120,9 @@ ClangUtilityFunction::Install (Stream &error_stream, error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; } - - ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this); + + const bool generate_debug_info = true; + ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); unsigned num_errors = parser.Parse (error_stream); @@ -130,13 +143,29 @@ ClangUtilityFunction::Install (Stream &error_stream, Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, - m_execution_unit_ap, + m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) - m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + { + 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 diff --git a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp index 28aa6d0..44b64ab 100644 --- a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp @@ -282,6 +282,33 @@ DWARFExpression::CopyOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& } void +DWARFExpression::CopyOpcodeData (const void *data, + lldb::offset_t data_length, + ByteOrder byte_order, + uint8_t addr_byte_size) +{ + if (data && data_length) + { + m_data.SetData(DataBufferSP(new DataBufferHeap(data, data_length))); + m_data.SetByteOrder(byte_order); + m_data.SetAddressByteSize(addr_byte_size); + } +} + +void +DWARFExpression::CopyOpcodeData (uint64_t const_value, + lldb::offset_t const_value_byte_size, + uint8_t addr_byte_size) +{ + if (const_value_byte_size) + { + m_data.SetData(DataBufferSP(new DataBufferHeap(&const_value, const_value_byte_size))); + m_data.SetByteOrder(endian::InlHostByteOrder()); + m_data.SetAddressByteSize(addr_byte_size); + } +} + +void DWARFExpression::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) { m_module_wp = module_sp; @@ -728,7 +755,7 @@ static bool ReadRegisterValueAsScalar ( RegisterContext *reg_ctx, - uint32_t reg_kind, + lldb::RegisterKind reg_kind, uint32_t reg_num, Error *error_ptr, Value &value @@ -1307,11 +1334,11 @@ DWARFExpression::Evaluate ClangExpressionVariableList *expr_locals, ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, - lldb::ModuleSP opcode_ctx, + lldb::ModuleSP module_sp, const DataExtractor& opcodes, const lldb::offset_t opcodes_offset, const lldb::offset_t opcodes_length, - const uint32_t reg_kind, + const lldb::RegisterKind reg_kind, const Value* initial_value_ptr, Value& result, Error *error_ptr @@ -1345,6 +1372,10 @@ DWARFExpression::Evaluate Value tmp; uint32_t reg_num; + /// Insertion point for evaluating multi-piece expression. + uint64_t op_piece_offset = 0; + Value pieces; // Used for DW_OP_piece + // Make sure all of the data is available in opcodes. if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length)) { @@ -1363,7 +1394,7 @@ DWARFExpression::Evaluate if (log && log->GetVerbose()) { size_t count = stack.size(); - log->Printf("Stack before operation has %zu values:", count); + log->Printf("Stack before operation has %" PRIu64 " values:", (uint64_t)count); for (size_t i=0; i<count; ++i) { StreamString new_value; @@ -1453,14 +1484,11 @@ DWARFExpression::Evaluate if (process) { lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - uint8_t addr_bytes[sizeof(lldb::addr_t)]; - uint32_t addr_size = process->GetAddressByteSize(); Error error; - if (process->ReadMemory(pointer_addr, &addr_bytes, addr_size, error) == addr_size) + lldb::addr_t pointer_value = process->ReadPointerFromMemory(pointer_addr, error); + if (pointer_value != LLDB_INVALID_ADDRESS) { - DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), process->GetByteOrder(), addr_size); - lldb::offset_t addr_data_offset = 0; - stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset); + stack.back().GetScalar() = pointer_value; stack.back().ClearContext(); } else @@ -2574,45 +2602,134 @@ DWARFExpression::Evaluate // variable a particular DWARF expression refers to. //---------------------------------------------------------------------- case DW_OP_piece: - if (stack.size() < 1) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_piece."); - return false; - } - else { const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); - switch (stack.back().GetValueType()) + + if (piece_byte_size > 0) { - case Value::eValueTypeScalar: - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: + Value curr_piece; + + if (stack.empty()) + { + // In a multi-piece expression, this means that the current piece is not available. + // Fill with zeros for now by resizing the data and appending it + curr_piece.ResizeData(piece_byte_size); + ::memset (curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); + pieces.AppendDataToHostBuffer(curr_piece); + } + else + { + Error error; + // Extract the current piece into "curr_piece" + Value curr_piece_source_value(stack.back()); + stack.pop_back(); + + const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType(); + switch (curr_piece_source_value_type) { - uint32_t bit_size = piece_byte_size * 8; - uint32_t bit_offset = 0; - if (!stack.back().GetScalar().ExtractBitfield (bit_size, bit_offset)) + case Value::eValueTypeLoadAddress: + if (process) + { + if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) + { + lldb::addr_t load_addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (process->ReadMemory(load_addr, curr_piece.GetBuffer().GetBytes(), piece_byte_size, error) != piece_byte_size) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from 0x%" PRIx64, + piece_byte_size, + load_addr); + return false; + } + } + else + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("failed to resize the piece memory buffer for DW_OP_piece(%" PRIu64 ")", piece_byte_size); + return false; + } + } + break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeHostAddress: + if (error_ptr) + { + lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from %s address 0x%" PRIx64, + piece_byte_size, + curr_piece_source_value.GetValueType() == Value::eValueTypeFileAddress ? "file" : "host", + addr); + } + return false; + + case Value::eValueTypeScalar: + { + uint32_t bit_size = piece_byte_size * 8; + uint32_t bit_offset = 0; + if (!curr_piece_source_value.GetScalar().ExtractBitfield (bit_size, bit_offset)) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetScalar().GetByteSize()); + return false; + } + curr_piece = curr_piece_source_value; + } + break; + + case Value::eValueTypeVector: + { + if (curr_piece_source_value.GetVector().length >= piece_byte_size) + curr_piece_source_value.GetVector().length = piece_byte_size; + else + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetVector().length); + return false; + } + } + break; + + default: + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("unhandled value type for DW_OP_piece(%" PRIu64 ")", piece_byte_size); + return false; + + } + + // Check if this is the first piece? + if (op_piece_offset == 0) + { + // This is the first piece, we should push it back onto the stack so subsequent + // pieces will be able to access this piece and add to it + if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)stack.back().GetScalar().GetByteSize()); + error_ptr->SetErrorString("failed to append piece data"); return false; } } - break; - - case Value::eValueTypeVector: + else if (!stack.empty()) { - if (stack.back().GetVector().length >= piece_byte_size) - stack.back().GetVector().length = piece_byte_size; - else + // If this is the second or later piece there should be a value on the stack + if (pieces.GetBuffer().GetByteSize() != op_piece_offset) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)stack.back().GetVector().length); + error_ptr->SetErrorStringWithFormat ("DW_OP_piece for offset %" PRIu64 " but top of stack is of size %" PRIu64, + op_piece_offset, + pieces.GetBuffer().GetByteSize()); + return false; + } + + if (pieces.AppendDataToHostBuffer(curr_piece) == 0) + { + if (error_ptr) + error_ptr->SetErrorString("failed to append piece data"); return false; } } - break; + op_piece_offset += piece_byte_size; + } } } break; @@ -2631,9 +2748,6 @@ DWARFExpression::Evaluate switch (stack.back().GetValueType()) { case Value::eValueTypeScalar: - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: { if (!stack.back().GetScalar().ExtractBitfield (piece_bit_size, piece_bit_offset)) { @@ -2646,11 +2760,22 @@ DWARFExpression::Evaluate } } break; - + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + if (error_ptr) + { + error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from an addresss value.", + piece_bit_size, + piece_bit_offset); + } + return false; + case Value::eValueTypeVector: if (error_ptr) { - error_ptr->SetErrorStringWithFormat ("unable to extract %" PRIu64 " bit value with %" PRIu64 " bit offset from a vector value.", + error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from a vector value.", piece_bit_size, piece_bit_offset); } @@ -2784,7 +2909,7 @@ DWARFExpression::Evaluate return false; } - if (!exe_ctx || !opcode_ctx) + if (!exe_ctx || !module_sp) { if (error_ptr) error_ptr->SetErrorString("No context to evaluate TLS within."); @@ -2800,7 +2925,7 @@ DWARFExpression::Evaluate } // Lookup the TLS block address for this thread and module. - addr_t tls_addr = thread->GetThreadLocalData (opcode_ctx); + addr_t tls_addr = thread->GetThreadLocalData (module_sp); if (tls_addr == LLDB_INVALID_ADDRESS) { @@ -2825,24 +2950,34 @@ DWARFExpression::Evaluate if (stack.empty()) { - if (error_ptr) - error_ptr->SetErrorString ("Stack empty after evaluation."); - return false; + // Nothing on the stack, check if we created a piece value from DW_OP_piece or DW_OP_bit_piece opcodes + if (pieces.GetBuffer().GetByteSize()) + { + result = pieces; + } + else + { + if (error_ptr) + error_ptr->SetErrorString ("Stack empty after evaluation."); + return false; + } } - else if (log && log->GetVerbose()) + else { - size_t count = stack.size(); - log->Printf("Stack after operation has %zu values:", count); - for (size_t i=0; i<count; ++i) + if (log && log->GetVerbose()) { - StreamString new_value; - new_value.Printf("[%" PRIu64 "]", (uint64_t)i); - stack[i].Dump(&new_value); - log->Printf(" %s", new_value.GetData()); + size_t count = stack.size(); + log->Printf("Stack after operation has %" PRIu64 " values:", (uint64_t)count); + for (size_t i=0; i<count; ++i) + { + StreamString new_value; + new_value.Printf("[%" PRIu64 "]", (uint64_t)i); + stack[i].Dump(&new_value); + log->Printf(" %s", new_value.GetData()); + } } + result = stack.back(); } - - result = stack.back(); return true; // Return true on success } diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp index aef3b9e..080562e 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp @@ -10,6 +10,9 @@ #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Core/StreamString.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Target.h" using namespace lldb_private; @@ -25,25 +28,45 @@ ExpressionSourceCode::g_expression_prefix = R"( #define nil (__null) #define YES ((BOOL)1) #define NO ((BOOL)0) -typedef signed char BOOL; -typedef signed __INT8_TYPE__ int8_t; -typedef unsigned __INT8_TYPE__ uint8_t; -typedef signed __INT16_TYPE__ int16_t; -typedef unsigned __INT16_TYPE__ uint16_t; -typedef signed __INT32_TYPE__ int32_t; -typedef unsigned __INT32_TYPE__ uint32_t; -typedef signed __INT64_TYPE__ int64_t; -typedef unsigned __INT64_TYPE__ uint64_t; -typedef signed __INTPTR_TYPE__ intptr_t; -typedef unsigned __INTPTR_TYPE__ uintptr_t; +typedef __INT8_TYPE__ int8_t; +typedef __UINT8_TYPE__ uint8_t; +typedef __INT16_TYPE__ int16_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __INT32_TYPE__ int32_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __INT64_TYPE__ int64_t; +typedef __UINT64_TYPE__ uint64_t; +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef unsigned short unichar; )"; -bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method) const +bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const { + const char *target_specific_defines = "typedef signed char BOOL;\n"; + static ConstString g_platform_ios_simulator ("PlatformiOSSimulator"); + + if (Target *target = exe_ctx.GetTargetPtr()) + { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) + { + target_specific_defines = "typedef bool BOOL;\n"; + } + if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) + { + if (lldb::PlatformSP platform_sp = target->GetPlatform()) + { + if (platform_sp->GetPluginName() == g_platform_ios_simulator) + { + target_specific_defines = "typedef bool BOOL;\n"; + } + } + } + } + if (m_wrap) { switch (wrapping_language) @@ -65,12 +88,14 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi case lldb::eLanguageTypeC: wrap_stream.Printf("%s \n" "%s \n" + "%s \n" "void \n" "%s(void *$__lldb_arg) \n" "{ \n" " %s; \n" "} \n", g_expression_prefix, + target_specific_defines, m_prefix.c_str(), m_name.c_str(), m_body.c_str()); @@ -78,12 +103,14 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi case lldb::eLanguageTypeC_plus_plus: wrap_stream.Printf("%s \n" "%s \n" + "%s \n" "void \n" "$__lldb_class::%s(void *$__lldb_arg) %s\n" "{ \n" " %s; \n" "} \n", g_expression_prefix, + target_specific_defines, m_prefix.c_str(), m_name.c_str(), (const_object ? "const" : ""), @@ -94,6 +121,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi { wrap_stream.Printf("%s \n" "%s \n" + "%s \n" "@interface $__lldb_objc_class ($__lldb_category) \n" "+(void)%s:(void *)$__lldb_arg; \n" "@end \n" @@ -104,6 +132,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi "} \n" "@end \n", g_expression_prefix, + target_specific_defines, m_prefix.c_str(), m_name.c_str(), m_name.c_str(), @@ -113,6 +142,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi { wrap_stream.Printf("%s \n" "%s \n" + "%s \n" "@interface $__lldb_objc_class ($__lldb_category) \n" "-(void)%s:(void *)$__lldb_arg; \n" "@end \n" @@ -123,6 +153,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi "} \n" "@end \n", g_expression_prefix, + target_specific_defines, m_prefix.c_str(), m_name.c_str(), m_name.c_str(), diff --git a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp index a75a0fc..aa5d28b 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp @@ -33,7 +33,7 @@ static char ID; #define VALID_POINTER_CHECK_NAME "$__lldb_valid_pointer_check" #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check" -static const char g_valid_pointer_check_text[] = +static const char g_valid_pointer_check_text[] = "extern \"C\" void\n" "$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n" "{\n" @@ -56,22 +56,22 @@ DynamicCheckerFunctions::Install(Stream &error_stream, VALID_POINTER_CHECK_NAME)); if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) return false; - + Process *process = exe_ctx.GetProcessPtr(); if (process) { ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime(); - + if (objc_language_runtime) { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); - + if (!m_objc_object_check->Install(error_stream, exe_ctx)) return false; } } - + return true; } @@ -94,7 +94,7 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa } -static std::string +static std::string PrintValue(llvm::Value *V, bool truncate = false) { std::string s; @@ -128,10 +128,10 @@ PrintValue(llvm::Value *V, bool truncate = false) /// /// - InspectInstruction [default: does nothing] /// -/// - InspectBasicBlock [default: iterates through the instructions in a +/// - InspectBasicBlock [default: iterates through the instructions in a /// basic block calling InspectInstruction] /// -/// - InspectFunction [default: iterates through the basic blocks in a +/// - InspectFunction [default: iterates through the basic blocks in a /// function calling InspectBasicBlock] //---------------------------------------------------------------------- class Instrumenter { @@ -150,7 +150,7 @@ public: m_intptr_ty(NULL) { } - + virtual~Instrumenter () { } @@ -168,7 +168,7 @@ public: { return InspectFunction(function); } - + //------------------------------------------------------------------ /// Instrument all the instructions found by Inspect() /// @@ -184,7 +184,7 @@ public: if (!InstrumentInstruction(*ii)) return false; } - + return true; } protected: @@ -192,13 +192,13 @@ protected: /// Add instrumentation to a single instruction /// /// @param[in] inst - /// The instruction to be instrumented. + /// The instruction to be instrumented. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0; - + //------------------------------------------------------------------ /// Register a single instruction to be instrumented /// @@ -209,7 +209,7 @@ protected: { m_to_instrument.push_back(&i); } - + //------------------------------------------------------------------ /// Determine whether a single instruction is interesting to /// instrument, and, if so, call RegisterInstruction @@ -224,7 +224,7 @@ protected: { return true; } - + //------------------------------------------------------------------ /// Scan a basic block to see if any instructions are interesting /// @@ -243,15 +243,15 @@ protected: if (!InspectInstruction(*ii)) return false; } - + return true; } - + //------------------------------------------------------------------ /// Scan a function to see if any instructions are interesting /// /// @param[in] f - /// The function to be inspected. + /// The function to be inspected. /// /// @return /// False if there was an error scanning; true otherwise. @@ -265,12 +265,12 @@ protected: if (!InspectBasicBlock(*bbi)) return false; } - + return true; } - + //------------------------------------------------------------------ - /// Build a function pointer for a function with signature + /// Build a function pointer for a function with signature /// void (*)(uint8_t*) with a given address /// /// @param[in] start_address @@ -282,19 +282,19 @@ protected: llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) { llvm::Type *param_array[1]; - + param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy()); - + ArrayRef<llvm::Type*> params(param_array, 1); - + FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false); return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); } - + //------------------------------------------------------------------ - /// Build a function pointer for a function with signature + /// Build a function pointer for a function with signature /// void (*)(uint8_t*, uint8_t*) with a given address /// /// @param[in] start_address @@ -306,41 +306,41 @@ protected: llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) { llvm::Type *param_array[2]; - + param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy()); param_array[1] = const_cast<llvm::PointerType*>(GetI8PtrTy()); - + ArrayRef<llvm::Type*> params(param_array, 2); - + FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false); return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); } - + PointerType *GetI8PtrTy() { if (!m_i8ptr_ty) m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); - + return m_i8ptr_ty; } - + IntegerType *GetIntptrTy() { if (!m_intptr_ty) { llvm::DataLayout data_layout(&m_module); - + m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), data_layout.getPointerSizeInBits()); } - + return m_intptr_ty; } - + typedef std::vector <llvm::Instruction *> InstVector; typedef InstVector::iterator InstIterator; - + 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 @@ -358,7 +358,7 @@ public: m_valid_pointer_check_func(NULL) { } - + virtual ~ValidPointerChecker () { } @@ -368,53 +368,53 @@ private: Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) - log->Printf("Instrumenting load/store instruction: %s\n", + log->Printf("Instrumenting load/store instruction: %s\n", PrintValue(inst).c_str()); - + 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; - + if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst)) dereferenced_ptr = li->getPointerOperand(); else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst)) dereferenced_ptr = si->getPointerOperand(); else return false; - + // Insert an instruction to cast the loaded value to int8_t* - + BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst); - + // Insert an instruction to call the helper with the result - + llvm::Value *arg_array[1]; - + arg_array[0] = bit_cast; - + llvm::ArrayRef<llvm::Value *> args(arg_array, 1); - - CallInst::Create(m_valid_pointer_check_func, + + CallInst::Create(m_valid_pointer_check_func, args, "", inst); - + return true; } - + bool InspectInstruction(llvm::Instruction &i) { if (dyn_cast<llvm::LoadInst> (&i) || dyn_cast<llvm::StoreInst> (&i)) RegisterInstruction(i); - + return true; } - + llvm::Value *m_valid_pointer_check_func; }; @@ -427,12 +427,12 @@ public: m_objc_object_check_func(NULL) { } - + virtual ~ObjcObjectChecker () { } - + enum msgSend_type { eMsgSend = 0, @@ -441,25 +441,25 @@ public: eMsgSend_fpret, eMsgSend_stret }; - + std::map <llvm::Instruction *, msgSend_type> msgSend_types; private: bool InstrumentInstruction(llvm::Instruction *inst) { 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 - + if (!m_objc_object_check_func) m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress()); - + // id objc_msgSend(id theReceiver, SEL theSelector, ...) - + llvm::Value *target_object; llvm::Value *selector; - + switch (msgSend_types[inst]) { case eMsgSend: @@ -475,119 +475,124 @@ private: case eMsgSendSuper_stret: return true; } - + // These objects should always be valid according to Sean Calannan assert (target_object); assert (selector); // Insert an instruction to cast the receiver id to int8_t* - + BitCastInst *bit_cast = new BitCastInst(target_object, GetI8PtrTy(), "", inst); - + // Insert an instruction to call the helper with the result - + llvm::Value *arg_array[2]; - + arg_array[0] = bit_cast; arg_array[1] = selector; - + ArrayRef<llvm::Value*> args(arg_array, 2); - - CallInst::Create(m_objc_object_check_func, + + CallInst::Create(m_objc_object_check_func, args, "", inst); - + return true; } - + bool InspectInstruction(llvm::Instruction &i) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); CallInst *call_inst = dyn_cast<CallInst>(&i); - + if (call_inst) { // This metadata is set by IRForTarget::MaybeHandleCall(). - + MDNode *metadata = call_inst->getMetadata("lldb.call.realName"); - + if (!metadata) return true; - + if (metadata->getNumOperands() != 1) { if (log) - log->Printf("Function call metadata has %d operands for [%p] %s", metadata->getNumOperands(), call_inst, PrintValue(call_inst).c_str()); + log->Printf("Function call metadata has %d operands for [%p] %s", + metadata->getNumOperands(), + static_cast<void*>(call_inst), + PrintValue(call_inst).c_str()); return false; } - + MDString *real_name = dyn_cast<MDString>(metadata->getOperand(0)); - + if (!real_name) { if (log) - log->Printf("Function call metadata is not an MDString for [%p] %s", call_inst, PrintValue(call_inst).c_str()); + log->Printf("Function call metadata is not an MDString for [%p] %s", + static_cast<void*>(call_inst), + PrintValue(call_inst).c_str()); return false; } std::string name_str = real_name->getString(); const char* name_cstr = name_str.c_str(); - + if (log) log->Printf("Found call to %s: %s\n", name_cstr, PrintValue(call_inst).c_str()); - + if (name_str.find("objc_msgSend") == std::string::npos) return true; - + if (!strcmp(name_cstr, "objc_msgSend")) { RegisterInstruction(i); msgSend_types[&i] = eMsgSend; return true; } - + if (!strcmp(name_cstr, "objc_msgSend_stret")) { RegisterInstruction(i); msgSend_types[&i] = eMsgSend_stret; return true; } - + if (!strcmp(name_cstr, "objc_msgSend_fpret")) { RegisterInstruction(i); msgSend_types[&i] = eMsgSend_fpret; return true; } - + if (!strcmp(name_cstr, "objc_msgSendSuper")) { RegisterInstruction(i); msgSend_types[&i] = eMsgSendSuper; return true; } - + if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) { RegisterInstruction(i); msgSend_types[&i] = eMsgSendSuper_stret; return true; } - + if (log) log->Printf("Function name '%s' contains 'objc_msgSend' but is not handled", name_str.c_str()); - + return true; } - + return true; } - + llvm::Value *m_objc_object_check_func; }; @@ -607,52 +612,52 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str())); - + if (!function) { if (log) log->Printf("Couldn't find %s() in the module", m_func_name.c_str()); - + return false; } if (m_checker_functions.m_valid_pointer_check.get()) { ValidPointerChecker vpc(M, m_checker_functions); - + if (!vpc.Inspect(*function)) return false; - + if (!vpc.Instrument()) return false; } - + if (m_checker_functions.m_objc_object_check.get()) { ObjcObjectChecker ooc(M, m_checker_functions); - + if (!ooc.Inspect(*function)) return false; - + if (!ooc.Instrument()) return false; } - + if (log && log->GetVerbose()) { std::string s; raw_string_ostream oss(s); - + M.print(oss, NULL); - + oss.flush(); - + log->Printf ("Module after dynamic checks: \n%s", s.c_str()); } - - return true; + + return true; } void diff --git a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp index 17bd03a..090f88f 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp @@ -7,18 +7,16 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" -// Project includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" @@ -46,39 +44,39 @@ lldb::addr_t IRExecutionUnit::WriteNow (const uint8_t *bytes, size_t size, Error &error) -{ +{ lldb::addr_t allocation_process_addr = Malloc (size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable, eAllocationPolicyMirror, error); - + if (!error.Success()) return LLDB_INVALID_ADDRESS; - + WriteMemory(allocation_process_addr, bytes, size, error); - + if (!error.Success()) { Error err; Free (allocation_process_addr, err); - + return LLDB_INVALID_ADDRESS; } - + if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { DataBufferHeap my_buffer(size, 0); Error err; ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err); - + if (err.Success()) { DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8); } } - + return allocation_process_addr; } @@ -87,9 +85,9 @@ IRExecutionUnit::FreeNow (lldb::addr_t allocation) { if (allocation == LLDB_INVALID_ADDRESS) return; - + Error err; - + Free(allocation, err); } @@ -98,16 +96,16 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, lldb::ProcessSP &process_wp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + ExecutionContext exe_ctx(process_wp); - + Error ret; - + ret.Clear(); - + lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; - + for (JittedFunction &function : m_jitted_functions) { if (strstr(function.m_name.c_str(), m_name.AsCString())) @@ -116,31 +114,31 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, func_remote_addr = function.m_remote_addr; } } - + if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString()); return ret; } - + if (log) log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr); - + std::pair <lldb::addr_t, lldb::addr_t> func_range; - + func_range = GetRemoteRangeForLocal(func_local_addr); - + if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString()); return ret; } - + if (log) log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second); - + Target *target = exe_ctx.GetTargetPtr(); if (!target) { @@ -148,44 +146,44 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, ret.SetErrorString("Couldn't find the target"); return ret; } - + lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); - + Process *process = exe_ctx.GetProcessPtr(); Error err; process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); - + if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } - + ArchSpec arch(target->GetArchitecture()); - + const char *plugin_name = NULL; const char *flavor_string = NULL; lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name); - + if (!disassembler_sp) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } - + if (!process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } - + DataExtractor extractor(buffer_sp, process->GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); - + if (log) { log->Printf("Function data has contents:"); @@ -196,12 +194,12 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, 16, DataExtractor::TypeUInt8); } - + disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false); - + InstructionList &instruction_list = disassembler_sp->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); - + for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) @@ -223,7 +221,7 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie) { Error *err = static_cast<Error*>(Context); - + if (err && err->Success()) { err->SetErrorToGenericError(); @@ -237,52 +235,52 @@ IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_end) { lldb::ProcessSP process_sp(GetProcessWP().lock()); - + static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive); - + func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; - + if (!process_sp) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid"); return; } - + if (m_did_jit) { func_addr = m_function_load_addr; func_end = m_function_end_load_addr; - + return; }; - + Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex); - + m_did_jit = true; - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + std::string error_string; - + if (log) { std::string s; llvm::raw_string_ostream oss(s); - + m_module->print(oss, NULL); - + oss.flush(); - + log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } - + llvm::Triple triple(m_module->getTargetTriple()); llvm::Function *function = m_module->getFunction (m_name.AsCString()); llvm::Reloc::Model relocModel; llvm::CodeModel::Model codeModel; - + if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; @@ -294,11 +292,11 @@ IRExecutionUnit::GetRunnableInfo(Error &error, relocModel = llvm::Reloc::PIC_; codeModel = llvm::CodeModel::Small; } - + m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); - - llvm::EngineBuilder builder(m_module_ap.get()); - + + llvm::EngineBuilder builder(std::move(m_module_ap)); + builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(relocModel) @@ -307,68 +305,67 @@ IRExecutionUnit::GetRunnableInfo(Error &error, .setAllocateGVsWithCode(true) .setCodeModel(codeModel) .setUseMCJIT(true); - + llvm::StringRef mArch; llvm::StringRef mCPU; llvm::SmallVector<std::string, 0> mAttrs; - + for (std::string &feature : m_cpu_features) mAttrs.push_back(feature); - + llvm::TargetMachine *target_machine = builder.selectTarget(triple, mArch, mCPU, mAttrs); - + m_execution_engine_ap.reset(builder.create(target_machine)); - + if (!m_execution_engine_ap.get()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return; } - else - { - m_module_ap.release(); // ownership was transferred - } - + + // Make sure we see all sections, including ones that don't have relocations... + m_execution_engine_ap->setProcessAllSections(true); + m_execution_engine_ap->DisableLazyCompilation(); - + // We don't actually need the function pointer here, this just forces it to get resolved. - + void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function); - + if (!error.Success()) { // We got an error through our callback! return; } - + if (!function) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString()); return; } - + if (!fun_ptr) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString()); return; } - + m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr)); - + CommitAllocations(process_sp); ReportAllocations(*m_execution_engine_ap); WriteData(process_sp); - + for (JittedFunction &jitted_function : m_jitted_functions) { jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); - + if (!jitted_function.m_name.compare(m_name.AsCString())) { AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr); @@ -376,15 +373,15 @@ IRExecutionUnit::GetRunnableInfo(Error &error, m_function_load_addr = jitted_function.m_remote_addr; } } - + if (log) { log->Printf("Code can be run in the target."); - + StreamString disassembly_stream; - + Error err = DisassembleFunction(disassembly_stream, process_sp); - + if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); @@ -393,18 +390,18 @@ IRExecutionUnit::GetRunnableInfo(Error &error, { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } - + log->Printf("Sections: "); for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { record.dump(log); - + DataBufferHeap my_buffer(record.m_size, 0); Error err; ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err); - + if (err.Success()) { DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); @@ -413,10 +410,10 @@ IRExecutionUnit::GetRunnableInfo(Error &error, } } } - + func_addr = m_function_load_addr; func_end = m_function_end_load_addr; - + return; } @@ -433,6 +430,9 @@ IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) : { } +IRExecutionUnit::MemoryManager::~MemoryManager () +{ +} void IRExecutionUnit::MemoryManager::setMemoryWritable () { @@ -464,15 +464,19 @@ IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F, m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, + GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Stub), StubSize, - Alignment)); + Alignment, + eSectionIDInvalid, + NULL)); if (log) { log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p", - F, StubSize, Alignment, return_value); + static_cast<const void*>(F), StubSize, Alignment, + static_cast<void*>(return_value)); } - + return return_value; } @@ -484,24 +488,136 @@ IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F, m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd); } +lldb::SectionType +IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) +{ + lldb::SectionType sect_type = lldb::eSectionTypeCode; + switch (alloc_kind) + { + case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break; + case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break; + case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break; + case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break; + case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break; + } + + if (!name.empty()) + { + if (name.equals("__text") || name.equals(".text")) + sect_type = lldb::eSectionTypeCode; + else if (name.equals("__data") || name.equals(".data")) + sect_type = lldb::eSectionTypeCode; + else if (name.startswith("__debug_") || name.startswith(".debug_")) + { + const uint32_t name_idx = name[0] == '_' ? 8 : 7; + llvm::StringRef dwarf_name(name.substr(name_idx)); + switch (dwarf_name[0]) + { + case 'a': + if (dwarf_name.equals("abbrev")) + sect_type = lldb::eSectionTypeDWARFDebugAbbrev; + else if (dwarf_name.equals("aranges")) + sect_type = lldb::eSectionTypeDWARFDebugAranges; + break; + + case 'f': + if (dwarf_name.equals("frame")) + sect_type = lldb::eSectionTypeDWARFDebugFrame; + break; + + case 'i': + if (dwarf_name.equals("info")) + sect_type = lldb::eSectionTypeDWARFDebugInfo; + break; + + case 'l': + if (dwarf_name.equals("line")) + sect_type = lldb::eSectionTypeDWARFDebugLine; + else if (dwarf_name.equals("loc")) + sect_type = lldb::eSectionTypeDWARFDebugLoc; + break; + + case 'm': + if (dwarf_name.equals("macinfo")) + sect_type = lldb::eSectionTypeDWARFDebugMacInfo; + break; + + case 'p': + if (dwarf_name.equals("pubnames")) + sect_type = lldb::eSectionTypeDWARFDebugPubNames; + else if (dwarf_name.equals("pubtypes")) + sect_type = lldb::eSectionTypeDWARFDebugPubTypes; + break; + + case 's': + if (dwarf_name.equals("str")) + sect_type = lldb::eSectionTypeDWARFDebugStr; + break; + + case 'r': + if (dwarf_name.equals("ranges")) + sect_type = lldb::eSectionTypeDWARFDebugRanges; + break; + + default: + break; + } + } + else if (name.startswith("__apple_") || name.startswith(".apple_")) + { +#if 0 + const uint32_t name_idx = name[0] == '_' ? 8 : 7; + llvm::StringRef apple_name(name.substr(name_idx)); + switch (apple_name[0]) + { + case 'n': + if (apple_name.equals("names")) + sect_type = lldb::eSectionTypeDWARFAppleNames; + else if (apple_name.equals("namespac") || apple_name.equals("namespaces")) + sect_type = lldb::eSectionTypeDWARFAppleNamespaces; + break; + case 't': + if (apple_name.equals("types")) + sect_type = lldb::eSectionTypeDWARFAppleTypes; + break; + case 'o': + if (apple_name.equals("objc")) + sect_type = lldb::eSectionTypeDWARFAppleObjC; + break; + default: + break; + } +#else + sect_type = lldb::eSectionTypeInvalid; +#endif + } + else if (name.equals("__objc_imageinfo")) + sect_type = lldb::eSectionTypeOther; + } + return sect_type; +} + uint8_t * IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment); - + m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, + GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Bytes), Size, - Alignment)); - + Alignment, + eSectionIDInvalid, + NULL)); + if (log) { log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); } - + return return_value; } @@ -512,21 +628,23 @@ IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size, llvm::StringRef SectionName) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName); - + m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsExecutable, + GetSectionTypeFromSectionName (SectionName, AllocationKind::Code), Size, Alignment, - SectionID)); - + SectionID, + SectionName.str().c_str())); + if (log) { log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); } - + return return_value; } @@ -540,19 +658,21 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly); - + m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, + lldb::ePermissionsReadable | (IsReadOnly ? 0 : lldb::ePermissionsWritable), + GetSectionTypeFromSectionName (SectionName, AllocationKind::Data), Size, Alignment, - SectionID)); + SectionID, + SectionName.str().c_str())); if (log) { log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); } - - return return_value; + + return return_value; } uint8_t * @@ -562,18 +682,21 @@ IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size, Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment); - + m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, lldb::ePermissionsReadable | lldb::ePermissionsWritable, + GetSectionTypeFromSectionName (llvm::StringRef(), AllocationKind::Global), Size, - Alignment)); - + Alignment, + eSectionIDInvalid, + NULL)); + if (log) { log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); } - + return return_value; } @@ -595,9 +718,9 @@ IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) { if (record.m_process_address == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; - + lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address); - + if (log) { log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].", @@ -608,7 +731,7 @@ IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) record.m_process_address, record.m_process_address + record.m_size); } - + return ret; } } @@ -626,11 +749,11 @@ IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address) { if (record.m_process_address == LLDB_INVALID_ADDRESS) return AddrRange(0, 0); - + return AddrRange(record.m_process_address, record.m_size); } } - + return AddrRange (0, 0); } @@ -638,28 +761,50 @@ bool IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) { bool ret = true; - + lldb_private::Error err; - + for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) continue; - - - record.m_process_address = Malloc(record.m_size, - record.m_alignment, - record.m_permissions, - eAllocationPolicyProcessOnly, - err); - + + switch (record.m_sect_type) + { + case lldb::eSectionTypeInvalid: + case lldb::eSectionTypeDWARFDebugAbbrev: + case lldb::eSectionTypeDWARFDebugAranges: + case lldb::eSectionTypeDWARFDebugFrame: + case lldb::eSectionTypeDWARFDebugInfo: + case lldb::eSectionTypeDWARFDebugLine: + case lldb::eSectionTypeDWARFDebugLoc: + case lldb::eSectionTypeDWARFDebugMacInfo: + case lldb::eSectionTypeDWARFDebugPubNames: + case lldb::eSectionTypeDWARFDebugPubTypes: + case lldb::eSectionTypeDWARFDebugRanges: + case lldb::eSectionTypeDWARFDebugStr: + case lldb::eSectionTypeDWARFAppleNames: + case lldb::eSectionTypeDWARFAppleTypes: + case lldb::eSectionTypeDWARFAppleNamespaces: + case lldb::eSectionTypeDWARFAppleObjC: + err.Clear(); + break; + default: + record.m_process_address = Malloc (record.m_size, + record.m_alignment, + record.m_permissions, + eAllocationPolicyProcessOnly, + err); + break; + } + if (!err.Success()) { ret = false; break; } } - + if (!ret) { for (AllocationRecord &record : m_records) @@ -671,7 +816,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) } } } - + return ret; } @@ -682,13 +827,13 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) { if (record.m_process_address == LLDB_INVALID_ADDRESS) continue; - + if (record.m_section_id == eSectionIDInvalid) continue; - + engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address); } - + // Trigger re-application of relocations. engine.finalizeObject(); } @@ -696,25 +841,26 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) bool IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp) { + bool wrote_something = false; for (AllocationRecord &record : m_records) { - if (record.m_process_address == LLDB_INVALID_ADDRESS) - return false; - - lldb_private::Error err; - - WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err); + if (record.m_process_address != LLDB_INVALID_ADDRESS) + { + lldb_private::Error err; + WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err); + if (err.Success()) + wrote_something = true; + } } - - return true; + return wrote_something; } -void +void IRExecutionUnit::AllocationRecord::dump (Log *log) { if (!log) return; - + log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)", (unsigned long long)m_host_address, (unsigned long long)m_size, @@ -722,3 +868,80 @@ IRExecutionUnit::AllocationRecord::dump (Log *log) (unsigned)m_alignment, (unsigned)m_section_id); } + + +lldb::ByteOrder +IRExecutionUnit::GetByteOrder () const +{ + ExecutionContext exe_ctx (GetBestExecutionContextScope()); + return exe_ctx.GetByteOrder(); +} + +uint32_t +IRExecutionUnit::GetAddressByteSize () const +{ + ExecutionContext exe_ctx (GetBestExecutionContextScope()); + return exe_ctx.GetAddressByteSize(); +} + +void +IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file, + lldb_private::Symtab &symtab) +{ + // No symbols yet... +} + + +void +IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file, + lldb_private::SectionList §ion_list) +{ + for (AllocationRecord &record : m_records) + { + if (record.m_size > 0) + { + lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(), + obj_file, + record.m_section_id, + ConstString(record.m_name), + record.m_sect_type, + record.m_process_address, + record.m_size, + record.m_host_address, // file_offset (which is the host address for the data) + record.m_size, // file_size + 0, + record.m_permissions)); // flags + section_list.AddSection (section_sp); + } + } +} + +bool +IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch) +{ + ExecutionContext exe_ctx (GetBestExecutionContextScope()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) + arch = target->GetArchitecture(); + else + arch.Clear(); + return arch.IsValid(); +} + +lldb::ModuleSP +IRExecutionUnit::GetJITModule () +{ + ExecutionContext exe_ctx (GetBestExecutionContextScope()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) + { + lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this())); + if (jit_module_sp) + { + bool changed = false; + jit_module_sp->SetLoadAddress(*target, 0, true, changed); + } + return jit_module_sp; + } + return lldb::ModuleSP(); +} diff --git a/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp b/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp index a998896..b91e1b4 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp @@ -59,7 +59,7 @@ IRForTarget::FunctionValueCache::~FunctionValueCache() } llvm::Value *IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) -{ +{ if (!m_values.count(function)) { llvm::Value *ret = m_maker(function); @@ -72,13 +72,13 @@ llvm::Value *IRForTarget::FunctionValueCache::GetValue(llvm::Function *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; @@ -88,7 +88,7 @@ static llvm::Value *FindEntryInstruction (llvm::Function *function) { if (function->empty()) return NULL; - + return function->getEntryBlock().getFirstNonPHIOrDbg(); } @@ -116,7 +116,7 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, /* Handy utility functions used at several places in the code */ -static std::string +static std::string PrintValue(const Value *value, bool truncate = false) { std::string s; @@ -151,38 +151,38 @@ bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) { llvm_function.setLinkage(GlobalValue::ExternalLinkage); - + std::string name = llvm_function.getName().str(); - + return true; } -bool +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 false; + + return LookupResult::Fail; case Intrinsic::memcpy: { static lldb_private::ConstString g_memcpy_str ("memcpy"); @@ -195,8 +195,11 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, 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()); } @@ -204,14 +207,14 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, { 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)) + if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) { lldb_private::ConstString altnernate_name; bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); @@ -228,7 +231,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, found_it = m_decl_map->GetFunctionAddress (altnernate_name, fun_addr); } } - + if (!found_it) { lldb_private::Mangled mangled_name(name); @@ -243,7 +246,7 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, log->Printf("Function \"%s\" had no address", mangled_name.GetName().GetCString()); } - + if (m_error_stream) { if (alt_mangled_name) @@ -258,28 +261,28 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", mangled_name.GetName().GetCString()); } - return false; + return LookupResult::Fail; } } } - else + 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 false; + + return LookupResult::Fail; } } - + if (log) log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); - - return true; + + return LookupResult::Success; } llvm::Constant * @@ -293,15 +296,11 @@ IRForTarget::BuildFunctionPointer (llvm::Type *type, void IRForTarget::RegisterFunctionMetadata(LLVMContext &context, - llvm::Value *function_ptr, + llvm::Value *function_ptr, const char *name) { - for (Value::use_iterator i = function_ptr->use_begin(), e = function_ptr->use_end(); - i != e; - ++i) + for (llvm::User *user : function_ptr->users()) { - Value *user = *i; - if (Instruction *user_inst = dyn_cast<Instruction>(user)) { MDString* md_name = MDString::get(context, StringRef(name)); @@ -317,62 +316,74 @@ IRForTarget::RegisterFunctionMetadata(LLVMContext &context, } } -bool +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->hasNUses(0)) + + if (fun->use_empty()) continue; // ignore - + uint64_t addr = LLDB_INVALID_ADDRESS; lldb_private::ConstString name; Constant **value_ptr = NULL; - - if (!GetFunctionAddress(fun, - addr, - name, - value_ptr)) + + LookupResult result = GetFunctionAddress(fun, + addr, + name, + value_ptr); + + switch (result) + { + case LookupResult::Fail: return false; // GetFunctionAddress reports its own errors - - 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->use_begin(), e = fun->use_end(); u != e; ++u) { - if (auto call = dyn_cast<CallInst>(*u)) { - call->removeAttribute(AttributeSet::FunctionIndex, builtin); + + 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; } - - fun->replaceAllUsesWith(value); } - + return true; } @@ -381,69 +392,69 @@ 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) { MDNode *metadata_node = named_metadata->getOperand(node_index); - + if (!metadata_node) return NULL; - + if (metadata_node->getNumOperands() != 2) continue; - + if (metadata_node->getOperand(0) != global_val) continue; - + ConstantInt *constant_int = dyn_cast<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 +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)) { @@ -451,7 +462,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) m_result_is_pointer = true; break; } - + if (strstr(value_name, "$__lldb_expr_result") && strncmp(value_name, "_ZGV", 4)) { @@ -460,105 +471,105 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) 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()); } @@ -566,10 +577,10 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) { 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; } } @@ -578,99 +589,99 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), &result_decl->getASTContext()); } - + if (m_result_type.GetBitSize() == 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", + 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()); - + // Construct a new result global and set up its metadata - - GlobalVariable *new_result_global = new GlobalVariable((*m_module), + + 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::Value* values[2]; values[0] = new_result_global; values[1] = new_constant_int; - + ArrayRef<Value*> 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->hasNUses(0)) + + 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()); } @@ -678,76 +689,51 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) { result_global->replaceAllUsesWith(new_result_global); } - + if (!m_decl_map->AddPersistentVariable(result_decl, - m_result_name, + m_result_name, m_result_type, true, m_result_is_pointer)) return false; - + result_global->eraseFromParent(); - - return true; -} -#if 0 -static void DebugUsers(Log *log, Value *value, uint8_t depth) -{ - if (!depth) - return; - - depth--; - - if (log) - log->Printf(" <Begin %d users>", value->getNumUses()); - - for (Value::use_iterator ui = value->use_begin(), ue = value->use_end(); - ui != ue; - ++ui) - { - if (log) - log->Printf(" <Use %p> %s", *ui, PrintValue(*ui).c_str()); - DebugUsers(log, *ui, depth); - } - - if (log) - log->Printf(" <End uses>"); + return true; } -#endif 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 ( @@ -766,66 +752,66 @@ IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, // 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; } @@ -833,57 +819,57 @@ 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 { @@ -892,107 +878,107 @@ IRForTarget::RewriteObjCConstStrings() // 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) @@ -1000,175 +986,175 @@ IRForTarget::RewriteObjCConstStrings() 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("\01L_OBJC_SELECTOR_REFERENCES_")) return false; - + return true; } // This function does not report errors; its callers are responsible. -bool +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** @"\01L_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. - // + // // @"\01L_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, + + 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; } @@ -1178,25 +1164,25 @@ 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) @@ -1205,111 +1191,111 @@ IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) { 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 +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 = dyn_cast<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::Value* values[2]; values[0] = persistent_global; values[1] = constant_int; - + ArrayRef<llvm::Value*> 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 +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")) { @@ -1317,20 +1303,20 @@ IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { 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) @@ -1339,14 +1325,14 @@ IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { 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; } @@ -1355,14 +1341,14 @@ 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)", 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)); @@ -1379,17 +1365,17 @@ IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) { 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; } @@ -1423,52 +1409,52 @@ 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 +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()) @@ -1486,31 +1472,31 @@ IRForTarget::MaybeHandleVariable (Value *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] == '$') @@ -1531,25 +1517,25 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) { value_type = global_variable->getType(); } - + const uint64_t value_size = clang_type.GetByteSize(); - off_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull; - + 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 %" PRId64 "]", - name.c_str(), + 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_size, value_alignment); } - - + + if (named_decl && !m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString (name.c_str()), llvm_value_ptr, - value_size, + value_size, value_alignment)) { if (!global_variable->hasExternalLinkage()) @@ -1564,45 +1550,45 @@ IRForTarget::MaybeHandleVariable (Value *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; } @@ -1610,10 +1596,10 @@ 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) @@ -1621,10 +1607,10 @@ IRForTarget::MaybeHandleCallArguments (CallInst *Old) { 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; } @@ -1634,55 +1620,53 @@ 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_begin() == global_variable->use_end()) + + if (global_variable->use_empty()) return false; - + SmallVector<LoadInst *, 2> load_instructions; - - for (Value::use_iterator i = global_variable->use_begin(), e = global_variable->use_end(); - i != e; - ++i) + + for (llvm::User *u : global_variable->users()) { - if (LoadInst *load_instruction = dyn_cast<LoadInst>(*i)) + 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; } @@ -1690,54 +1674,54 @@ 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(); @@ -1745,14 +1729,14 @@ IRForTarget::ResolveCalls(BasicBlock &basic_block) ++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; } @@ -1760,68 +1744,58 @@ bool IRForTarget::ResolveExternals (Function &llvm_function) { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - for (Module::global_iterator global = m_module->global_begin(), end = m_module->global_end(); - global != end; - ++global) + + for (GlobalVariable &global_var : m_module->globals()) { - if (!global) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: global variable is NULL"); - - return false; - } - - std::string global_name = (*global).getName().str(); - + std::string global_name = global_var.getName().str(); + if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", + log->Printf("Examining %s, DeclForGlobalValue returns %p", global_name.c_str(), - DeclForGlobal(global)); - + static_cast<void*>(DeclForGlobal(&global_var))); + if (global_name.find("OBJC_IVAR") == 0) { - if (!HandleSymbol(global)) + 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)) + 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)) + 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)) + else if (DeclForGlobal(&global_var)) { - if (!MaybeHandleVariable (global)) + 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; } @@ -1829,40 +1803,36 @@ bool IRForTarget::ReplaceStrings () { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + typedef std::map <GlobalVariable *, size_t> OffsetsTy; - + OffsetsTy offsets; - - for (Module::global_iterator gi = m_module->global_begin(), ge = m_module->global_end(); - gi != ge; - ++gi) - { - GlobalVariable *gv = gi; - - if (!gv->hasInitializer()) + + for (GlobalVariable &gv : m_module->globals()) + { + if (!gv.hasInitializer()) continue; - - Constant *gc = gv->getInitializer(); - + + 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 @@ -1871,108 +1841,102 @@ IRForTarget::ReplaceStrings () 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(); - + + 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 (GlobalVariable::use_iterator ui = gv->use_begin(), ue = gv->use_end(); - ui != ue; - ++ui) + + for (llvm::User *u : gv->users()) { if (log) - log->Printf("Found use %s", PrintValue(*ui).c_str()); - - ConstantExpr *const_expr = dyn_cast<ConstantExpr>(*ui); - StoreInst *store_inst = dyn_cast<StoreInst>(*ui); - + 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 +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 (Instruction::op_iterator oi = inst.op_begin(), oe = inst.op_end(); - oi != oe; - ++oi) + + for (Value *operand_val : inst.operand_values()) { - Value *operand_val = oi->get(); - 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); @@ -1980,10 +1944,10 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) } } } - + 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) @@ -1992,17 +1956,17 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) 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; @@ -2015,16 +1979,16 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) ss << " "; } ss.flush(); - - log->Printf("Found ConstantFP with size %zu and raw data %s", operand_data_size, s.c_str()); + + 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) @@ -2036,77 +2000,72 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) { 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); - offset = aligned_offset; - + 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")) return false; - + return true; } -void +void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) { Constant* zero(ConstantInt::get(Type::getInt8Ty(m_module->getContext()), 0, true)); - Value::use_iterator ui; - - for (ui = guard_load->use_begin(); - ui != guard_load->use_end(); - ++ui) + for (llvm::User *u : guard_load->users()) { - if (isa<Constant>(*ui)) + if (isa<Constant>(u)) { // do nothing for the moment } else { - ui->replaceUsesOfWith(guard_load, zero); + u->replaceUsesOfWith(guard_load, zero); } } - + guard_load->eraseFromParent(); } @@ -2117,46 +2076,46 @@ static void ExciseGuardStore(Instruction* guard_store) 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)) + 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; } @@ -2168,27 +2127,23 @@ IRForTarget::UnfoldConstant(Constant *old_constant, { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - Value::use_iterator ui; - 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 (ui = old_constant->use_begin(); - ui != old_constant->use_end(); - ++ui) - users.push_back(*ui); - + 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()) @@ -2198,20 +2153,20 @@ IRForTarget::UnfoldConstant(Constant *old_constant, 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; } @@ -2221,35 +2176,35 @@ IRForTarget::UnfoldConstant(Constant *old_constant, // 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(ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); }); - + if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) return false; } @@ -2277,162 +2232,162 @@ IRForTarget::UnfoldConstant(Constant *old_constant, } } } - + if (!isa<GlobalValue>(old_constant)) { old_constant->destroyConstant(); } - + return true; } -bool +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; - off_t alignment; - + 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; - off_t offset; + 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 %" PRId64, + 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(argument, offset_int, @@ -2445,19 +2400,19 @@ IRForTarget::ReplaceVariables (Function &llvm_function) 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); @@ -2472,15 +2427,15 @@ IRForTarget::ReplaceVariables (Function &llvm_function) 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 %zu]", alignment, size); - + log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); + return true; } @@ -2488,29 +2443,29 @@ 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::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(m_reloc_placeholder, offsets); llvm::Constant *reloc_getbitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); - + return reloc_getbitcast; } -bool +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) @@ -2518,15 +2473,15 @@ IRForTarget::CompleteDataAllocation () 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; @@ -2538,47 +2493,39 @@ 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 (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end(); - gi != ge; - ++gi) + + for (GlobalVariable &global_var : llvm_module.globals()) { - GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi); - - global_var->removeDeadConstantUsers(); - - if (global_var->use_empty()) + global_var.removeDeadConstantUsers(); + + if (global_var.use_empty()) { if (log) log->Printf("Did remove %s", - PrintValue(global_var).c_str()); - global_var->eraseFromParent(); + PrintValue(&global_var).c_str()); + global_var.eraseFromParent(); erased = true; break; } } } - - for (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end(); - gi != ge; - ++gi) + + for (GlobalVariable &global_var : llvm_module.globals()) { - GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi); + GlobalValue::user_iterator ui = global_var.user_begin(); - GlobalValue::use_iterator ui = global_var->use_begin(); - if (log) log->Printf("Couldn't remove %s because of %s", - PrintValue(global_var).c_str(), + PrintValue(&global_var).c_str(), PrintValue(*ui).c_str()); } - + return true; } @@ -2586,46 +2533,46 @@ 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 */, @@ -2639,14 +2586,14 @@ IRForTarget::runOnModule (Module &llvm_module) //////////////////////////////////////////////////////////// // 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; } @@ -2654,25 +2601,25 @@ IRForTarget::runOnModule (Module &llvm_module) { 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) @@ -2681,62 +2628,62 @@ IRForTarget::runOnModule (Module &llvm_module) { 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) @@ -2751,9 +2698,9 @@ IRForTarget::runOnModule (Module &llvm_module) { if (log) log->Printf("RewriteObjCSelectors() failed"); - + // RewriteObjCSelectors() reports its own errors, so we don't do so here - + return false; } } @@ -2764,7 +2711,7 @@ IRForTarget::runOnModule (Module &llvm_module) ++fi) { llvm::Function *function = fi; - + for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); bbi != bbe; ++bbi) @@ -2773,81 +2720,81 @@ IRForTarget::runOnModule (Module &llvm_module) { 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; + + return true; } void diff --git a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp index 71ef8d6..d11bdc1 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" @@ -27,7 +28,7 @@ using namespace llvm; -static std::string +static std::string PrintValue(const Value *value, bool truncate = false) { std::string s; @@ -36,13 +37,13 @@ PrintValue(const Value *value, bool truncate = false) rso.flush(); if (truncate) s.resize(s.length() - 1); - + size_t offset; while ((offset = s.find('\n')) != s.npos) s.erase(offset, 1); while (s[0] == ' ' || s[0] == '\t') s.erase(0, 1); - + return s; } @@ -58,25 +59,48 @@ PrintType(const Type *type, bool truncate = false) return s; } +static bool +CanIgnoreCall (const CallInst *call) +{ + const llvm::Function *called_function = call->getCalledFunction(); + + if (!called_function) + return false; + + if (called_function->isIntrinsic()) + { + switch (called_function->getIntrinsicID()) + { + default: + break; + case llvm::Intrinsic::dbg_declare: + case llvm::Intrinsic::dbg_value: + return true; + } + } + + return false; +} + class InterpreterStackFrame { public: typedef std::map <const Value*, lldb::addr_t> ValueMap; - + ValueMap m_values; DataLayout &m_target_data; lldb_private::IRMemoryMap &m_memory_map; const BasicBlock *m_bb; BasicBlock::const_iterator m_ii; BasicBlock::const_iterator m_ie; - + lldb::addr_t m_frame_process_address; size_t m_frame_size; lldb::addr_t m_stack_pointer; - + lldb::ByteOrder m_byte_order; size_t m_addr_byte_size; - + InterpreterStackFrame (DataLayout &target_data, lldb_private::IRMemoryMap &memory_map, lldb::addr_t stack_frame_bottom, @@ -86,41 +110,41 @@ public: { m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig); m_addr_byte_size = (target_data.getPointerSize(0)); - + m_frame_process_address = stack_frame_bottom; m_frame_size = stack_frame_top - stack_frame_bottom; m_stack_pointer = stack_frame_top; } - + ~InterpreterStackFrame () { } - + void Jump (const BasicBlock *bb) { m_bb = bb; m_ii = m_bb->begin(); m_ie = m_bb->end(); } - + std::string SummarizeValue (const Value *value) { lldb_private::StreamString ss; ss.Printf("%s", PrintValue(value).c_str()); - + ValueMap::iterator i = m_values.find(value); if (i != m_values.end()) { lldb::addr_t addr = i->second; - + ss.Printf(" 0x%llx", (unsigned long long)addr); } - + return ss.GetString(); } - + bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type) { size_t type_size = m_target_data.getTypeStoreSize(type); @@ -142,36 +166,36 @@ public: default: return false; } - + return true; } - + bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module) { const Constant *constant = dyn_cast<Constant>(value); - + if (constant) { APInt value_apint; - + if (!ResolveConstantValue(value_apint, constant)) return false; - + return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType()); } else { lldb::addr_t process_address = ResolveValue(value, module); size_t value_size = m_target_data.getTypeStoreSize(value->getType()); - + lldb_private::DataExtractor value_extractor; lldb_private::Error extract_error; - + m_memory_map.GetMemoryData(value_extractor, process_address, value_size, extract_error); - + if (!extract_error.Success()) return false; - + lldb::offset_t offset = 0; if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8) { @@ -179,38 +203,38 @@ public: return AssignToMatchType(scalar, u64value, value->getType()); } } - + return false; } - + bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module) { lldb::addr_t process_address = ResolveValue (value, module); - + if (process_address == LLDB_INVALID_ADDRESS) return false; - + lldb_private::Scalar cast_scalar; - + if (!AssignToMatchType(cast_scalar, scalar.GetRawBits64(0), value->getType())) return false; - + size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); - + lldb_private::DataBufferHeap buf(value_byte_size, 0); - + lldb_private::Error get_data_error; - + if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error)) return false; - + lldb_private::Error write_error; - + m_memory_map.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); - + return write_error.Success(); } - + bool ResolveConstantValue (APInt &value, const Constant *constant) { switch (constant->getValueID()) @@ -246,27 +270,27 @@ public: { ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); ConstantExpr::const_op_iterator op_end = constant_expr->op_end(); - + Constant *base = dyn_cast<Constant>(*op_cursor); - + if (!base) return false; - + if (!ResolveConstantValue(value, base)) return false; - + op_cursor++; - + if (op_cursor == op_end) return true; // no offset to apply! - + SmallVector <Value *, 8> indices (op_cursor, op_end); - + uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices); - + const bool is_signed = true; value += APInt(value.getBitWidth(), offset, is_signed); - + return true; } } @@ -282,27 +306,27 @@ public: } return false; } - + bool MakeArgument(const Argument *value, uint64_t address) { lldb::addr_t data_address = Malloc(value->getType()); - + if (data_address == LLDB_INVALID_ADDRESS) return false; - + lldb_private::Error write_error; - + m_memory_map.WritePointerToMemory(data_address, address, write_error); - + if (!write_error.Success()) { lldb_private::Error free_error; m_memory_map.Free(data_address, free_error); return false; } - + m_values[value] = data_address; - + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) @@ -311,75 +335,75 @@ public: log->Printf(" Data region : %llx", (unsigned long long)address); log->Printf(" Ref region : %llx", (unsigned long long)data_address); } - + return true; } - + bool ResolveConstant (lldb::addr_t process_address, const Constant *constant) { APInt resolved_value; - + if (!ResolveConstantValue(resolved_value, constant)) return false; - + lldb_private::StreamString buffer (lldb_private::Stream::eBinary, m_memory_map.GetAddressByteSize(), m_memory_map.GetByteOrder()); - + size_t constant_size = m_target_data.getTypeStoreSize(constant->getType()); - + const uint64_t *raw_data = resolved_value.getRawData(); - + buffer.PutRawBytes(raw_data, constant_size, lldb::endian::InlHostByteOrder()); - + lldb_private::Error write_error; - + m_memory_map.WriteMemory(process_address, (const uint8_t*)buffer.GetData(), constant_size, write_error); - + return write_error.Success(); } - + lldb::addr_t Malloc (size_t size, uint8_t byte_alignment) { lldb::addr_t ret = m_stack_pointer; - + ret -= size; ret -= (ret % byte_alignment); - + if (ret < m_frame_process_address) return LLDB_INVALID_ADDRESS; - + m_stack_pointer = ret; return ret; } - + lldb::addr_t MallocPointer () { return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment()); } - + lldb::addr_t Malloc (llvm::Type *type) { lldb_private::Error alloc_error; - + return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type)); } - + std::string PrintData (lldb::addr_t addr, llvm::Type *type) { size_t length = m_target_data.getTypeStoreSize(type); - + lldb_private::DataBufferHeap buf(length, 0); - + lldb_private::Error read_error; - + m_memory_map.ReadMemory(buf.GetBytes(), addr, length, read_error); - + if (!read_error.Success()) return std::string("<couldn't read data>"); - + lldb_private::StreamString ss; - + for (size_t i = 0; i < length; i++) { if ((!(i & 0xf)) && i) @@ -387,21 +411,21 @@ public: else ss.Printf("%02hhx ", buf.GetBytes()[i]); } - + return ss.GetString(); } - + lldb::addr_t ResolveValue (const Value *value, Module &module) { ValueMap::iterator i = m_values.find(value); - + if (i != m_values.end()) return i->second; - + // Fall back and allocate space [allocation type Alloca] - + lldb::addr_t data_address = Malloc(value->getType()); - + if (const Constant *constant = dyn_cast<Constant>(value)) { if (!ResolveConstant (data_address, constant)) @@ -411,7 +435,7 @@ public: return LLDB_INVALID_ADDRESS; } } - + m_values[value] = data_address; return data_address; } @@ -434,9 +458,9 @@ IRInterpreter::CanInterpret (llvm::Module &module, lldb_private::Error &error) { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + bool saw_function_with_body = false; - + for (Module::iterator fi = module.begin(), fe = module.end(); fi != fe; ++fi) @@ -448,7 +472,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, saw_function_with_body = true; } } - + for (Function::iterator bbi = function.begin(), bbe = function.end(); bbi != bbe; ++bbi) @@ -471,26 +495,48 @@ IRInterpreter::CanInterpret (llvm::Module &module, case Instruction::Alloca: case Instruction::BitCast: case Instruction::Br: + break; + case Instruction::Call: + { + CallInst *call_inst = dyn_cast<CallInst>(ii); + + if (!call_inst) + { + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + if (!CanIgnoreCall(call_inst)) + { + if (log) + log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(unsupported_opcode_error); + return false; + } + } + break; case Instruction::GetElementPtr: break; case Instruction::ICmp: { ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii); - + if (!icmp_inst) { error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } - + switch (icmp_inst->getPredicate()) { default: { if (log) log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str()); - + error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -531,14 +577,14 @@ IRInterpreter::CanInterpret (llvm::Module &module, case Instruction::ZExt: break; } - + for (int oi = 0, oe = ii->getNumOperands(); oi != oe; ++oi) { Value *operand = ii->getOperand(oi); Type *operand_type = operand->getType(); - + switch (operand_type->getTypeID()) { default: @@ -553,9 +599,9 @@ IRInterpreter::CanInterpret (llvm::Module &module, } } } - + } - + return true;} bool @@ -568,60 +614,83 @@ IRInterpreter::Interpret (llvm::Module &module, lldb::addr_t stack_frame_top) { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + if (log) { std::string s; raw_string_ostream oss(s); - + module.print(oss, NULL); - + oss.flush(); - + log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str()); } - + DataLayout data_layout(&module); - + InterpreterStackFrame frame(data_layout, memory_map, stack_frame_bottom, stack_frame_top); - + if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) { error.SetErrorString("Couldn't allocate stack frame"); } - + int arg_index = 0; - + for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end(); ai != ae; ++ai, ++arg_index) { - if (args.size() < arg_index) + if (args.size() < static_cast<size_t>(arg_index)) { error.SetErrorString ("Not enough arguments passed in to function"); return false; } - + lldb::addr_t ptr = args[arg_index]; frame.MakeArgument(ai, ptr); } - + uint32_t num_insts = 0; - + frame.Jump(function.begin()); - + while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) { const Instruction *inst = frame.m_ii; - + if (log) log->Printf("Interpreting %s", PrintValue(inst).c_str()); - + switch (inst->getOpcode()) { default: break; + case Instruction::Call: + { + const CallInst *call_inst = dyn_cast<CallInst>(inst); + + if (!call_inst) + { + if (log) + log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + if (!CanIgnoreCall(call_inst)) + { + if (log) + log->Printf("The interpreter shouldn't have accepted %s", PrintValue(call_inst).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + } + break; case Instruction::Add: case Instruction::Sub: case Instruction::Mul: @@ -637,7 +706,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::Xor: { const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst); - + if (!bin_op) { if (log) @@ -646,13 +715,13 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *lhs = inst->getOperand(0); Value *rhs = inst->getOperand(1); - + lldb_private::Scalar L; lldb_private::Scalar R; - + if (!frame.EvaluateValue(L, lhs, module)) { if (log) @@ -661,7 +730,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (!frame.EvaluateValue(R, rhs, module)) { if (log) @@ -670,9 +739,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + lldb_private::Scalar result; - + switch (inst->getOpcode()) { default: @@ -722,9 +791,9 @@ IRInterpreter::Interpret (llvm::Module &module, result = L ^ R; break; } - + frame.AssignValue(inst, result, module); - + if (log) { log->Printf("Interpreted a %s", inst->getOpcodeName()); @@ -737,7 +806,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::Alloca: { const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst); - + if (!alloca_inst) { if (log) @@ -746,7 +815,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + if (alloca_inst->isArrayAllocation()) { if (log) @@ -755,17 +824,17 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(unsupported_opcode_error); return false; } - + // The semantics of Alloca are: // Create a region R of virtual memory of type T, backed by a data buffer // Create a region P of virtual memory of type T*, backed by a data buffer // Write the virtual address of R into P - + Type *T = alloca_inst->getAllocatedType(); Type *Tptr = alloca_inst->getType(); - + lldb::addr_t R = frame.Malloc(T); - + if (R == LLDB_INVALID_ADDRESS) { if (log) @@ -774,9 +843,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_allocation_error); return false; } - + lldb::addr_t P = frame.Malloc(Tptr); - + if (P == LLDB_INVALID_ADDRESS) { if (log) @@ -785,11 +854,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_allocation_error); return false; } - + lldb_private::Error write_error; - + memory_map.WritePointerToMemory(P, R, write_error); - + if (!write_error.Success()) { if (log) @@ -801,9 +870,9 @@ IRInterpreter::Interpret (llvm::Module &module, memory_map.Free(R, free_error); return false; } - + frame.m_values[alloca_inst] = P; - + if (log) { log->Printf("Interpreted an AllocaInst"); @@ -816,7 +885,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::ZExt: { const CastInst *cast_inst = dyn_cast<CastInst>(inst); - + if (!cast_inst) { if (log) @@ -825,11 +894,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *source = cast_inst->getOperand(0); - + lldb_private::Scalar S; - + if (!frame.EvaluateValue(S, source, module)) { if (log) @@ -838,14 +907,14 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + frame.AssignValue(inst, S, module); } break; case Instruction::SExt: { const CastInst *cast_inst = dyn_cast<CastInst>(inst); - + if (!cast_inst) { if (log) @@ -854,11 +923,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *source = cast_inst->getOperand(0); - + lldb_private::Scalar S; - + if (!frame.EvaluateValue(S, source, module)) { if (log) @@ -867,18 +936,18 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + S.MakeSigned(); - + lldb_private::Scalar S_signextend(S.SLongLong()); - + frame.AssignValue(inst, S_signextend, module); } break; case Instruction::Br: { const BranchInst *br_inst = dyn_cast<BranchInst>(inst); - + if (!br_inst) { if (log) @@ -887,13 +956,13 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + if (br_inst->isConditional()) { Value *condition = br_inst->getCondition(); - + lldb_private::Scalar C; - + if (!frame.EvaluateValue(C, condition, module)) { if (log) @@ -902,12 +971,12 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (C.GetRawBits64(0)) frame.Jump(br_inst->getSuccessor(0)); else frame.Jump(br_inst->getSuccessor(1)); - + if (log) { log->Printf("Interpreted a BrInst with a condition"); @@ -917,7 +986,7 @@ IRInterpreter::Interpret (llvm::Module &module, else { frame.Jump(br_inst->getSuccessor(0)); - + if (log) { log->Printf("Interpreted a BrInst with no condition"); @@ -928,7 +997,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::GetElementPtr: { const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst); - + if (!gep_inst) { if (log) @@ -937,12 +1006,12 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + const Value *pointer_operand = gep_inst->getPointerOperand(); Type *pointer_type = pointer_operand->getType(); - + lldb_private::Scalar P; - + if (!frame.EvaluateValue(P, pointer_operand, module)) { if (log) @@ -951,25 +1020,25 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + typedef SmallVector <Value *, 8> IndexVector; typedef IndexVector::iterator IndexIterator; - + SmallVector <Value *, 8> indices (gep_inst->idx_begin(), gep_inst->idx_end()); - + SmallVector <Value *, 8> const_indices; - + for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie; ++ii) { ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii); - + if (!constant_index) { lldb_private::Scalar I; - + if (!frame.EvaluateValue(I, *ii, module)) { if (log) @@ -978,22 +1047,22 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (log) log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS)); - + constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS))); } - + const_indices.push_back(constant_index); } - + uint64_t offset = data_layout.getIndexedOffset(pointer_type, const_indices); - + lldb_private::Scalar Poffset = P + offset; - + frame.AssignValue(inst, Poffset, module); - + if (log) { log->Printf("Interpreted a GetElementPtrInst"); @@ -1005,7 +1074,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::ICmp: { const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst); - + if (!icmp_inst) { if (log) @@ -1014,15 +1083,15 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + CmpInst::Predicate predicate = icmp_inst->getPredicate(); - + Value *lhs = inst->getOperand(0); Value *rhs = inst->getOperand(1); - + lldb_private::Scalar L; lldb_private::Scalar R; - + if (!frame.EvaluateValue(L, lhs, module)) { if (log) @@ -1031,7 +1100,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (!frame.EvaluateValue(R, rhs, module)) { if (log) @@ -1040,9 +1109,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + lldb_private::Scalar result; - + switch (predicate) { default: @@ -1086,9 +1155,9 @@ IRInterpreter::Interpret (llvm::Module &module, result = (L <= R); break; } - + frame.AssignValue(inst, result, module); - + if (log) { log->Printf("Interpreted an ICmpInst"); @@ -1101,7 +1170,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::IntToPtr: { const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst); - + if (!int_to_ptr_inst) { if (log) @@ -1110,11 +1179,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *src_operand = int_to_ptr_inst->getOperand(0); - + lldb_private::Scalar I; - + if (!frame.EvaluateValue(I, src_operand, module)) { if (log) @@ -1123,9 +1192,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + frame.AssignValue(inst, I, module); - + if (log) { log->Printf("Interpreted an IntToPtr"); @@ -1137,7 +1206,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::PtrToInt: { const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst); - + if (!ptr_to_int_inst) { if (log) @@ -1146,11 +1215,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *src_operand = ptr_to_int_inst->getOperand(0); - + lldb_private::Scalar I; - + if (!frame.EvaluateValue(I, src_operand, module)) { if (log) @@ -1159,9 +1228,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + frame.AssignValue(inst, I, module); - + if (log) { log->Printf("Interpreted a PtrToInt"); @@ -1173,7 +1242,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::Trunc: { const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst); - + if (!trunc_inst) { if (log) @@ -1182,11 +1251,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + Value *src_operand = trunc_inst->getOperand(0); - + lldb_private::Scalar I; - + if (!frame.EvaluateValue(I, src_operand, module)) { if (log) @@ -1195,9 +1264,9 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + frame.AssignValue(inst, I, module); - + if (log) { log->Printf("Interpreted a Trunc"); @@ -1209,7 +1278,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::Load: { const LoadInst *load_inst = dyn_cast<LoadInst>(inst); - + if (!load_inst) { if (log) @@ -1218,15 +1287,15 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + // The semantics of Load are: // Create a region D that will contain the loaded data // Resolve the region P containing a pointer // Dereference P to get the region R that the data should be loaded from // Transfer a unit of type type(D) from R to D - + const Value *pointer_operand = load_inst->getPointerOperand(); - + Type *pointer_ty = pointer_operand->getType(); PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); if (!pointer_ptr_ty) @@ -1238,10 +1307,10 @@ IRInterpreter::Interpret (llvm::Module &module, return false; } Type *target_ty = pointer_ptr_ty->getElementType(); - + lldb::addr_t D = frame.ResolveValue(load_inst, module); lldb::addr_t P = frame.ResolveValue(pointer_operand, module); - + if (D == LLDB_INVALID_ADDRESS) { if (log) @@ -1250,7 +1319,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (P == LLDB_INVALID_ADDRESS) { if (log) @@ -1259,11 +1328,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + lldb::addr_t R; lldb_private::Error read_error; memory_map.ReadPointerFromMemory(&R, P, read_error); - + if (!read_error.Success()) { if (log) @@ -1272,10 +1341,10 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_read_error); return false; } - + size_t target_size = data_layout.getTypeStoreSize(target_ty); lldb_private::DataBufferHeap buffer(target_size, 0); - + read_error.Clear(); memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error); if (!read_error.Success()) @@ -1286,7 +1355,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_read_error); return false; } - + lldb_private::Error write_error; memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) @@ -1297,7 +1366,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_read_error); return false; } - + if (log) { log->Printf("Interpreted a LoadInst"); @@ -1314,7 +1383,7 @@ IRInterpreter::Interpret (llvm::Module &module, case Instruction::Store: { const StoreInst *store_inst = dyn_cast<StoreInst>(inst); - + if (!store_inst) { if (log) @@ -1323,25 +1392,25 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(interpreter_internal_error); return false; } - + // The semantics of Store are: // Resolve the region D containing the data to be stored // Resolve the region P containing a pointer // Dereference P to get the region R that the data should be stored in // Transfer a unit of type type(D) from D to R - + const Value *value_operand = store_inst->getValueOperand(); const Value *pointer_operand = store_inst->getPointerOperand(); - + Type *pointer_ty = pointer_operand->getType(); PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); if (!pointer_ptr_ty) return false; Type *target_ty = pointer_ptr_ty->getElementType(); - + lldb::addr_t D = frame.ResolveValue(value_operand, module); lldb::addr_t P = frame.ResolveValue(pointer_operand, module); - + if (D == LLDB_INVALID_ADDRESS) { if (log) @@ -1350,7 +1419,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + if (P == LLDB_INVALID_ADDRESS) { if (log) @@ -1359,11 +1428,11 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(bad_value_error); return false; } - + lldb::addr_t R; lldb_private::Error read_error; memory_map.ReadPointerFromMemory(&R, P, read_error); - + if (!read_error.Success()) { if (log) @@ -1372,10 +1441,10 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_read_error); return false; } - + size_t target_size = data_layout.getTypeStoreSize(target_ty); lldb_private::DataBufferHeap buffer(target_size, 0); - + read_error.Clear(); memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error); if (!read_error.Success()) @@ -1386,7 +1455,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_read_error); return false; } - + lldb_private::Error write_error; memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) @@ -1397,7 +1466,7 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorString(memory_write_error); return false; } - + if (log) { log->Printf("Interpreted a StoreInst"); @@ -1408,16 +1477,16 @@ IRInterpreter::Interpret (llvm::Module &module, } break; } - + ++frame.m_ii; } - + if (num_insts >= 4096) { error.SetErrorToGenericError(); error.SetErrorString(infinite_loop_error); return false; } - + return false; } diff --git a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp index 53f74ae..a4fe7a9 100644 --- a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp @@ -28,11 +28,11 @@ IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) : IRMemoryMap::~IRMemoryMap () { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) { AllocationMap::iterator iter; - + Error err; while ((iter = m_allocations.begin()) != m_allocations.end()) @@ -51,54 +51,32 @@ IRMemoryMap::FindSpace (size_t size) { lldb::TargetSP target_sp = m_target_wp.lock(); lldb::ProcessSP process_sp = m_process_wp.lock(); - + lldb::addr_t ret = LLDB_INVALID_ADDRESS; - + if (size == 0) + return ret; + if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { Error alloc_error; - + ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); - + if (!alloc_error.Success()) return LLDB_INVALID_ADDRESS; else return ret; } - - for (int iterations = 0; iterations < 16; ++iterations) + + ret = 0; + if (!m_allocations.empty()) { - lldb::addr_t candidate = LLDB_INVALID_ADDRESS; - - switch (target_sp->GetArchitecture().GetAddressByteSize()) - { - case 4: - { - uint32_t random_data = rand(); - candidate = random_data; - candidate &= ~0xfffull; - break; - } - case 8: - { - uint32_t random_low = rand(); - uint32_t random_high = rand(); - candidate = random_high; - candidate <<= 32ull; - candidate |= random_low; - candidate &= ~0xfffull; - break; - } - } - - if (IntersectsAllocation(candidate, size)) - continue; - - ret = candidate; - - return ret; + auto back = m_allocations.rbegin(); + lldb::addr_t addr = back->first; + size_t alloc_size = back->second.m_size; + ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096); } - + return ret; } @@ -107,9 +85,9 @@ IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size) { if (addr == LLDB_INVALID_ADDRESS) return m_allocations.end(); - + AllocationMap::iterator iter = m_allocations.lower_bound (addr); - + if (iter == m_allocations.end() || iter->first > addr) { @@ -117,54 +95,69 @@ IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size) return m_allocations.end(); iter--; } - + if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size) return iter; - + return m_allocations.end(); } bool -IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) +IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const { if (addr == LLDB_INVALID_ADDRESS) return false; - - AllocationMap::iterator iter = m_allocations.lower_bound (addr); - - if (iter == m_allocations.end() || - iter->first > addr) - { - if (iter == m_allocations.begin()) - return false; - - iter--; + + AllocationMap::const_iterator iter = m_allocations.lower_bound (addr); + + // Since we only know that the returned interval begins at a location greater than or + // equal to where the given interval begins, it's possible that the given interval + // intersects either the returned interval or the previous interval. Thus, we need to + // check both. Note that we only need to check these two intervals. Since all intervals + // are disjoint it is not possible that an adjacent interval does not intersect, but a + // non-adjacent interval does intersect. + if (iter != m_allocations.end()) { + if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size)) + return true; } - - while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size) - { - if (iter->second.m_process_start + iter->second.m_size > addr) + + if (iter != m_allocations.begin()) { + --iter; + if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size)) return true; - - ++iter; } - + return false; } +bool +IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) { + // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy + // A<B and X<Y are the following: + // A B X Y + // A X B Y (intersects) + // A X Y B (intersects) + // X A B Y (intersects) + // X A Y B (intersects) + // X Y A B + // The first is B <= X, and the last is Y <= A. + // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y) + return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2)); +} + lldb::ByteOrder IRMemoryMap::GetByteOrder() { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) return process_sp->GetByteOrder(); - + lldb::TargetSP target_sp = m_target_wp.lock(); - + if (target_sp) return target_sp->GetArchitecture().GetByteOrder(); - + return lldb::eByteOrderInvalid; } @@ -172,31 +165,31 @@ uint32_t IRMemoryMap::GetAddressByteSize() { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) return process_sp->GetAddressByteSize(); - + lldb::TargetSP target_sp = m_target_wp.lock(); - + if (target_sp) return target_sp->GetArchitecture().GetAddressByteSize(); - + return UINT32_MAX; } ExecutionContextScope * -IRMemoryMap::GetBestExecutionContextScope() +IRMemoryMap::GetBestExecutionContextScope() const { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) return process_sp.get(); - + lldb::TargetSP target_sp = m_target_wp.lock(); - + if (target_sp) return target_sp.get(); - + return NULL; } @@ -234,8 +227,9 @@ 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) { + lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); error.Clear(); - + lldb::ProcessSP process_sp; lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; @@ -247,7 +241,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc allocation_size = alignment; else allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size; - + switch (policy) { default: @@ -265,6 +259,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); + if (log) + 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); @@ -273,6 +269,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc } else { + if (log) + log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__); policy = eAllocationPolicyHostOnly; allocation_address = FindSpace(allocation_size); if (allocation_address == LLDB_INVALID_ADDRESS) @@ -308,8 +306,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc } break; } - - + + lldb::addr_t mask = alignment - 1; aligned_address = (allocation_address + mask) & (~mask); @@ -319,11 +317,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc permissions, alignment, policy); - - if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) + + if (log) { const char * policy_string; - + switch (policy) { default: @@ -339,7 +337,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc policy_string = "eAllocationPolicyMirror"; break; } - + log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64, (uint64_t)allocation_size, (uint64_t)alignment, @@ -347,7 +345,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc policy_string, aligned_address); } - + return aligned_address; } @@ -355,16 +353,16 @@ void IRMemoryMap::Leak (lldb::addr_t process_address, Error &error) { error.Clear(); - + AllocationMap::iterator iter = m_allocations.find(process_address); - + if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't leak: allocation doesn't exist"); return; } - + Allocation &allocation = iter->second; allocation.m_leak = true; @@ -374,18 +372,18 @@ void IRMemoryMap::Free (lldb::addr_t process_address, Error &error) { error.Clear(); - + AllocationMap::iterator iter = m_allocations.find(process_address); - + if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't free: allocation doesn't exist"); return; } - + Allocation &allocation = iter->second; - + switch (allocation.m_policy) { default: @@ -397,7 +395,7 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error) if (process_sp->CanJIT() && process_sp->IsAlive()) process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real } - + break; } case eAllocationPolicyMirror: @@ -408,15 +406,15 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error) process_sp->DeallocateMemory(allocation.m_process_alloc); } } - + if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { + { log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, iter->second.m_process_start, iter->second.m_process_start + iter->second.m_size); } - + m_allocations.erase(iter); } @@ -424,28 +422,28 @@ void IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error) { error.Clear(); - + AllocationMap::iterator iter = FindAllocation(process_address, size); - + if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); return; } - + error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist"); return; } - + Allocation &allocation = iter->second; - + uint64_t offset = process_address - allocation.m_process_start; - + lldb::ProcessSP process_sp; switch (allocation.m_policy) @@ -489,9 +487,9 @@ IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, si } break; } - + if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { + { log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, (uint64_t)bytes, @@ -505,10 +503,10 @@ void IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error) { error.Clear(); - + if (size == UINT32_MAX) size = scalar.GetByteSize(); - + if (size > 0) { uint8_t buf[32]; @@ -535,9 +533,9 @@ void IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error) { error.Clear(); - + Scalar scalar(address); - + WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); } @@ -545,39 +543,46 @@ void IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error) { error.Clear(); - + AllocationMap::iterator iter = FindAllocation(process_address, size); - + if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); - + if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); return; } - + lldb::TargetSP target_sp = m_target_wp.lock(); - + if (target_sp) { Address absolute_address(process_address); target_sp->ReadMemory(absolute_address, false, bytes, size, error); return; } - + error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist"); return; } - + Allocation &allocation = iter->second; - + uint64_t offset = process_address - allocation.m_process_start; - + + if (offset > allocation.m_size) + { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: data is not in the allocation"); + return; + } + lldb::ProcessSP process_sp; - + switch (allocation.m_policy) { default: @@ -591,6 +596,13 @@ IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t si error.SetErrorString("Couldn't read: data buffer is empty"); return; } + if (allocation.m_data.GetByteSize() < offset + size) + { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: not enough underlying data"); + return; + } + ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size); break; case eAllocationPolicyMirror: @@ -622,7 +634,7 @@ IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t si } break; } - + if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", @@ -638,19 +650,19 @@ void IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error) { error.Clear(); - + if (size > 0) { DataBufferHeap buf(size, 0); ReadMemory(buf.GetBytes(), process_address, size, error); - + if (!error.Success()) return; - + DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize()); - + lldb::offset_t offset = 0; - + switch (size) { default: @@ -675,15 +687,15 @@ void IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error) { error.Clear(); - + Scalar pointer_scalar; ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error); - + if (!error.Success()) return; - + *address = pointer_scalar.ULongLong(); - + return; } @@ -691,20 +703,20 @@ void IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error) { error.Clear(); - + if (size > 0) { AllocationMap::iterator iter = FindAllocation(process_address, size); - + if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size); return; } - + Allocation &allocation = iter->second; - + switch (allocation.m_policy) { default: @@ -754,5 +766,3 @@ IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_addre return; } } - - diff --git a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp index 90687c0..b119216 100644 --- a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp @@ -95,7 +95,7 @@ public: } if (log) - log->Printf("Allocated %s (0x%" PRIx64 ") sucessfully", m_persistent_variable_sp->GetName().GetCString(), mem); + 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. @@ -443,10 +443,26 @@ public: return; } + Error valobj_error = valobj_sp->GetError(); + + if (valobj_error.Fail()) + { + err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString()); + return; + } + if (m_is_reference) { DataExtractor valobj_extractor; - valobj_sp->GetData(valobj_extractor); + Error extract_error; + valobj_sp->GetData(valobj_extractor, extract_error); + + if (!extract_error.Success()) + { + err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); + return; + } + lldb::offset_t offset = 0; lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); @@ -478,8 +494,14 @@ public: else { DataExtractor data; - valobj_sp->GetData(data); - + Error extract_error; + valobj_sp->GetData(data, extract_error); + if (!extract_error.Success()) + { + err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); + return; + } + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); @@ -513,6 +535,8 @@ public: 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())); + if (!alloc_error.Success()) { err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); @@ -585,14 +609,28 @@ public: return; } - Error set_error; + bool actually_write = true; - valobj_sp->SetData(data, set_error); + if (m_original_data) + { + if ((data.GetByteSize() == m_original_data->GetByteSize()) && + !memcmp(m_original_data->GetBytes(), data.GetDataStart(), data.GetByteSize())) + { + actually_write = false; + } + } - if (!set_error.Success()) + Error set_error; + + if (actually_write) { - err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); - return; + valobj_sp->SetData(data, set_error); + + if (!set_error.Success()) + { + err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); + return; + } } Error free_error; @@ -605,6 +643,7 @@ public: return; } + m_original_data.reset(); m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } @@ -700,6 +739,7 @@ private: bool m_is_reference; lldb::addr_t m_temporary_allocation; size_t m_temporary_allocation_size; + lldb::DataBufferSP m_original_data; }; uint32_t @@ -1312,43 +1352,44 @@ Materializer::DematerializerSP Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error) { ExecutionContextScope *exe_scope = frame_sp.get(); - + if (!exe_scope) exe_scope = map.GetBestExecutionContextScope(); - + DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); - + if (dematerializer_sp) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't materialize: already materialized"); } - + DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address)); - + if (!exe_scope) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't materialize: target doesn't exist"); } - + for (EntityUP &entity_up : m_entities) { entity_up->Materialize(frame_sp, map, process_address, error); - + if (!error.Success()) return DematerializerSP(); } - + if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address); + log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", + static_cast<void*>(frame_sp.get()), process_address); for (EntityUP &entity_up : m_entities) entity_up->DumpToLog(map, process_address, log); } - + m_dematerializer_wp = ret; - + return ret; } @@ -1360,15 +1401,15 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression lldb::ThreadSP thread_sp = m_thread_wp.lock(); if (thread_sp) frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); - + ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); - + if (!IsValid()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); } - + if (!exe_scope) { error.SetErrorToGenericError(); @@ -1378,11 +1419,12 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression { if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address); + log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", + static_cast<void*>(frame_sp.get()), m_process_address); for (EntityUP &entity_up : m_materializer->m_entities) entity_up->DumpToLog(*m_map, m_process_address, log); } - + for (EntityUP &entity_up : m_materializer->m_entities) { if (entity_up.get() == m_materializer->m_result_entity) @@ -1393,12 +1435,12 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression { entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); } - + if (!error.Success()) break; } } - + Wipe(); } |