2010-06-09 00:52:24 +08:00
|
|
|
//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
// Project includes
|
2010-09-23 11:01:22 +08:00
|
|
|
#include "clang/AST/DeclarationName.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/lldb-private.h"
|
|
|
|
#include "lldb/Core/Address.h"
|
2010-07-16 08:09:46 +08:00
|
|
|
#include "lldb/Core/Error.h"
|
2010-06-23 08:47:48 +08:00
|
|
|
#include "lldb/Core/Log.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Core/Module.h"
|
|
|
|
#include "lldb/Expression/ClangASTSource.h"
|
2010-08-11 11:57:18 +08:00
|
|
|
#include "lldb/Expression/ClangPersistentVariables.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Symbol/ClangASTContext.h"
|
|
|
|
#include "lldb/Symbol/CompileUnit.h"
|
|
|
|
#include "lldb/Symbol/Function.h"
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
|
|
#include "lldb/Symbol/Type.h"
|
|
|
|
#include "lldb/Symbol/TypeList.h"
|
|
|
|
#include "lldb/Symbol/Variable.h"
|
|
|
|
#include "lldb/Symbol/VariableList.h"
|
2010-07-21 07:31:16 +08:00
|
|
|
#include "lldb/Target/ExecutionContext.h"
|
2010-07-16 08:09:46 +08:00
|
|
|
#include "lldb/Target/Process.h"
|
2010-10-06 04:18:48 +08:00
|
|
|
#include "lldb/Target/RegisterContext.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Target/StackFrame.h"
|
2010-07-21 07:31:16 +08:00
|
|
|
#include "lldb/Target/Target.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
using namespace clang;
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) :
|
|
|
|
m_exe_ctx(exe_ctx), m_struct_laid_out(false),
|
2010-07-16 08:09:46 +08:00
|
|
|
m_materialized_location(0)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
if (exe_ctx && exe_ctx->frame)
|
|
|
|
m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
|
|
|
|
else
|
|
|
|
m_sym_ctx = NULL;
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
if (exe_ctx && exe_ctx->process)
|
|
|
|
m_persistent_vars = &exe_ctx->process->GetPersistentVariables();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ClangExpressionDeclMap::~ClangExpressionDeclMap()
|
2010-08-24 07:09:38 +08:00
|
|
|
{
|
|
|
|
for (uint64_t entity_index = 0, num_entities = m_found_entities.Size();
|
|
|
|
entity_index < num_entities;
|
|
|
|
++entity_index)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(entity_index));
|
|
|
|
if (entity.m_parser_vars.get() &&
|
|
|
|
entity.m_parser_vars->m_lldb_value)
|
|
|
|
delete entity.m_parser_vars->m_lldb_value;
|
2010-08-31 06:17:16 +08:00
|
|
|
|
|
|
|
entity.DisableParserVars();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint64_t pvar_index = 0, num_pvars = m_persistent_vars->Size();
|
|
|
|
pvar_index < num_pvars;
|
|
|
|
++pvar_index)
|
|
|
|
{
|
|
|
|
ClangExpressionVariable &pvar(m_persistent_vars->VariableAtIndex(pvar_index));
|
|
|
|
pvar.DisableParserVars();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-10-08 09:58:41 +08:00
|
|
|
if (m_materialized_location)
|
|
|
|
{
|
|
|
|
m_exe_ctx->process->DeallocateMemory(m_materialized_location);
|
|
|
|
m_materialized_location = 0;
|
|
|
|
}
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (m_sym_ctx)
|
|
|
|
delete m_sym_ctx;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
// Interface for IRForTarget
|
|
|
|
|
2010-08-12 09:56:52 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::GetPersistentResultName (std::string &name)
|
|
|
|
{
|
|
|
|
m_persistent_vars->GetNextResultName(m_result_name);
|
|
|
|
|
|
|
|
name = m_result_name;
|
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
bool
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionDeclMap::AddPersistentVariable (const clang::NamedDecl *decl,
|
|
|
|
const char *name,
|
|
|
|
TypeFromParser parser_type)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
|
|
|
clang::ASTContext *context(m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
|
|
|
|
|
|
|
|
TypeFromUser user_type(ClangASTContext::CopyType(context,
|
2010-08-12 09:56:52 +08:00
|
|
|
parser_type.GetASTContext(),
|
|
|
|
parser_type.GetOpaqueQualType()),
|
2010-08-11 11:57:18 +08:00
|
|
|
context);
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (!m_persistent_vars->CreatePersistentVariable (name, user_type))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ClangExpressionVariable *var = m_persistent_vars->GetVariable(name);
|
|
|
|
|
|
|
|
if (!var)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
var->EnableParserVars();
|
|
|
|
|
|
|
|
var->m_parser_vars->m_named_decl = decl;
|
|
|
|
var->m_parser_vars->m_parser_type = parser_type;
|
|
|
|
|
|
|
|
return true;
|
2010-08-11 11:57:18 +08:00
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
bool
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionDeclMap::AddValueToStruct (const clang::NamedDecl *decl,
|
2010-08-31 06:17:16 +08:00
|
|
|
const char *name,
|
2010-08-24 07:09:38 +08:00
|
|
|
llvm::Value *value,
|
2010-07-14 05:41:46 +08:00
|
|
|
size_t size,
|
|
|
|
off_t alignment)
|
|
|
|
{
|
2010-08-31 06:17:16 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
m_struct_laid_out = false;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (m_struct_members.GetVariable(decl))
|
|
|
|
return true;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable *var = m_found_entities.GetVariable(decl);
|
|
|
|
|
|
|
|
if (!var)
|
|
|
|
var = m_persistent_vars->GetVariable(decl);
|
|
|
|
|
|
|
|
if (!var)
|
|
|
|
return false;
|
|
|
|
|
2010-08-31 06:17:16 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Adding value for decl %p [%s - %s] to the structure",
|
|
|
|
decl,
|
|
|
|
name,
|
|
|
|
var->m_name.c_str());
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
// We know entity->m_parser_vars is valid because we used a parser variable
|
|
|
|
// to find it
|
|
|
|
var->m_parser_vars->m_llvm_value = value;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
var->EnableJITVars();
|
|
|
|
var->m_jit_vars->m_alignment = alignment;
|
|
|
|
var->m_jit_vars->m_size = size;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
m_struct_members.AddVariable(*var);
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoStructLayout ()
|
|
|
|
{
|
|
|
|
if (m_struct_laid_out)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
off_t cursor = 0;
|
|
|
|
|
|
|
|
m_struct_alignment = 0;
|
|
|
|
m_struct_size = 0;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
|
|
|
|
member_index < num_members;
|
|
|
|
++member_index)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &member(m_struct_members.VariableAtIndex(member_index));
|
|
|
|
|
|
|
|
if (!member.m_jit_vars.get())
|
|
|
|
return false;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (member_index == 0)
|
|
|
|
m_struct_alignment = member.m_jit_vars->m_alignment;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (cursor % member.m_jit_vars->m_alignment)
|
|
|
|
cursor += (member.m_jit_vars->m_alignment - (cursor % member.m_jit_vars->m_alignment));
|
|
|
|
|
|
|
|
member.m_jit_vars->m_offset = cursor;
|
|
|
|
cursor += member.m_jit_vars->m_size;
|
2010-07-14 05:41:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
m_struct_size = cursor;
|
|
|
|
|
|
|
|
m_struct_laid_out = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ClangExpressionDeclMap::GetStructInfo (uint32_t &num_elements,
|
|
|
|
size_t &size,
|
|
|
|
off_t &alignment)
|
|
|
|
{
|
|
|
|
if (!m_struct_laid_out)
|
|
|
|
return false;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
num_elements = m_struct_members.Size();
|
2010-07-14 05:41:46 +08:00
|
|
|
size = m_struct_size;
|
|
|
|
alignment = m_struct_alignment;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::GetStructElement (const clang::NamedDecl *&decl,
|
|
|
|
llvm::Value *&value,
|
|
|
|
off_t &offset,
|
2010-08-31 06:17:16 +08:00
|
|
|
const char *&name,
|
2010-07-14 05:41:46 +08:00
|
|
|
uint32_t index)
|
|
|
|
{
|
|
|
|
if (!m_struct_laid_out)
|
|
|
|
return false;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (index >= m_struct_members.Size())
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &member(m_struct_members.VariableAtIndex(index));
|
|
|
|
|
|
|
|
if (!member.m_parser_vars.get() ||
|
|
|
|
!member.m_jit_vars.get())
|
|
|
|
return false;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
decl = member.m_parser_vars->m_named_decl;
|
|
|
|
value = member.m_parser_vars->m_llvm_value;
|
|
|
|
offset = member.m_jit_vars->m_offset;
|
2010-08-31 06:17:16 +08:00
|
|
|
name = member.m_name.c_str();
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-28 05:39:39 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::GetFunctionInfo (const clang::NamedDecl *decl,
|
|
|
|
llvm::Value**& value,
|
|
|
|
uint64_t &ptr)
|
2010-07-27 10:07:53 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable *entity = m_found_entities.GetVariable(decl);
|
|
|
|
|
|
|
|
if (!entity)
|
|
|
|
return false;
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
// We know m_parser_vars is valid since we searched for the variable by
|
|
|
|
// its NamedDecl
|
2010-07-27 10:07:53 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
value = &entity->m_parser_vars->m_llvm_value;
|
|
|
|
ptr = entity->m_parser_vars->m_lldb_value->GetScalar().ULongLong();
|
|
|
|
|
|
|
|
return true;
|
2010-07-27 10:07:53 +08:00
|
|
|
}
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::GetFunctionAddress (const char *name,
|
|
|
|
uint64_t &ptr)
|
|
|
|
{
|
|
|
|
// Back out in all cases where we're not fully initialized
|
|
|
|
if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ConstString name_cs(name);
|
|
|
|
SymbolContextList sym_ctxs;
|
|
|
|
|
|
|
|
m_sym_ctx->FindFunctionsByName(name_cs, false, sym_ctxs);
|
|
|
|
|
|
|
|
if (!sym_ctxs.GetSize())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SymbolContext sym_ctx;
|
|
|
|
sym_ctxs.GetContextAtIndex(0, sym_ctx);
|
|
|
|
|
|
|
|
const Address *fun_address;
|
|
|
|
|
|
|
|
if (sym_ctx.function)
|
|
|
|
fun_address = &sym_ctx.function->GetAddressRange().GetBaseAddress();
|
|
|
|
else if (sym_ctx.symbol)
|
|
|
|
fun_address = &sym_ctx.symbol->GetAddressRangeRef().GetBaseAddress();
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
2010-09-15 07:36:40 +08:00
|
|
|
ptr = fun_address->GetLoadAddress(m_exe_ctx->target);
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
// Interface for CommandObjectExpression
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::Materialize (ExecutionContext *exe_ctx,
|
|
|
|
lldb::addr_t &struct_address,
|
|
|
|
Error &err)
|
|
|
|
{
|
|
|
|
bool result = DoMaterialize(false, exe_ctx, NULL, err);
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
struct_address = m_materialized_location;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::GetObjectPointer(lldb::addr_t &object_ptr,
|
|
|
|
ExecutionContext *exe_ctx,
|
|
|
|
Error &err)
|
|
|
|
{
|
|
|
|
if (!exe_ctx || !exe_ctx->frame || !exe_ctx->target || !exe_ctx->process)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't load 'this' because the context is incomplete");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_object_pointer_type.GetOpaqueQualType())
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't load 'this' because its type is unknown");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Variable *object_ptr_var = FindVariableInScope(*exe_ctx->frame, "this", &m_object_pointer_type);
|
|
|
|
|
|
|
|
if (!object_ptr_var)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't find 'this' with appropriate type in scope");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(*exe_ctx,
|
|
|
|
object_ptr_var,
|
|
|
|
m_object_pointer_type.GetASTContext()));
|
|
|
|
|
|
|
|
if (!location_value.get())
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't get the location for 'this'");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (location_value->GetValueType() == Value::eValueTypeLoadAddress)
|
|
|
|
{
|
|
|
|
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
|
|
|
uint32_t address_byte_size = exe_ctx->target->GetArchitecture().GetAddressByteSize();
|
|
|
|
lldb::ByteOrder address_byte_order = exe_ctx->process->GetByteOrder();
|
|
|
|
|
|
|
|
if (ClangASTType::GetClangTypeBitWidth(m_object_pointer_type.GetASTContext(), m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("'this' is not of an expected pointer size");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataBufferHeap data;
|
|
|
|
data.SetByteSize(address_byte_size);
|
|
|
|
Error read_error;
|
|
|
|
|
|
|
|
if (exe_ctx->process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Coldn't read 'this' from the target: %s", read_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor extractor(data.GetBytes(), data.GetByteSize(), address_byte_order, address_byte_size);
|
|
|
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
|
|
|
object_ptr = extractor.GetPointer(&offset);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err.SetErrorString("'this' is not in memory; LLDB must be extended to handle registers");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::Dematerialize (ExecutionContext *exe_ctx,
|
2010-08-20 09:02:30 +08:00
|
|
|
ClangExpressionVariable *&result,
|
2010-07-21 07:31:16 +08:00
|
|
|
Error &err)
|
|
|
|
{
|
2010-08-12 09:56:52 +08:00
|
|
|
return DoMaterialize(true, exe_ctx, &result, err);
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
|
|
|
|
2010-07-24 06:19:18 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DumpMaterializedStruct(ExecutionContext *exe_ctx,
|
|
|
|
Stream &s,
|
|
|
|
Error &err)
|
|
|
|
{
|
|
|
|
if (!m_struct_laid_out)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Structure hasn't been laid out yet");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exe_ctx)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Received null execution context");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!exe_ctx->process)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't find the process");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exe_ctx->target)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't find the target");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::DataBufferSP data(new DataBufferHeap(m_struct_size, 0));
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx->process->ReadMemory (m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor extractor(data, exe_ctx->process->GetByteOrder(), exe_ctx->target->GetArchitecture().GetAddressByteSize());
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
|
|
|
|
member_index < num_members;
|
|
|
|
++member_index)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &member (m_struct_members.VariableAtIndex(member_index));
|
2010-07-24 06:19:18 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
s.Printf("[%s]\n", member.m_name.c_str());
|
|
|
|
|
|
|
|
if (!member.m_jit_vars.get())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
extractor.Dump(&s, // stream
|
|
|
|
member.m_jit_vars->m_offset, // offset
|
|
|
|
lldb::eFormatBytesWithASCII, // format
|
|
|
|
1, // byte size of individual entries
|
|
|
|
member.m_jit_vars->m_size, // number of entries
|
|
|
|
16, // entries per line
|
|
|
|
m_materialized_location + member.m_jit_vars->m_offset, // address to print
|
|
|
|
0, // bit size (bitfields only; 0 means ignore)
|
|
|
|
0); // bit alignment (bitfields only; 0 means ignore)
|
2010-07-24 06:19:18 +08:00
|
|
|
|
|
|
|
s.PutChar('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
|
|
|
|
ExecutionContext *exe_ctx,
|
2010-08-20 09:02:30 +08:00
|
|
|
ClangExpressionVariable **result,
|
2010-07-21 07:31:16 +08:00
|
|
|
Error &err)
|
2010-07-16 08:09:46 +08:00
|
|
|
{
|
2010-07-17 08:43:37 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
2010-08-12 09:56:52 +08:00
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
if (!m_struct_laid_out)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Structure hasn't been laid out yet");
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exe_ctx)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Received null execution context");
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2010-07-24 09:37:44 +08:00
|
|
|
if (!exe_ctx->frame)
|
|
|
|
{
|
|
|
|
err.SetErrorString("Received null execution frame");
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2010-09-14 05:34:21 +08:00
|
|
|
if (!m_struct_size)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Not bothering to allocate a struct because no arguments are needed");
|
|
|
|
|
|
|
|
m_allocated_area = NULL;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
if (!dematerialize)
|
|
|
|
{
|
|
|
|
if (m_materialized_location)
|
|
|
|
{
|
|
|
|
exe_ctx->process->DeallocateMemory(m_materialized_location);
|
|
|
|
m_materialized_location = 0;
|
|
|
|
}
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-10-08 09:58:41 +08:00
|
|
|
if (log)
|
|
|
|
log->PutCString("Allocating memory for materialized argument struct");
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
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 false;
|
|
|
|
|
|
|
|
m_allocated_area = mem;
|
|
|
|
}
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
m_materialized_location = m_allocated_area;
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
if (m_materialized_location % m_struct_alignment)
|
|
|
|
m_materialized_location += (m_struct_alignment - (m_materialized_location % m_struct_alignment));
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
|
|
|
|
member_index < num_members;
|
|
|
|
++member_index)
|
2010-07-16 08:09:46 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &member (m_struct_members.VariableAtIndex(member_index));
|
|
|
|
|
|
|
|
if (!member.m_parser_vars.get())
|
|
|
|
return false;
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable *entity = m_found_entities.GetVariable(member.m_parser_vars->m_named_decl);
|
|
|
|
ClangExpressionVariable *persistent_variable = m_persistent_vars->GetVariable(member.m_name.c_str());
|
|
|
|
|
|
|
|
if (entity)
|
2010-07-17 08:43:37 +08:00
|
|
|
{
|
2010-08-24 07:09:38 +08:00
|
|
|
if (!member.m_jit_vars.get())
|
|
|
|
return false;
|
2010-08-12 09:56:52 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (!DoMaterializeOneVariable(dematerialize, *exe_ctx, sym_ctx, member.m_name.c_str(), member.m_user_type, m_materialized_location + member.m_jit_vars->m_offset, err))
|
2010-08-11 11:57:18 +08:00
|
|
|
return false;
|
2010-08-24 07:09:38 +08:00
|
|
|
}
|
|
|
|
else if (persistent_variable)
|
|
|
|
{
|
2010-08-31 06:17:16 +08:00
|
|
|
if (!member.m_name.compare(m_result_name))
|
|
|
|
{
|
|
|
|
if (!dematerialize)
|
|
|
|
continue;
|
2010-08-24 07:09:38 +08:00
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Found result member in the struct");
|
2010-08-31 06:17:16 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
*result = &member;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
|
|
|
|
2010-08-31 06:17:16 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Searched for persistent variable %s and found %s", member.m_name.c_str(), persistent_variable->m_name.c_str());
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, persistent_variable->m_name.c_str(), m_materialized_location + member.m_jit_vars->m_offset, err))
|
|
|
|
return false;
|
2010-07-17 08:43:37 +08:00
|
|
|
}
|
2010-08-24 07:09:38 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Unexpected variable %s", member.m_name.c_str());
|
2010-07-17 08:43:37 +08:00
|
|
|
return false;
|
2010-08-24 07:09:38 +08:00
|
|
|
}
|
2010-07-16 08:09:46 +08:00
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable(bool dematerialize,
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
const char *name,
|
|
|
|
lldb::addr_t addr,
|
|
|
|
Error &err)
|
2010-08-31 06:17:16 +08:00
|
|
|
{
|
2010-08-20 09:02:30 +08:00
|
|
|
ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
if (!pvar)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Undefined persistent variable %s", name);
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t pvar_size = pvar->Size();
|
2010-08-20 09:02:30 +08:00
|
|
|
|
2010-10-05 08:00:42 +08:00
|
|
|
if (!pvar->m_data_sp.get())
|
2010-08-20 09:02:30 +08:00
|
|
|
return false;
|
|
|
|
|
2010-10-05 08:00:42 +08:00
|
|
|
uint8_t *pvar_data = pvar->m_data_sp->GetBytes();
|
2010-08-11 11:57:18 +08:00
|
|
|
Error error;
|
|
|
|
|
|
|
|
if (dematerialize)
|
|
|
|
{
|
|
|
|
if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_size, error) != pvar_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_size, error) != pvar_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize,
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
const SymbolContext &sym_ctx,
|
|
|
|
const char *name,
|
|
|
|
TypeFromUser type,
|
|
|
|
lldb::addr_t addr,
|
|
|
|
Error &err)
|
|
|
|
{
|
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
2010-10-06 04:18:48 +08:00
|
|
|
if (!exe_ctx.frame || !exe_ctx.process)
|
2010-09-15 05:59:34 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
Variable *var = FindVariableInScope(*exe_ctx.frame, name, &type);
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
if (!var)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't find %s with appropriate type", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-23 08:16:21 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("%s %s with type %p", (dematerialize ? "Dematerializing" : "Materializing"), name, type.GetOpaqueQualType());
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
|
|
|
|
var,
|
|
|
|
type.GetASTContext()));
|
|
|
|
|
|
|
|
if (!location_value.get())
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't get value for %s", name);
|
|
|
|
return false;
|
|
|
|
}
|
2010-10-06 04:18:48 +08:00
|
|
|
|
|
|
|
// The size of the type contained in addr
|
2010-07-21 07:31:16 +08:00
|
|
|
|
2010-10-06 04:18:48 +08:00
|
|
|
size_t addr_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
|
|
|
|
size_t addr_byte_size = addr_bit_size % 8 ? ((addr_bit_size + 8) / 8) : (addr_bit_size / 8);
|
|
|
|
|
|
|
|
Value::ValueType value_type = location_value->GetValueType();
|
|
|
|
|
|
|
|
switch (value_type)
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-10-06 04:18:48 +08:00
|
|
|
default:
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-10-06 04:18:48 +08:00
|
|
|
StreamString ss;
|
|
|
|
|
|
|
|
location_value->Dump(&ss);
|
|
|
|
|
|
|
|
err.SetErrorStringWithFormat("%s has a value of unhandled type: %s", name, ss.GetString().c_str());
|
|
|
|
return false;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
2010-10-06 04:18:48 +08:00
|
|
|
break;
|
|
|
|
case Value::eValueTypeLoadAddress:
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-10-06 04:18:48 +08:00
|
|
|
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
|
|
|
|
|
|
|
DataBufferHeap data;
|
|
|
|
data.SetByteSize(addr_byte_size);
|
|
|
|
|
|
|
|
lldb::addr_t src_addr;
|
|
|
|
lldb::addr_t dest_addr;
|
|
|
|
|
|
|
|
if (dematerialize)
|
|
|
|
{
|
|
|
|
src_addr = addr;
|
|
|
|
dest_addr = value_addr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src_addr = value_addr;
|
|
|
|
dest_addr = addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name, error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exe_ctx.process->WriteMemory (dest_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name, error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr);
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
2010-10-06 04:18:48 +08:00
|
|
|
break;
|
|
|
|
case Value::eValueTypeScalar:
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-10-06 04:18:48 +08:00
|
|
|
if (location_value->GetContextType() != Value::eContextTypeDCRegisterInfo)
|
|
|
|
{
|
|
|
|
StreamString ss;
|
|
|
|
|
|
|
|
location_value->Dump(&ss);
|
|
|
|
|
|
|
|
err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name, ss.GetString().c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::RegisterInfo *register_info = location_value->GetRegisterInfo();
|
|
|
|
|
|
|
|
if (!register_info)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't get the register information for %s", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterContext *register_context = exe_ctx.GetRegisterContext();
|
|
|
|
|
|
|
|
if (!register_context)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_number = register_info->kinds[lldb::eRegisterKindLLDB];
|
|
|
|
uint32_t register_byte_size = register_info->byte_size;
|
|
|
|
|
|
|
|
if (dematerialize)
|
|
|
|
{
|
|
|
|
// Moving from addr into a register
|
|
|
|
//
|
|
|
|
// Case 1: addr_byte_size and register_byte_size are the same
|
|
|
|
//
|
|
|
|
// |AABBCCDD| Address contents
|
|
|
|
// |AABBCCDD| Register contents
|
|
|
|
//
|
|
|
|
// Case 2: addr_byte_size is bigger than register_byte_size
|
|
|
|
//
|
|
|
|
// Error! (The register should always be big enough to hold the data)
|
|
|
|
//
|
|
|
|
// Case 3: register_byte_size is bigger than addr_byte_size
|
|
|
|
//
|
|
|
|
// |AABB| Address contents
|
|
|
|
// |AABB0000| Register contents [on little-endian hardware]
|
|
|
|
// |0000AABB| Register contents [on big-endian hardware]
|
|
|
|
|
|
|
|
if (addr_byte_size > register_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("%s is too big to store in %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_offset;
|
|
|
|
|
|
|
|
switch (exe_ctx.process->GetByteOrder())
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name);
|
|
|
|
return false;
|
|
|
|
case lldb::eByteOrderLittle:
|
|
|
|
register_offset = 0;
|
|
|
|
break;
|
|
|
|
case lldb::eByteOrderBig:
|
|
|
|
register_offset = register_byte_size - addr_byte_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataBufferHeap register_data (register_byte_size, 0);
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes() + register_offset, addr_byte_size, error) != addr_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name, error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor register_extractor (register_data.GetBytes(), register_byte_size, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
|
|
|
|
|
|
|
|
if (!register_context->WriteRegisterBytes(register_number, register_extractor, 0))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s from %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Moving from a register into addr
|
|
|
|
//
|
|
|
|
// Case 1: addr_byte_size and register_byte_size are the same
|
|
|
|
//
|
|
|
|
// |AABBCCDD| Register contents
|
|
|
|
// |AABBCCDD| Address contents
|
|
|
|
//
|
|
|
|
// Case 2: addr_byte_size is bigger than register_byte_size
|
|
|
|
//
|
|
|
|
// Error! (The register should always be big enough to hold the data)
|
|
|
|
//
|
|
|
|
// Case 3: register_byte_size is bigger than addr_byte_size
|
|
|
|
//
|
|
|
|
// |AABBCCDD| Register contents
|
|
|
|
// |AABB| Address contents on little-endian hardware
|
|
|
|
// |CCDD| Address contents on big-endian hardware
|
|
|
|
|
|
|
|
if (addr_byte_size > register_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("%s is too big to store in %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_offset;
|
|
|
|
|
|
|
|
switch (exe_ctx.process->GetByteOrder())
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name);
|
|
|
|
return false;
|
|
|
|
case lldb::eByteOrderLittle:
|
|
|
|
register_offset = 0;
|
|
|
|
break;
|
|
|
|
case lldb::eByteOrderBig:
|
|
|
|
register_offset = register_byte_size - addr_byte_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor register_extractor;
|
|
|
|
|
|
|
|
if (!register_context->ReadRegisterBytes(register_number, register_extractor))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s from %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const void *register_data = register_extractor.GetData(®ister_offset, addr_byte_size);
|
|
|
|
|
|
|
|
if (!register_data)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Read but couldn't extract data for %s from %s", name, register_info->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx.process->WriteMemory (addr, register_data, addr_byte_size, error) != addr_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-07-16 08:09:46 +08:00
|
|
|
}
|
|
|
|
|
2010-09-15 05:59:34 +08:00
|
|
|
Variable *
|
|
|
|
ClangExpressionDeclMap::FindVariableInScope(StackFrame &frame,
|
|
|
|
const char *name,
|
|
|
|
TypeFromUser *type)
|
|
|
|
{
|
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
|
|
|
ConstString name_cs(name);
|
|
|
|
|
|
|
|
VariableList *var_list = frame.GetVariableList(true);
|
|
|
|
|
2010-10-15 06:52:14 +08:00
|
|
|
if (!var_list)
|
|
|
|
return NULL;
|
|
|
|
|
2010-09-15 05:59:34 +08:00
|
|
|
lldb::VariableSP var = var_list->FindVariable(name_cs);
|
|
|
|
|
|
|
|
if (!var)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!type)
|
|
|
|
return var.get();
|
|
|
|
|
|
|
|
if (type->GetASTContext() == var->GetType()->GetClangAST())
|
|
|
|
{
|
2010-09-29 09:12:09 +08:00
|
|
|
if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var->GetType()->GetClangType()))
|
2010-09-15 05:59:34 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipping a candidate variable because of different AST contexts");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return var.get();
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
// Interface for ClangASTSource
|
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::GetDecls(NameSearchContext &context,
|
|
|
|
const char *name)
|
|
|
|
{
|
2010-06-23 08:47:48 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
2010-10-15 11:36:13 +08:00
|
|
|
log->Printf("Hunting for a definition for '%s'", name);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
// Back out in all cases where we're not fully initialized
|
|
|
|
if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
|
|
|
|
return;
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
|
|
|
|
ConstString name_cs(name);
|
|
|
|
|
|
|
|
if (!strcmp(name, "___clang_class"))
|
|
|
|
{
|
|
|
|
// Clang is looking for the type of "this"
|
|
|
|
|
|
|
|
VariableList *vars = m_exe_ctx->frame->GetVariableList(false);
|
|
|
|
|
|
|
|
if (!vars)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
|
|
|
|
|
|
|
|
if (!this_var)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Type *this_type = this_var->GetType();
|
|
|
|
|
|
|
|
if (!this_type)
|
|
|
|
return;
|
|
|
|
|
2010-09-29 09:12:09 +08:00
|
|
|
TypeFromUser this_user_type(this_type->GetClangType(),
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
this_type->GetClangAST());
|
|
|
|
|
|
|
|
m_object_pointer_type = this_user_type;
|
|
|
|
|
|
|
|
void *pointer_target_type;
|
|
|
|
|
|
|
|
if (!ClangASTContext::IsPointerType(this_user_type.GetOpaqueQualType(),
|
|
|
|
&pointer_target_type))
|
|
|
|
return;
|
|
|
|
|
|
|
|
TypeFromUser class_user_type(pointer_target_type,
|
|
|
|
this_type->GetClangAST());
|
|
|
|
|
|
|
|
AddOneType(context, class_user_type, true);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2010-09-15 05:59:34 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
SymbolContextList sym_ctxs;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
m_sym_ctx->FindFunctionsByName(name_cs, false, sym_ctxs);
|
|
|
|
|
2010-09-08 05:49:41 +08:00
|
|
|
bool found_specific = false;
|
2010-10-06 08:10:07 +08:00
|
|
|
Symbol *generic_symbol = NULL;
|
|
|
|
Symbol *non_extern_symbol = NULL;
|
2010-09-08 05:49:41 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
for (uint32_t index = 0, num_indices = sym_ctxs.GetSize();
|
|
|
|
index < num_indices;
|
|
|
|
++index)
|
|
|
|
{
|
|
|
|
SymbolContext sym_ctx;
|
|
|
|
sym_ctxs.GetContextAtIndex(index, sym_ctx);
|
2010-10-06 08:10:07 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
if (sym_ctx.function)
|
2010-09-08 05:49:41 +08:00
|
|
|
{
|
|
|
|
// TODO only do this if it's a C function; C++ functions may be
|
|
|
|
// overloaded
|
|
|
|
if (!found_specific)
|
|
|
|
AddOneFunction(context, sym_ctx.function, NULL);
|
|
|
|
found_specific = true;
|
|
|
|
}
|
2010-10-06 08:10:07 +08:00
|
|
|
else if (sym_ctx.symbol)
|
2010-09-08 05:49:41 +08:00
|
|
|
{
|
2010-10-06 08:10:07 +08:00
|
|
|
if (sym_ctx.symbol->IsExternal())
|
|
|
|
generic_symbol = sym_ctx.symbol;
|
|
|
|
else
|
|
|
|
non_extern_symbol = sym_ctx.symbol;
|
2010-09-08 05:49:41 +08:00
|
|
|
}
|
2010-07-27 08:55:47 +08:00
|
|
|
}
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-10-06 08:10:07 +08:00
|
|
|
if (!found_specific)
|
|
|
|
{
|
|
|
|
if (generic_symbol)
|
|
|
|
AddOneFunction(context, NULL, generic_symbol);
|
|
|
|
else if (non_extern_symbol)
|
|
|
|
AddOneFunction(context, NULL, non_extern_symbol);
|
|
|
|
}
|
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
Variable *var = FindVariableInScope(*m_exe_ctx->frame, name);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-07-17 08:43:37 +08:00
|
|
|
if (var)
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
AddOneVariable(context, var);
|
2010-08-04 09:02:13 +08:00
|
|
|
|
2010-08-20 09:02:30 +08:00
|
|
|
ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
if (pvar)
|
|
|
|
AddOneVariable(context, pvar);
|
|
|
|
|
2010-08-04 09:02:13 +08:00
|
|
|
|
2010-09-28 07:54:58 +08:00
|
|
|
// See information on gating of this operation next to the definition for
|
|
|
|
// m_lookedup_types.
|
|
|
|
|
|
|
|
const char *name_uniq = name_cs.GetCString();
|
|
|
|
|
|
|
|
if (m_lookedup_types.find(name_uniq) == m_lookedup_types.end())
|
|
|
|
{
|
|
|
|
// 1 The name is added to m_lookedup_types.
|
|
|
|
m_lookedup_types.insert(std::pair<const char*, bool>(name_uniq, true));
|
|
|
|
|
|
|
|
// 2 The type is looked up and added, potentially causing more type loookups.
|
|
|
|
lldb::TypeSP type = m_sym_ctx->FindTypeByName(name_cs);
|
|
|
|
|
|
|
|
if (type.get())
|
|
|
|
{
|
2010-09-29 09:12:09 +08:00
|
|
|
TypeFromUser user_type(type->GetClangType(),
|
2010-09-28 07:54:58 +08:00
|
|
|
type->GetClangAST());
|
|
|
|
|
|
|
|
AddOneType(context, user_type, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3 The name is removed from m_lookedup_types.
|
|
|
|
m_lookedup_types.erase(name_uniq);
|
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2010-07-17 08:43:37 +08:00
|
|
|
|
|
|
|
Value *
|
|
|
|
ClangExpressionDeclMap::GetVariableValue(ExecutionContext &exe_ctx,
|
|
|
|
Variable *var,
|
2010-07-21 07:31:16 +08:00
|
|
|
clang::ASTContext *parser_ast_context,
|
|
|
|
TypeFromUser *user_type,
|
|
|
|
TypeFromParser *parser_type)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-06-23 08:47:48 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
Type *var_type = var->GetType();
|
|
|
|
|
|
|
|
if (!var_type)
|
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipped a definition because it has no type");
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-09-29 09:12:09 +08:00
|
|
|
void *var_opaque_type = var_type->GetClangType();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
if (!var_opaque_type)
|
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipped a definition because it has no Clang type");
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TypeList *type_list = var_type->GetTypeList();
|
|
|
|
|
|
|
|
if (!type_list)
|
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipped a definition because the type has no associated type list");
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
clang::ASTContext *exe_ast_ctx = type_list->GetClangASTContext().getASTContext();
|
|
|
|
|
|
|
|
if (!exe_ast_ctx)
|
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
|
|
|
log->PutCString("There is no AST context for the current execution context");
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-07-17 08:43:37 +08:00
|
|
|
DWARFExpression &var_location_expr = var->LocationExpression();
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
std::auto_ptr<Value> var_location(new Value);
|
|
|
|
|
2010-09-14 10:20:48 +08:00
|
|
|
lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
|
|
|
|
|
|
|
|
if (var_location_expr.IsLocationList())
|
|
|
|
{
|
|
|
|
SymbolContext var_sc;
|
|
|
|
var->CalculateSymbolContext (&var_sc);
|
2010-09-15 07:36:40 +08:00
|
|
|
loclist_base_load_addr = var_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target);
|
2010-09-14 10:20:48 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
Error err;
|
|
|
|
|
2010-09-14 10:20:48 +08:00
|
|
|
if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, loclist_base_load_addr, NULL, *var_location.get(), &err))
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Error evaluating location: %s", err.AsCString());
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
clang::ASTContext *var_ast_context = type_list->GetClangASTContext().getASTContext();
|
|
|
|
|
2010-07-17 08:43:37 +08:00
|
|
|
void *type_to_use;
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
if (parser_ast_context)
|
|
|
|
{
|
|
|
|
type_to_use = ClangASTContext::CopyType(parser_ast_context, var_ast_context, var_opaque_type);
|
|
|
|
|
|
|
|
if (parser_type)
|
|
|
|
*parser_type = TypeFromParser(type_to_use, parser_ast_context);
|
|
|
|
}
|
2010-07-17 08:43:37 +08:00
|
|
|
else
|
|
|
|
type_to_use = var_opaque_type;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
if (var_location.get()->GetContextType() == Value::eContextTypeInvalid)
|
2010-07-17 08:43:37 +08:00
|
|
|
var_location.get()->SetContext(Value::eContextTypeOpaqueClangQualType, type_to_use);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
if (var_location.get()->GetValueType() == Value::eValueTypeFileAddress)
|
|
|
|
{
|
|
|
|
SymbolContext var_sc;
|
|
|
|
var->CalculateSymbolContext(&var_sc);
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
if (!var_sc.module_sp)
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
ObjectFile *object_file = var_sc.module_sp->GetObjectFile();
|
|
|
|
|
|
|
|
if (!object_file)
|
2010-07-17 08:43:37 +08:00
|
|
|
return NULL;
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
Address so_addr(var_location->GetScalar().ULongLong(), object_file->GetSectionList());
|
|
|
|
|
2010-09-15 07:36:40 +08:00
|
|
|
lldb::addr_t load_addr = so_addr.GetLoadAddress(m_exe_ctx->target);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
var_location->GetScalar() = load_addr;
|
|
|
|
var_location->SetValueType(Value::eValueTypeLoadAddress);
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
if (user_type)
|
|
|
|
*user_type = TypeFromUser(var_opaque_type, var_ast_context);
|
2010-07-17 08:43:37 +08:00
|
|
|
|
|
|
|
return var_location.release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
Variable* var)
|
2010-07-17 08:43:37 +08:00
|
|
|
{
|
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
TypeFromUser ut;
|
|
|
|
TypeFromParser pt;
|
2010-07-17 08:43:37 +08:00
|
|
|
|
|
|
|
Value *var_location = GetVariableValue(*m_exe_ctx,
|
|
|
|
var,
|
|
|
|
context.GetASTContext(),
|
2010-07-21 07:31:16 +08:00
|
|
|
&ut,
|
|
|
|
&pt);
|
2010-07-17 08:43:37 +08:00
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(m_found_entities.CreateVariable()));
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
entity.m_name = context.Name.getAsString();
|
2010-08-24 07:09:38 +08:00
|
|
|
entity.m_user_type = ut;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
entity.EnableParserVars();
|
|
|
|
entity.m_parser_vars->m_parser_type = pt;
|
|
|
|
entity.m_parser_vars->m_named_decl = var_decl;
|
|
|
|
entity.m_parser_vars->m_llvm_value = NULL;
|
|
|
|
entity.m_parser_vars->m_lldb_value = var_location;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
2010-07-31 09:32:05 +08:00
|
|
|
log->Printf("Found variable %s, returned (NamedDecl)%p", context.Name.getAsString().c_str(), var_decl);
|
2010-06-23 07:46:24 +08:00
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
|
2010-08-20 09:02:30 +08:00
|
|
|
ClangExpressionVariable *pvar)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2010-08-31 06:17:16 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
2010-08-20 09:02:30 +08:00
|
|
|
TypeFromUser user_type = pvar->m_user_type;
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
TypeFromParser parser_type(ClangASTContext::CopyType(context.GetASTContext(),
|
|
|
|
user_type.GetASTContext(),
|
|
|
|
user_type.GetOpaqueQualType()),
|
|
|
|
context.GetASTContext());
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
|
|
|
|
|
|
|
|
pvar->EnableParserVars();
|
|
|
|
pvar->m_parser_vars->m_parser_type = parser_type;
|
|
|
|
pvar->m_parser_vars->m_named_decl = var_decl;
|
|
|
|
pvar->m_parser_vars->m_llvm_value = NULL;
|
|
|
|
pvar->m_parser_vars->m_lldb_value = NULL;
|
2010-08-31 06:17:16 +08:00
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Added pvar %s, returned (NamedDecl)%p", pvar->m_name.c_str(), var_decl);
|
2010-08-11 11:57:18 +08:00
|
|
|
}
|
|
|
|
|
2010-06-23 07:46:24 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
|
2010-07-27 08:55:47 +08:00
|
|
|
Function* fun,
|
|
|
|
Symbol* symbol)
|
2010-06-23 07:46:24 +08:00
|
|
|
{
|
2010-06-23 08:47:48 +08:00
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
NamedDecl *fun_decl;
|
|
|
|
std::auto_ptr<Value> fun_location(new Value);
|
|
|
|
const Address *fun_address;
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
// only valid for Functions, not for Symbols
|
|
|
|
void *fun_opaque_type = NULL;
|
|
|
|
clang::ASTContext *fun_ast_context = NULL;
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-07-27 08:55:47 +08:00
|
|
|
if (fun)
|
|
|
|
{
|
2010-09-09 06:38:54 +08:00
|
|
|
#define BROKEN_OVERLOADING
|
|
|
|
// Awaiting a fix on the Clang side
|
|
|
|
#ifndef BROKEN_OVERLOADING
|
2010-07-27 08:55:47 +08:00
|
|
|
Type *fun_type = fun->GetType();
|
|
|
|
|
|
|
|
if (!fun_type)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipped a function because it has no type");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-29 09:12:09 +08:00
|
|
|
fun_opaque_type = fun_type->GetClangType();
|
2010-07-27 08:55:47 +08:00
|
|
|
|
|
|
|
if (!fun_opaque_type)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipped a function because it has no Clang type");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fun_address = &fun->GetAddressRange().GetBaseAddress();
|
|
|
|
|
|
|
|
TypeList *type_list = fun_type->GetTypeList();
|
|
|
|
fun_ast_context = type_list->GetClangASTContext().getASTContext();
|
|
|
|
void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), fun_ast_context, fun_opaque_type);
|
|
|
|
|
|
|
|
fun_decl = context.AddFunDecl(copied_type);
|
2010-09-09 06:38:54 +08:00
|
|
|
#else
|
|
|
|
fun_address = &fun->GetAddressRange().GetBaseAddress();
|
|
|
|
|
|
|
|
fun_decl = context.AddGenericFunDecl();
|
|
|
|
#endif
|
2010-07-27 08:55:47 +08:00
|
|
|
}
|
|
|
|
else if (symbol)
|
|
|
|
{
|
|
|
|
fun_address = &symbol->GetAddressRangeRef().GetBaseAddress();
|
|
|
|
|
|
|
|
fun_decl = context.AddGenericFunDecl();
|
|
|
|
}
|
|
|
|
else
|
2010-06-23 07:46:24 +08:00
|
|
|
{
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
2010-07-27 08:55:47 +08:00
|
|
|
log->PutCString("AddOneFunction called with no function and no symbol");
|
2010-06-23 07:46:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-15 07:36:40 +08:00
|
|
|
lldb::addr_t load_addr = fun_address->GetLoadAddress(m_exe_ctx->target);
|
2010-06-23 07:46:24 +08:00
|
|
|
fun_location->SetValueType(Value::eValueTypeLoadAddress);
|
|
|
|
fun_location->GetScalar() = load_addr;
|
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(m_found_entities.CreateVariable()));
|
|
|
|
entity.m_name = context.Name.getAsString();
|
|
|
|
entity.m_user_type = TypeFromUser(fun_opaque_type, fun_ast_context);;
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
entity.EnableParserVars();
|
|
|
|
entity.m_parser_vars->m_named_decl = fun_decl;
|
|
|
|
entity.m_parser_vars->m_llvm_value = NULL;
|
|
|
|
entity.m_parser_vars->m_lldb_value = fun_location.release();
|
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
2010-09-08 05:49:41 +08:00
|
|
|
log->Printf("Found %s function %s, returned (NamedDecl)%p", (fun ? "specific" : "generic"), context.Name.getAsString().c_str(), fun_decl);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2010-08-04 09:02:13 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
TypeFromUser &ut,
|
|
|
|
bool add_method)
|
2010-08-04 09:02:13 +08:00
|
|
|
{
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
clang::ASTContext *parser_ast_context = context.GetASTContext();
|
|
|
|
clang::ASTContext *user_ast_context = ut.GetASTContext();
|
|
|
|
|
|
|
|
void *copied_type = ClangASTContext::CopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
|
|
|
|
|
|
|
|
TypeFromParser parser_type(copied_type, parser_ast_context);
|
2010-08-04 09:02:13 +08:00
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
if (add_method && ClangASTContext::IsAggregateType(copied_type))
|
|
|
|
{
|
|
|
|
void *args[1];
|
|
|
|
|
|
|
|
args[0] = ClangASTContext::GetVoidPtrType(parser_ast_context, false);
|
|
|
|
|
|
|
|
void *method_type = ClangASTContext::CreateFunctionType (parser_ast_context,
|
|
|
|
ClangASTContext::GetBuiltInType_void(parser_ast_context),
|
|
|
|
args,
|
|
|
|
1,
|
|
|
|
false,
|
|
|
|
ClangASTContext::GetTypeQualifiers(copied_type));
|
2010-10-01 10:31:07 +08:00
|
|
|
|
2010-09-24 13:15:53 +08:00
|
|
|
const bool is_virtual = false;
|
|
|
|
const bool is_static = false;
|
|
|
|
const bool is_inline = false;
|
2010-10-01 10:31:07 +08:00
|
|
|
const bool is_explicit = false;
|
|
|
|
|
2010-09-24 13:15:53 +08:00
|
|
|
ClangASTContext::AddMethodToCXXRecordType (parser_ast_context,
|
|
|
|
copied_type,
|
|
|
|
"___clang_expr",
|
|
|
|
method_type,
|
|
|
|
lldb::eAccessPublic,
|
|
|
|
is_virtual,
|
|
|
|
is_static,
|
2010-10-01 10:31:07 +08:00
|
|
|
is_inline,
|
|
|
|
is_explicit);
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
}
|
2010-08-04 09:02:13 +08:00
|
|
|
|
|
|
|
context.AddTypeDecl(copied_type);
|
|
|
|
}
|