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-11-02 07:22:47 +08:00
|
|
|
#include "clang/AST/Decl.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"
|
2010-12-16 11:17:46 +08:00
|
|
|
#include "lldb/Core/ValueObjectConstResult.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#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"
|
2010-11-13 11:52:47 +08:00
|
|
|
#include "lldb/Symbol/ClangNamespaceDecl.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#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-12-07 09:56:02 +08:00
|
|
|
#include "lldb/Target/Thread.h"
|
2010-11-02 07:22:47 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
using namespace lldb;
|
2010-06-09 00:52:24 +08:00
|
|
|
using namespace lldb_private;
|
|
|
|
using namespace clang;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory) :
|
2010-10-16 06:48:33 +08:00
|
|
|
m_found_entities (),
|
|
|
|
m_struct_members (),
|
2010-12-03 09:38:59 +08:00
|
|
|
m_parser_vars (),
|
2011-01-13 16:53:35 +08:00
|
|
|
m_struct_vars (),
|
|
|
|
m_keep_result_in_memory (keep_result_in_memory)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
EnableStructVars();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ClangExpressionDeclMap::~ClangExpressionDeclMap()
|
2010-12-03 09:38:59 +08:00
|
|
|
{
|
|
|
|
DidDematerialize();
|
|
|
|
DisableStructVars();
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx)
|
2010-08-24 07:09:38 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
EnableParserVars();
|
|
|
|
m_parser_vars->m_exe_ctx = &exe_ctx;
|
2010-08-31 06:17:16 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (exe_ctx.frame)
|
|
|
|
m_parser_vars->m_sym_ctx = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything);
|
2010-12-07 09:56:02 +08:00
|
|
|
else if (exe_ctx.thread)
|
|
|
|
m_parser_vars->m_sym_ctx = exe_ctx.thread->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything);
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (exe_ctx.target)
|
|
|
|
m_parser_vars->m_persistent_vars = &exe_ctx.target->GetPersistentVariables();
|
2010-12-03 09:38:59 +08:00
|
|
|
}
|
2010-10-26 08:31:56 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::DidParse()
|
2010-12-03 09:38:59 +08:00
|
|
|
{
|
|
|
|
if (m_parser_vars.get())
|
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
|
2010-12-03 09:38:59 +08:00
|
|
|
entity_index < num_entities;
|
|
|
|
++entity_index)
|
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index));
|
|
|
|
if (var_sp &&
|
|
|
|
var_sp->m_parser_vars.get() &&
|
|
|
|
var_sp->m_parser_vars->m_lldb_value)
|
|
|
|
delete var_sp->m_parser_vars->m_lldb_value;
|
2010-12-03 09:38:59 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->DisableParserVars();
|
2010-12-03 09:38:59 +08:00
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize();
|
2010-12-03 09:38:59 +08:00
|
|
|
pvar_index < num_pvars;
|
|
|
|
++pvar_index)
|
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
|
|
|
|
if (pvar_sp)
|
|
|
|
pvar_sp->DisableParserVars();
|
2010-12-03 09:38:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DisableParserVars();
|
2010-10-08 09:58:41 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
// Interface for IRForTarget
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
const ConstString &
|
|
|
|
ClangExpressionDeclMap::GetPersistentResultName ()
|
2010-08-12 09:56:52 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
assert (m_parser_vars.get());
|
|
|
|
if (!m_struct_vars->m_result_name)
|
2010-12-14 10:59:59 +08:00
|
|
|
{
|
|
|
|
Target *target = m_parser_vars->GetTarget();
|
|
|
|
assert (target);
|
|
|
|
m_struct_vars->m_result_name = target->GetPersistentVariables().GetNextPersistentVariableName();
|
|
|
|
}
|
2010-12-03 09:38:59 +08:00
|
|
|
return m_struct_vars->m_result_name;
|
2010-08-12 09:56:52 +08:00
|
|
|
}
|
|
|
|
|
2010-12-16 11:17:46 +08:00
|
|
|
lldb::ClangExpressionVariableSP
|
|
|
|
ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
|
|
|
|
lldb_private::TypeFromParser type,
|
|
|
|
const llvm::APInt& value)
|
|
|
|
{
|
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
|
|
|
clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
|
|
|
|
|
|
|
|
TypeFromUser user_type(ClangASTContext::CopyType(context,
|
|
|
|
type.GetASTContext(),
|
|
|
|
type.GetOpaqueQualType()),
|
|
|
|
context);
|
|
|
|
|
2011-01-04 10:41:41 +08:00
|
|
|
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (name,
|
|
|
|
user_type,
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetByteOrder(),
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()))
|
|
|
|
return lldb::ClangExpressionVariableSP();
|
|
|
|
|
|
|
|
ClangExpressionVariableSP pvar_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
|
|
|
|
|
|
|
|
if (!pvar_sp)
|
|
|
|
return lldb::ClangExpressionVariableSP();
|
2010-12-16 11:17:46 +08:00
|
|
|
|
2011-01-04 10:41:41 +08:00
|
|
|
uint8_t *pvar_data = pvar_sp->GetValueBytes();
|
|
|
|
if (pvar_data == NULL)
|
|
|
|
return lldb::ClangExpressionVariableSP();
|
2010-12-16 11:17:46 +08:00
|
|
|
|
|
|
|
uint64_t value64 = value.getLimitedValue();
|
|
|
|
|
|
|
|
ByteOrder byte_order = m_parser_vars->m_exe_ctx->process->GetByteOrder();
|
|
|
|
|
|
|
|
size_t num_val_bytes = sizeof(value64);
|
2011-01-04 10:41:41 +08:00
|
|
|
size_t num_data_bytes = pvar_sp->GetByteSize();
|
2010-12-16 11:17:46 +08:00
|
|
|
|
|
|
|
size_t num_bytes = num_val_bytes;
|
|
|
|
if (num_bytes > num_data_bytes)
|
|
|
|
num_bytes = num_data_bytes;
|
|
|
|
|
|
|
|
for (off_t byte_idx = 0;
|
|
|
|
byte_idx < num_bytes;
|
|
|
|
++byte_idx)
|
|
|
|
{
|
|
|
|
uint64_t shift = byte_idx * 8;
|
|
|
|
uint64_t mask = 0xffll << shift;
|
|
|
|
uint8_t cur_byte = (uint8_t)((value64 & mask) >> shift);
|
|
|
|
|
|
|
|
switch (byte_order)
|
|
|
|
{
|
2011-01-04 10:41:41 +08:00
|
|
|
case eByteOrderBig:
|
|
|
|
// High Low
|
|
|
|
// Original: |AABBCCDDEEFFGGHH|
|
|
|
|
// Target: |EEFFGGHH|
|
|
|
|
|
|
|
|
pvar_data[num_data_bytes - (1 + byte_idx)] = cur_byte;
|
|
|
|
break;
|
|
|
|
case eByteOrderLittle:
|
|
|
|
// Target: |HHGGFFEE|
|
|
|
|
pvar_data[byte_idx] = cur_byte;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return lldb::ClangExpressionVariableSP();
|
2010-12-16 11:17:46 +08:00
|
|
|
}
|
|
|
|
}
|
2011-01-13 16:53:35 +08:00
|
|
|
|
|
|
|
pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
|
2011-01-04 10:41:41 +08:00
|
|
|
|
|
|
|
return pvar_sp;
|
2010-12-16 11:17:46 +08:00
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::AddPersistentVariable
|
|
|
|
(
|
|
|
|
const clang::NamedDecl *decl,
|
|
|
|
const ConstString &name,
|
2011-01-13 16:53:35 +08:00
|
|
|
TypeFromParser parser_type,
|
|
|
|
bool is_result,
|
|
|
|
bool is_lvalue
|
2010-10-16 06:48:33 +08:00
|
|
|
)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
|
2010-08-11 11:57:18 +08:00
|
|
|
|
|
|
|
TypeFromUser user_type(ClangASTContext::CopyType(context,
|
2010-08-12 09:56:52 +08:00
|
|
|
parser_type.GetASTContext(),
|
|
|
|
parser_type.GetOpaqueQualType()),
|
2011-01-14 05:23:32 +08:00
|
|
|
context);
|
2010-08-11 11:57:18 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (name,
|
|
|
|
user_type,
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetByteOrder(),
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()))
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP var_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!var_sp)
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
if (is_result)
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
|
|
|
|
else
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
|
|
|
|
|
|
|
|
if (is_lvalue)
|
|
|
|
{
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->EnableParserVars();
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->m_parser_vars->m_named_decl = decl;
|
|
|
|
var_sp->m_parser_vars->m_parser_type = parser_type;
|
2010-08-24 07:09:38 +08:00
|
|
|
|
|
|
|
return true;
|
2010-08-11 11:57:18 +08:00
|
|
|
}
|
|
|
|
|
2010-07-14 05:41:46 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::AddValueToStruct
|
|
|
|
(
|
|
|
|
const clang::NamedDecl *decl,
|
|
|
|
const ConstString &name,
|
|
|
|
llvm::Value *value,
|
|
|
|
size_t size,
|
|
|
|
off_t alignment
|
|
|
|
)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-08-31 06:17:16 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_struct_vars->m_struct_laid_out = false;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
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-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!var_sp)
|
|
|
|
var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl);
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!var_sp)
|
2010-08-24 07:09:38 +08:00
|
|
|
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,
|
2010-10-16 06:48:33 +08:00
|
|
|
name.GetCString(),
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->GetName().GetCString());
|
2010-08-31 06:17:16 +08:00
|
|
|
|
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
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->m_parser_vars->m_llvm_value = value;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
var_sp->EnableJITVars();
|
|
|
|
var_sp->m_jit_vars->m_alignment = alignment;
|
|
|
|
var_sp->m_jit_vars->m_size = size;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
m_struct_members.AddVariable(var_sp);
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoStructLayout ()
|
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
|
|
|
|
if (m_struct_vars->m_struct_laid_out)
|
2010-07-14 05:41:46 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
off_t cursor = 0;
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_struct_vars->m_struct_alignment = 0;
|
|
|
|
m_struct_vars->m_struct_size = 0;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
for (size_t member_index = 0, num_members = m_struct_members.GetSize();
|
2010-08-24 07:09:38 +08:00
|
|
|
member_index < num_members;
|
|
|
|
++member_index)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(member_index));
|
|
|
|
if (!member_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!member_sp->m_jit_vars.get())
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-08-24 07:09:38 +08:00
|
|
|
if (member_index == 0)
|
2010-12-14 10:59:59 +08:00
|
|
|
m_struct_vars->m_struct_alignment = member_sp->m_jit_vars->m_alignment;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (cursor % member_sp->m_jit_vars->m_alignment)
|
|
|
|
cursor += (member_sp->m_jit_vars->m_alignment - (cursor % member_sp->m_jit_vars->m_alignment));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
member_sp->m_jit_vars->m_offset = cursor;
|
|
|
|
cursor += member_sp->m_jit_vars->m_size;
|
2010-07-14 05:41:46 +08:00
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_struct_vars->m_struct_size = cursor;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_struct_vars->m_struct_laid_out = true;
|
2010-07-14 05:41:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
bool ClangExpressionDeclMap::GetStructInfo
|
|
|
|
(
|
|
|
|
uint32_t &num_elements,
|
|
|
|
size_t &size,
|
|
|
|
off_t &alignment
|
|
|
|
)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
|
|
|
|
if (!m_struct_vars->m_struct_laid_out)
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
num_elements = m_struct_members.GetSize();
|
2010-12-03 09:38:59 +08:00
|
|
|
size = m_struct_vars->m_struct_size;
|
|
|
|
alignment = m_struct_vars->m_struct_alignment;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::GetStructElement
|
|
|
|
(
|
|
|
|
const clang::NamedDecl *&decl,
|
|
|
|
llvm::Value *&value,
|
|
|
|
off_t &offset,
|
|
|
|
ConstString &name,
|
|
|
|
uint32_t index
|
|
|
|
)
|
2010-07-14 05:41:46 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
|
|
|
|
if (!m_struct_vars->m_struct_laid_out)
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (index >= m_struct_members.GetSize())
|
2010-07-14 05:41:46 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!member_sp ||
|
|
|
|
!member_sp->m_parser_vars.get() ||
|
|
|
|
!member_sp->m_jit_vars.get())
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
2010-07-14 05:41:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
decl = member_sp->m_parser_vars->m_named_decl;
|
|
|
|
value = member_sp->m_parser_vars->m_llvm_value;
|
|
|
|
offset = member_sp->m_jit_vars->m_offset;
|
|
|
|
name = member_sp->GetName();
|
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
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::GetFunctionInfo
|
|
|
|
(
|
|
|
|
const clang::NamedDecl *decl,
|
|
|
|
llvm::Value**& value,
|
|
|
|
uint64_t &ptr
|
|
|
|
)
|
2010-07-27 10:07:53 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP entity_sp(m_found_entities.GetVariable(decl));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!entity_sp)
|
2010-08-24 07:09:38 +08:00
|
|
|
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-12-14 10:59:59 +08:00
|
|
|
value = &entity_sp->m_parser_vars->m_llvm_value;
|
|
|
|
ptr = entity_sp->m_parser_vars->m_lldb_value->GetScalar().ULongLong();
|
2010-08-24 07:09:38 +08:00
|
|
|
|
|
|
|
return true;
|
2010-07-27 10:07:53 +08:00
|
|
|
}
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::GetFunctionAddress
|
|
|
|
(
|
|
|
|
const ConstString &name,
|
|
|
|
uint64_t &ptr
|
|
|
|
)
|
2010-07-31 09:32:05 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2010-07-31 09:32:05 +08:00
|
|
|
// Back out in all cases where we're not fully initialized
|
2010-12-07 09:56:02 +08:00
|
|
|
if (m_parser_vars->m_exe_ctx->target == NULL)
|
|
|
|
return false;
|
|
|
|
if (!m_parser_vars->m_sym_ctx.target_sp)
|
2010-07-31 09:32:05 +08:00
|
|
|
return false;
|
|
|
|
|
2010-11-10 07:46:37 +08:00
|
|
|
SymbolContextList sc_list;
|
2010-07-31 09:32:05 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_parser_vars->m_sym_ctx.FindFunctionsByName(name, false, sc_list);
|
2010-07-31 09:32:05 +08:00
|
|
|
|
2010-11-10 07:46:37 +08:00
|
|
|
if (!sc_list.GetSize())
|
2010-07-31 09:32:05 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
SymbolContext sym_ctx;
|
2010-11-10 07:46:37 +08:00
|
|
|
sc_list.GetContextAtIndex(0, sym_ctx);
|
2010-07-31 09:32:05 +08:00
|
|
|
|
|
|
|
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-12-03 09:38:59 +08:00
|
|
|
ptr = fun_address->GetLoadAddress (m_parser_vars->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
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::Materialize
|
|
|
|
(
|
2010-12-03 09:38:59 +08:00
|
|
|
ExecutionContext &exe_ctx,
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb::addr_t &struct_address,
|
|
|
|
Error &err
|
|
|
|
)
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
EnableMaterialVars();
|
|
|
|
|
|
|
|
m_material_vars->m_process = exe_ctx.process;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err);
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
if (result)
|
2010-12-03 09:38:59 +08:00
|
|
|
struct_address = m_material_vars->m_materialized_location;
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
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
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::GetObjectPointer
|
|
|
|
(
|
|
|
|
lldb::addr_t &object_ptr,
|
2010-12-14 06:46:15 +08:00
|
|
|
ConstString &object_name,
|
2010-12-03 09:38:59 +08:00
|
|
|
ExecutionContext &exe_ctx,
|
2010-12-14 08:42:36 +08:00
|
|
|
Error &err,
|
|
|
|
bool suppress_type_check
|
2010-10-16 06:48:33 +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
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
|
|
|
|
if (!exe_ctx.frame || !exe_ctx.target || !exe_ctx.process)
|
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
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't load 'this' because the context is incomplete");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (!m_struct_vars->m_object_pointer_type.GetOpaqueQualType())
|
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
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't load 'this' because its type is unknown");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-14 08:42:36 +08:00
|
|
|
Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame,
|
|
|
|
object_name,
|
|
|
|
(suppress_type_check ? NULL : &m_struct_vars->m_object_pointer_type));
|
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 (!object_ptr_var)
|
|
|
|
{
|
2010-12-14 06:46:15 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't find '%s' with appropriate type in scope", object_name.GetCString());
|
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
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
|
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
|
|
|
object_ptr_var,
|
2010-12-03 09:38:59 +08:00
|
|
|
NULL));
|
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 (!location_value.get())
|
|
|
|
{
|
2010-12-14 06:46:15 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't get the location for '%s'", object_name.GetCString());
|
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
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (location_value->GetValueType() == Value::eValueTypeLoadAddress)
|
|
|
|
{
|
|
|
|
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
2010-12-03 09:38:59 +08:00
|
|
|
uint32_t address_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
|
|
|
|
lldb::ByteOrder address_byte_order = exe_ctx.process->GetByteOrder();
|
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-12-03 09:38:59 +08:00
|
|
|
if (ClangASTType::GetClangTypeBitWidth(m_struct_vars->m_object_pointer_type.GetASTContext(),
|
|
|
|
m_struct_vars->m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
|
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-12-14 06:46:15 +08:00
|
|
|
err.SetErrorStringWithFormat("'%s' is not of an expected pointer size", object_name.GetCString());
|
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
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataBufferHeap data;
|
|
|
|
data.SetByteSize(address_byte_size);
|
|
|
|
Error read_error;
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (exe_ctx.process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
|
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-12-14 06:46:15 +08:00
|
|
|
err.SetErrorStringWithFormat("Coldn't read '%s' from the target: %s", object_name.GetCString(), read_error.AsCString());
|
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
|
|
|
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
|
|
|
|
{
|
2010-12-14 06:46:15 +08:00
|
|
|
err.SetErrorStringWithFormat("'%s' is not in memory; LLDB must be extended to handle registers", object_name.GetCString());
|
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
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::Dematerialize
|
|
|
|
(
|
2010-12-03 09:38:59 +08:00
|
|
|
ExecutionContext &exe_ctx,
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP &result_sp,
|
2010-10-16 06:48:33 +08:00
|
|
|
Error &err
|
|
|
|
)
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
return DoMaterialize(true, exe_ctx, &result_sp, err);
|
2010-12-03 09:38:59 +08:00
|
|
|
|
|
|
|
DidDematerialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::DidDematerialize()
|
|
|
|
{
|
|
|
|
if (m_material_vars.get())
|
|
|
|
{
|
|
|
|
if (m_material_vars->m_materialized_location)
|
|
|
|
{
|
|
|
|
//#define SINGLE_STEP_EXPRESSIONS
|
|
|
|
|
|
|
|
#ifndef SINGLE_STEP_EXPRESSIONS
|
|
|
|
m_material_vars->m_process->DeallocateMemory(m_material_vars->m_materialized_location);
|
|
|
|
#endif
|
|
|
|
m_material_vars->m_materialized_location = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DisableMaterialVars();
|
|
|
|
}
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
|
|
|
|
2010-07-24 06:19:18 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::DumpMaterializedStruct
|
|
|
|
(
|
2010-12-03 09:38:59 +08:00
|
|
|
ExecutionContext &exe_ctx,
|
2010-10-16 06:48:33 +08:00
|
|
|
Stream &s,
|
|
|
|
Error &err
|
|
|
|
)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
assert (m_material_vars.get());
|
|
|
|
|
|
|
|
if (!m_struct_vars->m_struct_laid_out)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
|
|
|
err.SetErrorString("Structure hasn't been laid out yet");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (!exe_ctx.process)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't find the process");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (!exe_ctx.target)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
|
|
|
err.SetErrorString("Couldn't find the target");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-07 18:00:20 +08:00
|
|
|
if (!m_material_vars->m_materialized_location)
|
|
|
|
{
|
|
|
|
err.SetErrorString("No materialized location");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
lldb::DataBufferSP data(new DataBufferHeap(m_struct_vars->m_struct_size, 0));
|
2010-07-24 06:19:18 +08:00
|
|
|
|
|
|
|
Error error;
|
2010-12-03 09:38:59 +08:00
|
|
|
if (exe_ctx.process->ReadMemory (m_material_vars->m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
DataExtractor extractor(data, exe_ctx.process->GetByteOrder(), exe_ctx.target->GetArchitecture().GetAddressByteSize());
|
2010-07-24 06:19:18 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
for (size_t member_idx = 0, num_members = m_struct_members.GetSize();
|
|
|
|
member_idx < num_members;
|
|
|
|
++member_idx)
|
2010-07-24 06:19:18 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(member_idx));
|
2010-07-24 06:19:18 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!member_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
s.Printf("[%s]\n", member_sp->GetName().GetCString());
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!member_sp->m_jit_vars.get())
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
extractor.Dump (&s, // stream
|
|
|
|
member_sp->m_jit_vars->m_offset, // offset
|
|
|
|
lldb::eFormatBytesWithASCII, // format
|
|
|
|
1, // byte size of individual entries
|
|
|
|
member_sp->m_jit_vars->m_size, // number of entries
|
|
|
|
16, // entries per line
|
|
|
|
m_material_vars->m_materialized_location + member_sp->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
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::DoMaterialize
|
|
|
|
(
|
|
|
|
bool dematerialize,
|
2010-12-03 09:38:59 +08:00
|
|
|
ExecutionContext &exe_ctx,
|
2010-12-14 10:59:59 +08:00
|
|
|
lldb::ClangExpressionVariableSP *result_sp_ptr,
|
2010-10-16 06:48:33 +08:00
|
|
|
Error &err
|
|
|
|
)
|
2010-07-16 08:09:46 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
if (result_sp_ptr)
|
|
|
|
result_sp_ptr->reset();
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-08-12 09:56:52 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (!m_struct_vars->m_struct_laid_out)
|
2010-07-16 08:09:46 +08:00
|
|
|
{
|
|
|
|
err.SetErrorString("Structure hasn't been laid out yet");
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (!exe_ctx.frame)
|
2010-07-24 09:37:44 +08:00
|
|
|
{
|
|
|
|
err.SetErrorString("Received null execution frame");
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangPersistentVariables &persistent_vars = exe_ctx.target->GetPersistentVariables();
|
2010-12-03 09:38:59 +08:00
|
|
|
|
|
|
|
if (!m_struct_vars->m_struct_size)
|
2010-09-14 05:34:21 +08:00
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Not bothering to allocate a struct because no arguments are needed");
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_material_vars->m_allocated_area = NULL;
|
2010-09-14 05:34:21 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
const SymbolContext &sym_ctx(exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything));
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
if (!dematerialize)
|
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
if (m_material_vars->m_materialized_location)
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
exe_ctx.process->DeallocateMemory(m_material_vars->m_materialized_location);
|
|
|
|
m_material_vars->m_materialized_location = 0;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
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-12-03 09:38:59 +08:00
|
|
|
lldb::addr_t mem = exe_ctx.process->AllocateMemory(m_struct_vars->m_struct_alignment + m_struct_vars->m_struct_size,
|
|
|
|
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
|
|
|
err);
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
if (mem == LLDB_INVALID_ADDRESS)
|
|
|
|
return false;
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_material_vars->m_allocated_area = mem;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_material_vars->m_materialized_location = m_material_vars->m_allocated_area;
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (m_material_vars->m_materialized_location % m_struct_vars->m_struct_alignment)
|
|
|
|
m_material_vars->m_materialized_location += (m_struct_vars->m_struct_alignment - (m_material_vars->m_materialized_location % m_struct_vars->m_struct_alignment));
|
2010-07-16 08:09:46 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
for (uint64_t member_index = 0, num_members = m_struct_members.GetSize();
|
2010-08-24 07:09:38 +08:00
|
|
|
member_index < num_members;
|
|
|
|
++member_index)
|
2010-07-16 08:09:46 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(member_index));
|
2010-12-01 09:29:06 +08:00
|
|
|
|
2011-01-10 05:07:35 +08:00
|
|
|
if (m_found_entities.ContainsVariable (member_sp))
|
2010-07-17 08:43:37 +08:00
|
|
|
{
|
2011-01-10 05:07:35 +08:00
|
|
|
RegisterInfo *reg_info = member_sp->GetRegisterInfo ();
|
2010-12-14 10:59:59 +08:00
|
|
|
if (reg_info)
|
2010-11-30 08:27:43 +08:00
|
|
|
{
|
|
|
|
// This is a register variable
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
|
2010-11-30 08:27:43 +08:00
|
|
|
|
|
|
|
if (!reg_ctx)
|
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!DoMaterializeOneRegister (dematerialize,
|
|
|
|
exe_ctx,
|
|
|
|
*reg_ctx,
|
|
|
|
*reg_info,
|
|
|
|
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
|
|
|
|
err))
|
2010-11-30 08:27:43 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!member_sp->m_jit_vars.get())
|
2010-11-30 08:27:43 +08:00
|
|
|
return false;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!DoMaterializeOneVariable (dematerialize,
|
|
|
|
exe_ctx,
|
2011-01-13 16:53:35 +08:00
|
|
|
sym_ctx,
|
|
|
|
member_sp,
|
2010-12-14 10:59:59 +08:00
|
|
|
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
|
|
|
|
err))
|
2010-11-30 08:27:43 +08:00
|
|
|
return false;
|
|
|
|
}
|
2010-08-24 07:09:38 +08:00
|
|
|
}
|
2011-01-10 05:07:35 +08:00
|
|
|
else
|
2010-08-24 07:09:38 +08:00
|
|
|
{
|
2011-01-10 05:07:35 +08:00
|
|
|
// No need to look for presistent variables if the name doesn't start
|
|
|
|
// with with a '$' character...
|
|
|
|
if (member_sp->GetName().AsCString ("!")[0] == '$' && persistent_vars.ContainsVariable(member_sp))
|
2010-08-31 06:17:16 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
bool keep_this_in_memory = false;
|
|
|
|
|
2011-01-10 05:07:35 +08:00
|
|
|
if (member_sp->GetName() == m_struct_vars->m_result_name)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Found result member in the struct");
|
2011-01-13 16:53:35 +08:00
|
|
|
|
2011-01-10 05:07:35 +08:00
|
|
|
if (result_sp_ptr)
|
|
|
|
*result_sp_ptr = member_sp;
|
2011-01-13 16:53:35 +08:00
|
|
|
|
|
|
|
keep_this_in_memory = m_keep_result_in_memory;
|
2011-01-10 05:07:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!DoMaterializeOnePersistentVariable (dematerialize,
|
2011-01-13 16:53:35 +08:00
|
|
|
exe_ctx,
|
2011-01-10 05:07:35 +08:00
|
|
|
member_sp,
|
|
|
|
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
|
|
|
|
err))
|
|
|
|
return false;
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
2011-01-10 05:07:35 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Unexpected variable %s", member_sp->GetName().GetCString());
|
2010-08-24 07:09:38 +08:00
|
|
|
return false;
|
2011-01-10 05:07:35 +08:00
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
static bool WriteAddressInto
|
|
|
|
(
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
lldb::addr_t target,
|
|
|
|
lldb::addr_t address,
|
|
|
|
Error &err
|
|
|
|
)
|
|
|
|
{
|
|
|
|
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
|
|
|
|
|
|
|
|
StreamString str (0 | Stream::eBinary,
|
|
|
|
pointer_byte_size,
|
|
|
|
exe_ctx.process->GetByteOrder());
|
|
|
|
|
|
|
|
switch (pointer_byte_size)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
assert(!"Unhandled byte size");
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
uint32_t address32 = address & 0xffffffffll;
|
|
|
|
str.PutRawBytes(&address32, sizeof(address32), eByteOrderHost, eByteOrderInvalid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
{
|
|
|
|
uint64_t address64 = address;
|
|
|
|
str.PutRawBytes(&address64, sizeof(address64), eByteOrderHost, eByteOrderInvalid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (exe_ctx.process->WriteMemory (target, str.GetData(), pointer_byte_size, err) == pointer_byte_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static lldb::addr_t ReadAddressFrom
|
|
|
|
(
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
lldb::addr_t source,
|
|
|
|
Error &err
|
|
|
|
)
|
|
|
|
{
|
|
|
|
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
|
|
|
|
|
|
|
|
DataBufferHeap *buf = new DataBufferHeap(pointer_byte_size, 0);
|
|
|
|
DataBufferSP buf_sp(buf);
|
|
|
|
|
|
|
|
if (exe_ctx.process->ReadMemory (source, buf->GetBytes(), pointer_byte_size, err) != pointer_byte_size)
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
|
|
|
|
DataExtractor extractor (buf_sp, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
|
|
|
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
|
|
|
return (lldb::addr_t)extractor.GetPointer(&offset);
|
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|
|
|
(
|
|
|
|
bool dematerialize,
|
|
|
|
ExecutionContext &exe_ctx,
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP &var_sp,
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb::addr_t addr,
|
|
|
|
Error &err
|
|
|
|
)
|
2010-12-03 09:38:59 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (!var_sp)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
err.SetErrorString("Invalid persistent variable");
|
2010-08-11 11:57:18 +08:00
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
const size_t pvar_byte_size = var_sp->GetByteSize();
|
2010-08-20 09:02:30 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
uint8_t *pvar_data = var_sp->GetValueBytes();
|
|
|
|
if (pvar_data == NULL)
|
2010-08-20 09:02:30 +08:00
|
|
|
return false;
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
Error error;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
lldb::addr_t mem; // The address of a spare memory area used to hold the persistent variable.
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
if (dematerialize)
|
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Dematerializing persistent variable with flags 0x%hx", var_sp->m_flags);
|
|
|
|
|
|
|
|
if ((var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
|
|
|
|
(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
|
|
|
|
{
|
|
|
|
// Get the location of the target out of the struct.
|
|
|
|
|
|
|
|
Error read_error;
|
|
|
|
mem = ReadAddressFrom(exe_ctx, addr, read_error);
|
|
|
|
|
|
|
|
if (mem == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read address of %s from struct: %s", var_sp->GetName().GetCString(), error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
|
|
|
|
!var_sp->m_live_sp)
|
|
|
|
{
|
|
|
|
// If the reference comes from the program, then the ClangExpressionVariable's
|
|
|
|
// live variable data hasn't been set up yet. Do this now.
|
|
|
|
|
|
|
|
var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
|
|
|
|
var_sp->GetTypeFromUser().GetOpaqueQualType(),
|
|
|
|
var_sp->GetName(),
|
|
|
|
mem,
|
|
|
|
lldb::eAddressTypeLoad,
|
|
|
|
pvar_byte_size));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!var_sp->m_live_sp)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", var_sp->GetName().GetCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_sp->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", var_sp->GetName().GetCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-14 05:23:32 +08:00
|
|
|
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
|
|
|
|
var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
|
2011-01-13 16:53:35 +08:00
|
|
|
{
|
|
|
|
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
|
|
|
|
|
|
|
|
// Read the contents of the spare memory area
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Read");
|
|
|
|
|
|
|
|
var_sp->ValueUpdated ();
|
|
|
|
if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
|
|
|
|
!(var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
|
|
|
|
{
|
|
|
|
if (m_keep_result_in_memory)
|
|
|
|
{
|
|
|
|
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
|
|
|
|
|
|
|
|
if (!err.Success())
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", var_sp->GetName().GetCString(), deallocate_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
|
2010-08-11 11:57:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Materializing persistent variable with flags 0x%hx", var_sp->m_flags);
|
|
|
|
|
|
|
|
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
|
|
|
|
{
|
|
|
|
// Allocate a spare memory area to store the persistent variable's contents.
|
|
|
|
|
|
|
|
Error allocate_error;
|
|
|
|
|
|
|
|
mem = exe_ctx.process->AllocateMemory(pvar_byte_size,
|
|
|
|
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
|
|
|
allocate_error);
|
|
|
|
|
|
|
|
if (mem == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", var_sp->GetName().GetCString(), allocate_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Allocated %s (0x%llx) sucessfully", var_sp->GetName().GetCString(), mem);
|
|
|
|
|
|
|
|
// Put the location of the spare memory into the live data of the ValueObject.
|
|
|
|
|
|
|
|
var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
|
|
|
|
var_sp->GetTypeFromUser().GetOpaqueQualType(),
|
|
|
|
var_sp->GetName(),
|
|
|
|
mem,
|
|
|
|
lldb::eAddressTypeLoad,
|
|
|
|
pvar_byte_size));
|
|
|
|
|
|
|
|
// Clear the flag if the variable will never be deallocated.
|
|
|
|
|
|
|
|
if (var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
|
|
|
|
var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
|
|
|
|
|
|
|
|
// Write the contents of the variable to the area.
|
|
|
|
|
|
|
|
if (exe_ctx.process->WriteMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
|
|
|
|
var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
|
|
|
|
{
|
|
|
|
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
|
|
|
|
|
|
|
|
// Now write the location of the area into the struct.
|
|
|
|
|
|
|
|
Error write_error;
|
|
|
|
if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
|
|
|
|
}
|
|
|
|
else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
|
2010-08-11 11:57:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
bool
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::DoMaterializeOneVariable
|
|
|
|
(
|
|
|
|
bool dematerialize,
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
const SymbolContext &sym_ctx,
|
2011-01-13 16:53:35 +08:00
|
|
|
ClangExpressionVariableSP &expr_var,
|
2010-10-16 06:48:33 +08:00
|
|
|
lldb::addr_t addr,
|
|
|
|
Error &err
|
|
|
|
)
|
2010-07-21 07:31:16 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-21 07:31:16 +08:00
|
|
|
|
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;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
// Vital information about the value
|
|
|
|
|
|
|
|
const ConstString &name(expr_var->GetName());
|
|
|
|
TypeFromUser type(expr_var->GetTypeFromUser());
|
|
|
|
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type);
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
if (!var)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't find %s with appropriate type", name.GetCString());
|
2010-07-21 07:31:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-23 08:16:21 +08:00
|
|
|
if (log)
|
2010-10-16 06:48:33 +08:00
|
|
|
log->Printf("%s %s with type %p", (dematerialize ? "Dematerializing" : "Materializing"), name.GetCString(), type.GetOpaqueQualType());
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
|
|
|
|
var,
|
2010-12-03 09:38:59 +08:00
|
|
|
NULL));
|
2010-07-21 07:31:16 +08:00
|
|
|
|
|
|
|
if (!location_value.get())
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't get value for %s", name.GetCString());
|
2010-07-21 07:31:16 +08:00
|
|
|
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
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
size_t value_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
|
|
|
|
size_t value_byte_size = value_bit_size % 8 ? ((value_bit_size + 8) / 8) : (value_bit_size / 8);
|
2010-10-06 04:18:48 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s has a value of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
|
2010-10-06 04:18:48 +08:00
|
|
|
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
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
if (!dematerialize)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
|
|
|
|
if (!WriteAddressInto(exe_ctx,
|
|
|
|
addr,
|
|
|
|
value_addr,
|
|
|
|
error))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
2010-10-06 04:18:48 +08:00
|
|
|
}
|
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-11-13 11:52:47 +08:00
|
|
|
if (location_value->GetContextType() != Value::eContextTypeRegisterInfo)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
|
|
|
StreamString ss;
|
|
|
|
location_value->Dump(&ss);
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
lldb::addr_t mem; // The address of a spare memory area aused to hold the variable.
|
|
|
|
|
2010-10-06 04:18:48 +08:00
|
|
|
lldb::RegisterInfo *register_info = location_value->GetRegisterInfo();
|
|
|
|
|
|
|
|
if (!register_info)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't get the register information for %s", name.GetCString());
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterContext *register_context = exe_ctx.GetRegisterContext();
|
|
|
|
|
|
|
|
if (!register_context)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_number = register_info->kinds[lldb::eRegisterKindLLDB];
|
|
|
|
uint32_t register_byte_size = register_info->byte_size;
|
|
|
|
|
|
|
|
if (dematerialize)
|
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
// Get the location of the spare memory area out of the variable's live data.
|
|
|
|
|
|
|
|
if (!expr_var->m_live_sp)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", name.GetCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (expr_var->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", name.GetCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mem = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
|
|
|
|
|
2010-10-06 04:18:48 +08:00
|
|
|
// 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]
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
if (value_byte_size > register_byte_size)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_offset;
|
|
|
|
|
|
|
|
switch (exe_ctx.process->GetByteOrder())
|
|
|
|
{
|
|
|
|
default:
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name.GetCString());
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
case lldb::eByteOrderLittle:
|
|
|
|
register_offset = 0;
|
|
|
|
break;
|
|
|
|
case lldb::eByteOrderBig:
|
2011-01-13 16:53:35 +08:00
|
|
|
register_offset = register_byte_size - value_byte_size;
|
2010-10-06 04:18:48 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataBufferHeap register_data (register_byte_size, 0);
|
|
|
|
|
|
|
|
Error error;
|
2011-01-13 16:53:35 +08:00
|
|
|
if (exe_ctx.process->ReadMemory (mem, register_data.GetBytes() + register_offset, value_byte_size, error) != value_byte_size)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
|
2010-10-06 04:18:48 +08:00
|
|
|
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))
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-13 16:53:35 +08:00
|
|
|
|
|
|
|
// Deallocate the spare area and clear the variable's live data.
|
|
|
|
|
|
|
|
Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
|
|
|
|
|
|
|
|
if (!deallocate_error.Success())
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't deallocate spare memory area for %s: %s", name.GetCString(), deallocate_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
expr_var->m_live_sp.reset();
|
2010-10-06 04:18:48 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
// Allocate a spare memory area to place the register's contents into. This memory area will be pointed to by the slot in the
|
|
|
|
// struct.
|
|
|
|
|
|
|
|
Error allocate_error;
|
|
|
|
|
|
|
|
mem = exe_ctx.process->AllocateMemory(value_byte_size,
|
|
|
|
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
|
|
|
allocate_error);
|
|
|
|
|
|
|
|
if (mem == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put the location of the spare memory into the live data of the ValueObject.
|
|
|
|
|
|
|
|
expr_var->m_live_sp.reset(new lldb_private::ValueObjectConstResult(type.GetASTContext(),
|
|
|
|
type.GetOpaqueQualType(),
|
|
|
|
name,
|
|
|
|
mem,
|
|
|
|
lldb::eAddressTypeLoad,
|
|
|
|
value_byte_size));
|
|
|
|
|
|
|
|
// Now write the location of the area into the struct.
|
|
|
|
|
|
|
|
Error write_error;
|
|
|
|
if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-06 04:18:48 +08:00
|
|
|
// 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
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
if (value_byte_size > register_byte_size)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_offset;
|
|
|
|
|
|
|
|
switch (exe_ctx.process->GetByteOrder())
|
|
|
|
{
|
|
|
|
default:
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name.GetCString());
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
case lldb::eByteOrderLittle:
|
|
|
|
register_offset = 0;
|
|
|
|
break;
|
|
|
|
case lldb::eByteOrderBig:
|
2011-01-13 16:53:35 +08:00
|
|
|
register_offset = register_byte_size - value_byte_size;
|
2010-10-06 04:18:48 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor register_extractor;
|
|
|
|
|
|
|
|
if (!register_context->ReadRegisterBytes(register_number, register_extractor))
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
const void *register_data = register_extractor.GetData(®ister_offset, value_byte_size);
|
2010-10-06 04:18:48 +08:00
|
|
|
|
|
|
|
if (!register_data)
|
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
err.SetErrorStringWithFormat("Read but couldn't extract data for %s from %s", name.GetCString(), register_info->name);
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
if (exe_ctx.process->WriteMemory (mem, register_data, value_byte_size, write_error) != value_byte_size)
|
2010-10-06 04:18:48 +08:00
|
|
|
{
|
2011-01-13 16:53:35 +08:00
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
|
2010-10-06 04:18:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2010-07-21 07:31:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-07-16 08:09:46 +08:00
|
|
|
}
|
|
|
|
|
2010-11-30 08:27:43 +08:00
|
|
|
bool
|
|
|
|
ClangExpressionDeclMap::DoMaterializeOneRegister
|
|
|
|
(
|
|
|
|
bool dematerialize,
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
RegisterContext ®_ctx,
|
|
|
|
const lldb::RegisterInfo ®_info,
|
|
|
|
lldb::addr_t addr,
|
|
|
|
Error &err
|
|
|
|
)
|
|
|
|
{
|
|
|
|
uint32_t register_number = reg_info.kinds[lldb::eRegisterKindLLDB];
|
|
|
|
uint32_t register_byte_size = reg_info.byte_size;
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
|
|
|
|
if (dematerialize)
|
|
|
|
{
|
|
|
|
DataBufferHeap register_data (register_byte_size, 0);
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes(), register_byte_size, error) != register_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", reg_info.name, error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataExtractor register_extractor (register_data.GetBytes(), register_byte_size, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
|
|
|
|
|
|
|
|
if (!reg_ctx.WriteRegisterBytes(register_number, register_extractor, 0))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DataExtractor register_extractor;
|
|
|
|
|
|
|
|
if (!reg_ctx.ReadRegisterBytes(register_number, register_extractor))
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t register_offset = 0;
|
|
|
|
|
|
|
|
const void *register_data = register_extractor.GetData(®ister_offset, register_byte_size);
|
|
|
|
|
|
|
|
if (!register_data)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat("Read but couldn't extract data for %s", reg_info.name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
if (exe_ctx.process->WriteMemory (addr, register_data, register_byte_size, error) != register_byte_size)
|
|
|
|
{
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-09-15 05:59:34 +08:00
|
|
|
Variable *
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::FindVariableInScope
|
|
|
|
(
|
|
|
|
StackFrame &frame,
|
|
|
|
const ConstString &name,
|
|
|
|
TypeFromUser *type
|
|
|
|
)
|
2010-12-03 09:38:59 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-09-15 05:59:34 +08:00
|
|
|
|
|
|
|
VariableList *var_list = frame.GetVariableList(true);
|
|
|
|
|
2010-10-15 06:52:14 +08:00
|
|
|
if (!var_list)
|
|
|
|
return NULL;
|
|
|
|
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
lldb::VariableSP var_sp (var_list->FindVariable(name));
|
|
|
|
|
|
|
|
const bool append = true;
|
|
|
|
const uint32_t max_matches = 1;
|
|
|
|
if (!var_sp)
|
2010-09-15 05:59:34 +08:00
|
|
|
{
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
// Look for globals elsewhere in the module for the frame
|
2010-12-03 09:38:59 +08:00
|
|
|
ModuleSP module_sp (frame.GetSymbolContext(eSymbolContextModule).module_sp);
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
if (module_sp)
|
|
|
|
{
|
|
|
|
VariableList module_globals;
|
|
|
|
if (module_sp->FindGlobalVariables (name, append, max_matches, module_globals))
|
|
|
|
var_sp = module_globals.GetVariableAtIndex (0);
|
|
|
|
}
|
2010-09-15 05:59:34 +08:00
|
|
|
}
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
|
|
|
|
if (!var_sp)
|
2010-09-15 05:59:34 +08:00
|
|
|
{
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
// Look for globals elsewhere in the program (all images)
|
2010-12-03 09:38:59 +08:00
|
|
|
TargetSP target_sp (frame.GetSymbolContext(eSymbolContextTarget).target_sp);
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
if (target_sp)
|
|
|
|
{
|
|
|
|
VariableList program_globals;
|
|
|
|
if (target_sp->GetImages().FindGlobalVariables (name, append, max_matches, program_globals))
|
|
|
|
var_sp = program_globals.GetVariableAtIndex (0);
|
|
|
|
}
|
2010-09-15 05:59:34 +08:00
|
|
|
}
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
|
|
|
|
if (var_sp && type)
|
|
|
|
{
|
|
|
|
if (type->GetASTContext() == var_sp->GetType()->GetClangAST())
|
|
|
|
{
|
|
|
|
if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var_sp->GetType()->GetClangType()))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->PutCString("Skipping a candidate variable because of different AST contexts");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return var_sp.get();
|
2010-09-15 05:59:34 +08:00
|
|
|
}
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
// Interface for ClangASTSource
|
|
|
|
void
|
2010-11-10 07:46:37 +08:00
|
|
|
ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_struct_vars.get());
|
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP 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-16 06:48:33 +08:00
|
|
|
log->Printf("Hunting for a definition for '%s'", name.GetCString());
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
// Back out in all cases where we're not fully initialized
|
2010-12-03 09:38:59 +08:00
|
|
|
if (m_parser_vars->m_exe_ctx->frame == NULL)
|
2010-06-09 00:52:24 +08:00
|
|
|
return;
|
2010-11-20 04:20:02 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (m_parser_vars->m_ignore_lookups)
|
2010-11-20 04:20:02 +08:00
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("Ignoring a query during an import");
|
|
|
|
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
|
|
|
|
2010-11-10 07:46:37 +08:00
|
|
|
SymbolContextList sc_list;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
const char *name_unique_cstr = name.GetCString();
|
|
|
|
|
|
|
|
if (name_unique_cstr == NULL)
|
|
|
|
return;
|
|
|
|
|
2010-10-16 06:48:33 +08:00
|
|
|
// Only look for functions by name out in our symbols if the function
|
|
|
|
// doesn't start with our phony prefix of '$'
|
Just like functions can have a basename and a mangled/demangled name, variable
can too. So now the lldb_private::Variable class has support for this.
Variables now have support for having a basename ("i"), and a mangled name
("_ZN12_GLOBAL__N_11iE"), and a demangled name ("(anonymous namespace)::i").
Nowwhen searching for a variable by name, users might enter the fully qualified
name, or just the basename. So new test functions were added to the Variable
and Mangled classes as:
bool NameMatches (const ConstString &name);
bool NameMatches (const RegularExpression ®ex);
I also modified "ClangExpressionDeclMap::FindVariableInScope" to also search
for global variables that are not in the current file scope by first starting
with the current module, then moving on to all modules.
Fixed an issue in the DWARF parser that could cause a varaible to get parsed
more than once. Now, once we have parsed a VariableSP for a DIE, we cache
the result even if a variable wasn't made so we don't do any re-parsing. Some
DW_TAG_variable DIEs don't have locations, or are missing vital info that
stops a debugger from being able to display anything for it, we parse a NULL
variable shared pointer for these DIEs so we don't keep trying to reparse it.
llvm-svn: 119085
2010-11-15 06:13:40 +08:00
|
|
|
if (name_unique_cstr[0] != '$')
|
2010-07-27 08:55:47 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
Variable *var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name);
|
2010-10-16 06:48:33 +08:00
|
|
|
|
|
|
|
// If we found a variable in scope, no need to pull up function names
|
|
|
|
if (var != NULL)
|
2010-09-08 05:49:41 +08:00
|
|
|
{
|
2010-10-16 06:48:33 +08:00
|
|
|
AddOneVariable(context, var);
|
2010-09-08 05:49:41 +08:00
|
|
|
}
|
2010-10-16 06:48:33 +08:00
|
|
|
else
|
2010-09-08 05:49:41 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
m_parser_vars->m_sym_ctx.FindFunctionsByName (name, false, sc_list);
|
2010-10-16 06:48:33 +08:00
|
|
|
|
|
|
|
bool found_specific = false;
|
|
|
|
Symbol *generic_symbol = NULL;
|
|
|
|
Symbol *non_extern_symbol = NULL;
|
|
|
|
|
2010-11-10 07:46:37 +08:00
|
|
|
for (uint32_t index = 0, num_indices = sc_list.GetSize();
|
2010-10-16 06:48:33 +08:00
|
|
|
index < num_indices;
|
|
|
|
++index)
|
|
|
|
{
|
|
|
|
SymbolContext sym_ctx;
|
2010-11-10 07:46:37 +08:00
|
|
|
sc_list.GetContextAtIndex(index, sym_ctx);
|
2010-10-16 06:48:33 +08:00
|
|
|
|
|
|
|
if (sym_ctx.function)
|
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
else if (sym_ctx.symbol)
|
|
|
|
{
|
|
|
|
if (sym_ctx.symbol->IsExternal())
|
|
|
|
generic_symbol = sym_ctx.symbol;
|
|
|
|
else
|
|
|
|
non_extern_symbol = sym_ctx.symbol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found_specific)
|
|
|
|
{
|
|
|
|
if (generic_symbol)
|
|
|
|
AddOneFunction(context, NULL, generic_symbol);
|
|
|
|
else if (non_extern_symbol)
|
|
|
|
AddOneFunction(context, NULL, non_extern_symbol);
|
|
|
|
}
|
2010-11-13 11:52:47 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
ClangNamespaceDecl namespace_decl (m_parser_vars->m_sym_ctx.FindNamespace(name));
|
2010-11-13 11:52:47 +08:00
|
|
|
if (namespace_decl)
|
|
|
|
{
|
2010-11-13 12:18:24 +08:00
|
|
|
clang::NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl);
|
|
|
|
if (clang_namespace_decl)
|
|
|
|
clang_namespace_decl->setHasExternalLexicalStorage();
|
2010-11-13 11:52:47 +08:00
|
|
|
}
|
2010-09-08 05:49:41 +08:00
|
|
|
}
|
2010-07-27 08:55:47 +08:00
|
|
|
}
|
2010-10-16 06:48:33 +08:00
|
|
|
else
|
2010-10-06 08:10:07 +08:00
|
|
|
{
|
2010-11-09 12:42:43 +08:00
|
|
|
static ConstString g_lldb_class_name ("$__lldb_class");
|
|
|
|
if (name == g_lldb_class_name)
|
|
|
|
{
|
|
|
|
// Clang is looking for the type of "this"
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
|
2010-11-09 12:42:43 +08:00
|
|
|
|
|
|
|
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-11-16 10:10:54 +08:00
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
log->PutCString ("Type for \"this\" is: ");
|
|
|
|
StreamString strm;
|
|
|
|
this_type->Dump(&strm, true);
|
|
|
|
log->PutCString (strm.GetData());
|
|
|
|
}
|
|
|
|
|
2010-11-09 12:42:43 +08:00
|
|
|
TypeFromUser this_user_type(this_type->GetClangType(),
|
|
|
|
this_type->GetClangAST());
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_struct_vars->m_object_pointer_type = this_user_type;
|
2010-11-09 12:42:43 +08:00
|
|
|
|
|
|
|
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());
|
|
|
|
|
2010-12-14 06:46:15 +08:00
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
StreamString type_stream;
|
|
|
|
class_user_type.DumpTypeCode(&type_stream);
|
|
|
|
type_stream.Flush();
|
|
|
|
log->Printf("Adding type for $__lldb_class: %s", type_stream.GetString().c_str());
|
|
|
|
}
|
|
|
|
|
2010-11-09 12:42:43 +08:00
|
|
|
AddOneType(context, class_user_type, true);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-14 06:46:15 +08:00
|
|
|
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"
|
|
|
|
|
|
|
|
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
|
|
|
|
|
|
|
|
if (!vars)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
|
|
|
|
|
|
|
|
if (!self_var)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Type *self_type = self_var->GetType();
|
|
|
|
|
|
|
|
if (!self_type)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TypeFromUser self_user_type(self_type->GetClangType(),
|
|
|
|
self_type->GetClangAST());
|
|
|
|
|
|
|
|
m_struct_vars->m_object_pointer_type = self_user_type;
|
|
|
|
|
|
|
|
void *pointer_target_type;
|
|
|
|
|
|
|
|
if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(),
|
|
|
|
&pointer_target_type))
|
|
|
|
return;
|
|
|
|
|
|
|
|
TypeFromUser class_user_type(pointer_target_type,
|
|
|
|
self_type->GetClangAST());
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
StreamString type_stream;
|
|
|
|
class_user_type.DumpTypeCode(&type_stream);
|
|
|
|
type_stream.Flush();
|
|
|
|
log->Printf("Adding type for $__lldb_objc_class: %s", type_stream.GetString().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
AddOneType(context, class_user_type, false);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2010-12-14 10:59:59 +08:00
|
|
|
|
|
|
|
ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
|
2010-10-06 08:10:07 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
if (pvar_sp)
|
2010-11-30 08:27:43 +08:00
|
|
|
{
|
2010-12-14 10:59:59 +08:00
|
|
|
AddOneVariable(context, pvar_sp);
|
2010-11-30 08:27:43 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *reg_name(&name.GetCString()[1]);
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
if (m_parser_vars->m_exe_ctx->GetRegisterContext())
|
2010-11-30 08:27:43 +08:00
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
const lldb::RegisterInfo *reg_info(m_parser_vars->m_exe_ctx->GetRegisterContext()->GetRegisterInfoByName(reg_name));
|
2010-11-30 08:27:43 +08:00
|
|
|
|
|
|
|
if (reg_info)
|
|
|
|
AddOneRegister(context, reg_info);
|
|
|
|
}
|
2010-10-16 06:48:33 +08:00
|
|
|
}
|
2010-08-11 11:57:18 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
lldb::TypeSP type_sp (m_parser_vars->m_sym_ctx.FindTypeByName (name));
|
2010-09-28 07:54:58 +08:00
|
|
|
|
2010-11-20 04:20:02 +08:00
|
|
|
if (type_sp)
|
|
|
|
{
|
|
|
|
if (log)
|
2010-09-28 07:54:58 +08:00
|
|
|
{
|
2010-11-20 04:20:02 +08:00
|
|
|
log->Printf ("Matching type found for \"%s\": ", name.GetCString());
|
|
|
|
StreamString strm;
|
|
|
|
type_sp->Dump(&strm, true);
|
|
|
|
log->PutCString (strm.GetData());
|
|
|
|
}
|
2010-11-16 10:10:54 +08:00
|
|
|
|
2010-11-20 04:20:02 +08:00
|
|
|
TypeFromUser user_type(type_sp->GetClangType(),
|
2010-11-16 10:10:54 +08:00
|
|
|
type_sp->GetClangAST());
|
2010-09-28 07:54:58 +08:00
|
|
|
|
2010-11-20 04:20:02 +08:00
|
|
|
AddOneType(context, user_type, false);
|
2010-09-28 07:54:58 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2010-07-17 08:43:37 +08:00
|
|
|
|
|
|
|
Value *
|
2010-10-16 06:48:33 +08:00
|
|
|
ClangExpressionDeclMap::GetVariableValue
|
|
|
|
(
|
|
|
|
ExecutionContext &exe_ctx,
|
|
|
|
Variable *var,
|
|
|
|
clang::ASTContext *parser_ast_context,
|
|
|
|
TypeFromUser *user_type,
|
|
|
|
TypeFromParser *parser_type
|
|
|
|
)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-06-23 08:47:48 +08:00
|
|
|
|
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-11-20 09:28:30 +08:00
|
|
|
if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, NULL, 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)
|
|
|
|
{
|
2010-11-20 04:20:02 +08:00
|
|
|
type_to_use = GuardedCopyType(parser_ast_context, var_ast_context, var_opaque_type);
|
2010-07-21 07:31:16 +08:00
|
|
|
|
2010-11-20 10:19:29 +08:00
|
|
|
if (!type_to_use)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("Couldn't copy a variable's type into the parser's AST context");
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
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-11-13 11:52:47 +08:00
|
|
|
var_location.get()->SetContext(Value::eContextTypeClangType, 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-12-03 09:38:59 +08:00
|
|
|
lldb::addr_t load_addr = so_addr.GetLoadAddress(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
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-07-21 07:31:16 +08:00
|
|
|
TypeFromUser ut;
|
|
|
|
TypeFromParser pt;
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
Value *var_location = GetVariableValue (*m_parser_vars->m_exe_ctx,
|
2010-10-16 06:48:33 +08:00
|
|
|
var,
|
|
|
|
context.GetASTContext(),
|
|
|
|
&ut,
|
|
|
|
&pt);
|
2010-07-17 08:43:37 +08:00
|
|
|
|
2010-11-20 10:19:29 +08:00
|
|
|
if (!var_location)
|
|
|
|
return;
|
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType()));
|
2010-10-16 06:48:33 +08:00
|
|
|
std::string decl_name(context.m_decl_name.getAsString());
|
2010-12-14 10:59:59 +08:00
|
|
|
ConstString entity_name(decl_name.c_str());
|
|
|
|
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (entity_name,
|
|
|
|
ut,
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetByteOrder(),
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
|
|
|
|
assert (entity.get());
|
|
|
|
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-10-16 06:48:33 +08:00
|
|
|
{
|
2010-11-02 07:22:47 +08:00
|
|
|
std::string var_decl_print_string;
|
|
|
|
llvm::raw_string_ostream var_decl_print_stream(var_decl_print_string);
|
|
|
|
var_decl->print(var_decl_print_stream);
|
|
|
|
var_decl_print_stream.flush();
|
|
|
|
|
|
|
|
log->Printf("Found variable %s, returned %s", decl_name.c_str(), var_decl_print_string.c_str());
|
2010-10-16 06:48:33 +08:00
|
|
|
}
|
2010-06-23 07:46:24 +08:00
|
|
|
}
|
|
|
|
|
2010-08-11 11:57:18 +08:00
|
|
|
void
|
|
|
|
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP &pvar_sp)
|
2010-08-11 11:57:18 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-08-31 06:17:16 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
TypeFromUser user_type (pvar_sp->GetTypeFromUser());
|
2010-08-11 11:57:18 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
TypeFromParser parser_type (GuardedCopyType(context.GetASTContext(),
|
|
|
|
user_type.GetASTContext(),
|
|
|
|
user_type.GetOpaqueQualType()),
|
|
|
|
context.GetASTContext());
|
2010-08-11 11:57:18 +08:00
|
|
|
|
2011-01-13 16:53:35 +08:00
|
|
|
NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(parser_type.GetASTContext(), parser_type.GetOpaqueQualType()));
|
2010-08-24 07:09:38 +08:00
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
pvar_sp->EnableParserVars();
|
|
|
|
pvar_sp->m_parser_vars->m_parser_type = parser_type;
|
|
|
|
pvar_sp->m_parser_vars->m_named_decl = var_decl;
|
|
|
|
pvar_sp->m_parser_vars->m_llvm_value = NULL;
|
|
|
|
pvar_sp->m_parser_vars->m_lldb_value = NULL;
|
2010-08-31 06:17:16 +08:00
|
|
|
|
|
|
|
if (log)
|
2010-11-02 07:22:47 +08:00
|
|
|
{
|
|
|
|
std::string var_decl_print_string;
|
|
|
|
llvm::raw_string_ostream var_decl_print_stream(var_decl_print_string);
|
|
|
|
var_decl->print(var_decl_print_stream);
|
|
|
|
var_decl_print_stream.flush();
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
log->Printf("Added pvar %s, returned %s", pvar_sp->GetName().GetCString(), var_decl_print_string.c_str());
|
2010-11-02 07:22:47 +08:00
|
|
|
}
|
2010-08-11 11:57:18 +08:00
|
|
|
}
|
|
|
|
|
2010-11-30 08:27:43 +08:00
|
|
|
void
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
|
|
|
|
const RegisterInfo *reg_info)
|
2010-11-30 08:27:43 +08:00
|
|
|
{
|
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
|
|
|
void *ast_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(context.GetASTContext(),
|
|
|
|
reg_info->encoding,
|
|
|
|
reg_info->byte_size * 8);
|
|
|
|
|
|
|
|
if (!ast_type)
|
|
|
|
{
|
|
|
|
log->Printf("Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
TypeFromParser parser_type (ast_type,
|
|
|
|
context.GetASTContext());
|
2010-11-30 08:27:43 +08:00
|
|
|
|
|
|
|
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->process->GetByteOrder(),
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
|
|
|
|
assert (entity.get());
|
2010-11-30 08:27:43 +08:00
|
|
|
std::string decl_name(context.m_decl_name.getAsString());
|
2010-12-14 10:59:59 +08:00
|
|
|
entity->SetName (ConstString (decl_name.c_str()));
|
|
|
|
entity->SetRegisterInfo (reg_info);
|
|
|
|
entity->EnableParserVars();
|
|
|
|
entity->m_parser_vars->m_parser_type = parser_type;
|
|
|
|
entity->m_parser_vars->m_named_decl = var_decl;
|
|
|
|
entity->m_parser_vars->m_llvm_value = NULL;
|
|
|
|
entity->m_parser_vars->m_lldb_value = NULL;
|
2010-11-30 08:27:43 +08:00
|
|
|
|
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
std::string var_decl_print_string;
|
|
|
|
llvm::raw_string_ostream var_decl_print_stream(var_decl_print_string);
|
|
|
|
var_decl->print(var_decl_print_stream);
|
|
|
|
var_decl_print_stream.flush();
|
|
|
|
|
|
|
|
log->Printf("Added register %s, returned %s", context.m_decl_name.getAsString().c_str(), var_decl_print_string.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
clang::NamespaceDecl *
|
|
|
|
ClangExpressionDeclMap::AddNamespace (NameSearchContext &context, const ClangNamespaceDecl &namespace_decl)
|
|
|
|
{
|
|
|
|
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
|
|
|
|
|
|
|
clang::Decl *copied_decl = ClangASTContext::CopyDecl (context.GetASTContext(),
|
|
|
|
namespace_decl.GetASTContext(),
|
|
|
|
namespace_decl.GetNamespaceDecl());
|
|
|
|
|
|
|
|
return dyn_cast<clang::NamespaceDecl>(copied_decl);
|
|
|
|
}
|
|
|
|
|
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-12-03 09:38:59 +08:00
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
lldb::LogSP 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)
|
|
|
|
{
|
|
|
|
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();
|
2010-11-20 04:20:02 +08:00
|
|
|
void *copied_type = GuardedCopyType(context.GetASTContext(), fun_ast_context, fun_opaque_type);
|
2010-07-27 08:55:47 +08:00
|
|
|
|
|
|
|
fun_decl = context.AddFunDecl(copied_type);
|
|
|
|
}
|
|
|
|
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-12-03 09:38:59 +08:00
|
|
|
lldb::addr_t load_addr = fun_address->GetLoadAddress(m_parser_vars->m_exe_ctx->target);
|
2010-06-23 07:46:24 +08:00
|
|
|
fun_location->SetValueType(Value::eValueTypeLoadAddress);
|
|
|
|
fun_location->GetScalar() = load_addr;
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->process->GetByteOrder(),
|
|
|
|
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
|
|
|
|
assert (entity.get());
|
2010-10-16 06:48:33 +08:00
|
|
|
std::string decl_name(context.m_decl_name.getAsString());
|
2010-12-14 10:59:59 +08:00
|
|
|
entity->SetName(ConstString(decl_name.c_str()));
|
|
|
|
entity->SetClangType (fun_opaque_type);
|
|
|
|
entity->SetClangAST (fun_ast_context);
|
|
|
|
|
|
|
|
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-08-24 07:09:38 +08:00
|
|
|
|
2010-07-16 08:09:46 +08:00
|
|
|
if (log)
|
2010-10-16 06:48:33 +08:00
|
|
|
{
|
2010-11-02 07:22:47 +08:00
|
|
|
std::string fun_decl_print_string;
|
|
|
|
llvm::raw_string_ostream fun_decl_print_stream(fun_decl_print_string);
|
|
|
|
fun_decl->print(fun_decl_print_stream);
|
|
|
|
fun_decl_print_stream.flush();
|
|
|
|
|
|
|
|
log->Printf("Found %s function %s, returned %s", (fun ? "specific" : "generic"), decl_name.c_str(), fun_decl_print_string.c_str());
|
2010-10-16 06:48:33 +08:00
|
|
|
}
|
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();
|
|
|
|
|
2010-11-20 04:20:02 +08:00
|
|
|
void *copied_type = GuardedCopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
|
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
|
|
|
|
|
|
|
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,
|
2010-10-16 06:48:33 +08:00
|
|
|
"$__lldb_expr",
|
2010-09-24 13:15:53 +08:00
|
|
|
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);
|
|
|
|
}
|
2010-11-20 04:20:02 +08:00
|
|
|
|
|
|
|
void *
|
|
|
|
ClangExpressionDeclMap::GuardedCopyType (ASTContext *dest_context,
|
|
|
|
ASTContext *source_context,
|
|
|
|
void *clang_type)
|
|
|
|
{
|
2010-12-03 09:38:59 +08:00
|
|
|
assert (m_parser_vars.get());
|
|
|
|
|
|
|
|
m_parser_vars->m_ignore_lookups = true;
|
2010-11-20 04:20:02 +08:00
|
|
|
|
|
|
|
void *ret = ClangASTContext::CopyType (dest_context,
|
|
|
|
source_context,
|
|
|
|
clang_type);
|
|
|
|
|
2010-12-03 09:38:59 +08:00
|
|
|
m_parser_vars->m_ignore_lookups = false;
|
2010-11-20 04:20:02 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|