diff options
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionDeclMap.h | 26 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 16 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 198 | ||||
-rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 16 |
4 files changed, 228 insertions, 28 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index 9719d55cf42..88bb9d279f8 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -25,6 +25,7 @@ namespace clang { class DeclarationName; class DeclContext; + class QualType; } namespace llvm { @@ -33,6 +34,7 @@ namespace llvm { namespace lldb_private { +class Error; class Function; class NameSearchContext; class Variable; @@ -50,6 +52,8 @@ public: // Interface for IRForTarget bool AddValueToStruct (llvm::Value *value, const clang::NamedDecl *decl, + std::string &name, + void *type, size_t size, off_t alignment); bool DoStructLayout (); @@ -64,6 +68,10 @@ public: // Interface for DwarfExpression Value *GetValueForIndex (uint32_t index); + // Interface for CommandObjectExpression + lldb::addr_t Materialize(ExecutionContext *exe_ctx, + Error &error); + // Interface for ClangASTSource void GetDecls (NameSearchContext &context, const char *name); @@ -72,13 +80,17 @@ private: struct Tuple { const clang::NamedDecl *m_decl; + clang::ASTContext *m_ast_context; + void *m_orig_type; Value *m_value; /* owned by ClangExpressionDeclMap */ }; struct StructMember { - const clang::NamedDecl *m_decl; - llvm::Value *m_value; + const clang::NamedDecl *m_decl; + llvm::Value *m_value; + std::string m_name; + void *m_type; off_t m_offset; size_t m_size; off_t m_alignment; @@ -97,9 +109,17 @@ private: off_t m_struct_alignment; size_t m_struct_size; bool m_struct_laid_out; - + lldb::addr_t m_materialized_location; + void AddOneVariable(NameSearchContext &context, Variable *var); void AddOneFunction(NameSearchContext &context, Function *fun); + + bool MaterializeOneVariable(ExecutionContext &exe_ctx, + const SymbolContext &sym_ctx, + const char *name, + void *type, + clang::ASTContext *ast_context, + lldb::addr_t addr); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 56f97fb4027..e3f2baab51a 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -304,8 +304,22 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream return false; } - log->Printf("Function is at 0x%llx", (uint64_t)function_address); + Error err; + + lldb::addr_t struct_address = expr_decl_map.Materialize(&m_exe_ctx, err); + + if (struct_address == LLDB_INVALID_ADDRESS) + { + error_stream.Printf ("Couldn't materialize struct: %s\n", err.AsCString("unknown error")); + return false; + } + + log->Printf("Function address : 0x%llx", (uint64_t)function_address); + log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); } + + return true; + } else { diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index b83cf4a330e..b0f1cf275e0 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -15,6 +15,7 @@ // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Address.h" +#include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Expression/ClangASTSource.h" @@ -27,19 +28,17 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/ExecutionContext.h" -#define DEBUG_PRINTF(...) \ - if (log) \ - log->Printf(__VA_ARGS__) - using namespace lldb_private; using namespace clang; ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) : m_exe_ctx(exe_ctx), - m_struct_laid_out(false) + m_struct_laid_out(false), + m_materialized_location(0) { if (exe_ctx && exe_ctx->frame) m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything)); @@ -83,6 +82,8 @@ ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index, bool ClangExpressionDeclMap::AddValueToStruct (llvm::Value *value, const clang::NamedDecl *decl, + std::string &name, + void *type, size_t size, off_t alignment) { @@ -102,6 +103,8 @@ ClangExpressionDeclMap::AddValueToStruct (llvm::Value *value, member.m_value = value; member.m_decl = decl; + member.m_name = name; + member.m_type = type; member.m_offset = 0; member.m_size = size; member.m_alignment = alignment; @@ -187,6 +190,136 @@ Value return m_tuples[index].m_value; } +// Interface for CommandObjectExpression +lldb::addr_t +ClangExpressionDeclMap::Materialize (ExecutionContext *exe_ctx, Error &err) +{ + if (!m_struct_laid_out) + { + err.SetErrorString("Structure hasn't been laid out yet"); + return LLDB_INVALID_ADDRESS; + } + + if (m_materialized_location) + { + exe_ctx->process->DeallocateMemory(m_materialized_location); + m_materialized_location = 0; + } + + if (!exe_ctx) + { + err.SetErrorString("Received null execution context"); + return LLDB_INVALID_ADDRESS; + } + + const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything)); + + StructMemberIterator iter; + + lldb::addr_t mem = exe_ctx->process->AllocateMemory(m_struct_alignment + m_struct_size, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + err); + + if (mem == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + m_materialized_location = mem; + + lldb::addr_t aligned_mem = mem; + + if (aligned_mem % m_struct_alignment) + { + aligned_mem += (m_struct_alignment - (aligned_mem % m_struct_alignment)); + } + + for (iter = m_members.begin(); + iter != m_members.end(); + ++iter) + { + uint32_t tuple_index; + + if (!GetIndexForDecl(tuple_index, iter->m_decl)) + continue; + + Tuple &tuple(m_tuples[tuple_index]); + + MaterializeOneVariable(*exe_ctx, sym_ctx, iter->m_name.c_str(), tuple.m_orig_type, tuple.m_ast_context, aligned_mem + iter->m_offset); + } + + return aligned_mem; +} + +bool +ClangExpressionDeclMap::MaterializeOneVariable(ExecutionContext &exe_ctx, + const SymbolContext &sym_ctx, + const char *name, + void *type, + clang::ASTContext *ast_context, + lldb::addr_t addr) +{ + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + Function *function(m_sym_ctx->function); + Block *block(m_sym_ctx->block); + + if (!function || !block) + { + if (log) + log->Printf("function = %p, block = %p", function, block); + return false; + } + + BlockList& blocks(function->GetBlocks(true)); + + lldb::user_id_t current_block_id; + + for (current_block_id = block->GetID(); + current_block_id != Block::InvalidID; + current_block_id = blocks.GetParent(current_block_id)) + { + Block *current_block(blocks.GetBlockByID(current_block_id)); + + lldb::VariableListSP var_list = current_block->GetVariableList(false, true); + + if (!var_list) + continue; + + lldb::VariableSP var = var_list->FindVariable(ConstString(name)); + + if (!var) + continue; + + // var->GetType()->GetClangAST() is the program's AST context and holds + // var->GetType()->GetOpaqueClangQualType(). + + // type is m_type for one of the struct members, which was added by + // AddValueToStruct. That type was extracted from the AST context of + // the compiler in IRForTarget. The original for the type was copied + // out of the program's AST context by AddOneVariable. + + // The key here is: we know when we copied a type, and for what Decl we + // did it. So we need for each struct Tuple to keep the type that we + // found, and which AST context we found it in. Then we can look up + // m_decl in m_tuples. + + if (ast_context == var->GetType()->GetClangAST()) + { + if (!ClangASTContext::AreTypesSame(ast_context, type, var->GetType()->GetOpaqueClangQualType())) + continue; + } + else + { + if (log) + log->PutCString("Skipping a candidate variable because of different AST contexts"); + continue; + } + + + } + + return true; +} + // Interface for ClangASTSource void ClangExpressionDeclMap::GetDecls(NameSearchContext &context, @@ -194,7 +327,8 @@ ClangExpressionDeclMap::GetDecls(NameSearchContext &context, { Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); - DEBUG_PRINTF("Hunting for a definition for %s", name); + if (log) + log->Printf("Hunting for a definition for %s", name); // Back out in all cases where we're not fully initialized if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx) @@ -205,7 +339,8 @@ ClangExpressionDeclMap::GetDecls(NameSearchContext &context, if (!function || !block) { - DEBUG_PRINTF("function = %p, block = %p", function, block); + if (log) + log->Printf("function = %p, block = %p", function, block); return; } @@ -247,7 +382,8 @@ ClangExpressionDeclMap::GetDecls(NameSearchContext &context, if (!compile_unit) { - DEBUG_PRINTF("compile_unit = %p", compile_unit); + if (log) + log->Printf("compile_unit = %p", compile_unit); return; } @@ -276,7 +412,8 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (!var_type) { - DEBUG_PRINTF("Skipped a definition because it has no type"); + if (log) + log->PutCString("Skipped a definition because it has no type"); return; } @@ -284,7 +421,8 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (!var_opaque_type) { - DEBUG_PRINTF("Skipped a definition because it has no Clang type"); + if (log) + log->PutCString("Skipped a definition because it has no Clang type"); return; } @@ -294,7 +432,8 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (!type_list) { - DEBUG_PRINTF("Skipped a definition because the type has no associated type list"); + if (log) + log->PutCString("Skipped a definition because the type has no associated type list"); return; } @@ -302,7 +441,8 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (!exe_ast_ctx) { - DEBUG_PRINTF("There is no AST context for the current execution context"); + if (log) + log->PutCString("There is no AST context for the current execution context"); return; } @@ -312,11 +452,14 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (!var_location_expr.Evaluate(m_exe_ctx, exe_ast_ctx, NULL, *var_location.get(), &err)) { - DEBUG_PRINTF("Error evaluating location: %s", err.AsCString()); + if (log) + log->Printf("Error evaluating location: %s", err.AsCString()); return; } - void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), type_list->GetClangASTContext().getASTContext(), var_opaque_type); + clang::ASTContext *var_ast_context = type_list->GetClangASTContext().getASTContext(); + + void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), var_ast_context, var_opaque_type); if (var_location.get()->GetContextType() == Value::eContextTypeInvalid) var_location.get()->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type); @@ -346,12 +489,15 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, Tuple tuple; - tuple.m_decl = var_decl; - tuple.m_value = var_location.release(); + tuple.m_decl = var_decl; + tuple.m_value = var_location.release(); + tuple.m_orig_type = var_opaque_type; + tuple.m_ast_context = var_ast_context; m_tuples.push_back(tuple); - DEBUG_PRINTF("Found variable"); + if (log) + log->PutCString("Found variable"); } void @@ -364,7 +510,8 @@ ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!fun_type) { - DEBUG_PRINTF("Skipped a function because it has no type"); + if (log) + log->PutCString("Skipped a function because it has no type"); return; } @@ -372,7 +519,8 @@ ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!fun_opaque_type) { - DEBUG_PRINTF("Skipped a function because it has no Clang type"); + if (log) + log->PutCString("Skipped a function because it has no Clang type"); return; } @@ -384,16 +532,20 @@ ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, fun_location->GetScalar() = load_addr; TypeList *type_list = fun_type->GetTypeList(); - void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), type_list->GetClangASTContext().getASTContext(), fun_opaque_type); + clang::ASTContext *fun_ast_context = type_list->GetClangASTContext().getASTContext(); + void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), fun_ast_context, fun_opaque_type); NamedDecl *fun_decl = context.AddFunDecl(copied_type); Tuple tuple; - tuple.m_decl = fun_decl; - tuple.m_value = fun_location.release(); + tuple.m_decl = fun_decl; + tuple.m_value = fun_location.release(); + tuple.m_orig_type = fun_opaque_type; + tuple.m_ast_context = fun_ast_context; m_tuples.push_back(tuple); - DEBUG_PRINTF("Found function"); + if (log) + log->PutCString("Found function"); } diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index fd814fcd7b4..065c760d3f3 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -90,12 +90,26 @@ IRForTarget::MaybeHandleVariable(Module &M, { clang::NamedDecl *named_decl = DeclForGlobalValue(M, global_variable); + std::string name = named_decl->getName().str(); + + void *qual_type = NULL; + + if (clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl)) + qual_type = value_decl->getType().getAsOpaquePtr(); + else + return false; + const llvm::Type *value_type = global_variable->getType(); size_t value_size = m_target_data->getTypeStoreSize(value_type); off_t value_alignment = m_target_data->getPrefTypeAlignment(value_type); - if (named_decl && !DM->AddValueToStruct(V, named_decl, value_size, value_alignment)) + if (named_decl && !DM->AddValueToStruct(V, + named_decl, + name, + qual_type, + value_size, + value_alignment)) return false; } |