2010-06-09 00:52:24 +08:00
|
|
|
//===-- Value.cpp -----------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Core/Value.h"
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
// Project includes
|
|
|
|
#include "lldb/Core/DataExtractor.h"
|
|
|
|
#include "lldb/Core/DataBufferHeap.h"
|
|
|
|
#include "lldb/Core/Module.h"
|
|
|
|
#include "lldb/Core/Stream.h"
|
2010-07-22 06:12:05 +08:00
|
|
|
#include "lldb/Symbol/ClangASTType.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Symbol/ClangASTContext.h"
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
|
|
#include "lldb/Symbol/Type.h"
|
|
|
|
#include "lldb/Symbol/Variable.h"
|
|
|
|
#include "lldb/Target/ExecutionContext.h"
|
|
|
|
#include "lldb/Target/Process.h"
|
2011-02-16 05:59:32 +08:00
|
|
|
#include "lldb/Target/Target.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
Value::Value() :
|
|
|
|
m_value(),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(const Scalar& scalar) :
|
|
|
|
m_value(scalar),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(int v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(unsigned int v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(long v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(unsigned long v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(long long v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(unsigned long long v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(float v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(double v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(long double v) :
|
|
|
|
m_value(v),
|
|
|
|
m_value_type(eValueTypeScalar),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(const uint8_t *bytes, int len) :
|
|
|
|
m_value(),
|
|
|
|
m_value_type(eValueTypeHostAddress),
|
|
|
|
m_context(NULL),
|
|
|
|
m_context_type(eContextTypeInvalid)
|
|
|
|
{
|
|
|
|
m_data_buffer.CopyData(bytes, len);
|
|
|
|
m_value = (uintptr_t)m_data_buffer.GetBytes();
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::Value(const Value &v) :
|
|
|
|
m_value(v.m_value),
|
|
|
|
m_value_type(v.m_value_type),
|
|
|
|
m_context(v.m_context),
|
|
|
|
m_context_type(v.m_context_type)
|
|
|
|
{
|
|
|
|
if ((uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)v.m_data_buffer.GetBytes())
|
|
|
|
{
|
|
|
|
m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
|
|
|
|
v.m_data_buffer.GetByteSize());
|
|
|
|
|
|
|
|
m_value = (uintptr_t)m_data_buffer.GetBytes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-26 07:55:37 +08:00
|
|
|
Value &
|
|
|
|
Value::operator=(const Value &rhs)
|
|
|
|
{
|
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
m_value = rhs.m_value;
|
|
|
|
m_value_type = rhs.m_value_type;
|
|
|
|
m_context = rhs.m_context;
|
|
|
|
m_context_type = rhs.m_context_type;
|
|
|
|
if ((uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs.m_data_buffer.GetBytes())
|
|
|
|
{
|
|
|
|
m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),
|
|
|
|
rhs.m_data_buffer.GetByteSize());
|
|
|
|
|
|
|
|
m_value = (uintptr_t)m_data_buffer.GetBytes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
Value *
|
|
|
|
Value::CreateProxy()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->CreateProxy ();
|
|
|
|
|
|
|
|
Value *ret = new Value;
|
|
|
|
ret->SetContext(eContextTypeValue, this);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *
|
|
|
|
Value::GetProxyTarget()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return (Value*)m_context;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Value::Dump (Stream* strm)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
((Value*)m_context)->Dump (strm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_value.GetValue (strm, true);
|
|
|
|
strm->Printf(", value_type = %s, context = %p, context_type = %s",
|
|
|
|
Value::GetValueTypeAsCString(m_value_type),
|
|
|
|
m_context,
|
|
|
|
Value::GetContextTypeAsCString(m_context_type));
|
|
|
|
}
|
|
|
|
|
|
|
|
Value::ValueType
|
|
|
|
Value::GetValueType() const
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetValueType ();
|
|
|
|
|
|
|
|
return m_value_type;
|
|
|
|
}
|
|
|
|
|
2011-03-25 05:19:54 +08:00
|
|
|
AddressType
|
2010-06-09 00:52:24 +08:00
|
|
|
Value::GetValueAddressType () const
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetValueAddressType ();
|
|
|
|
|
|
|
|
switch (m_value_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case eValueTypeScalar:
|
|
|
|
break;
|
|
|
|
case eValueTypeLoadAddress: return eAddressTypeLoad;
|
|
|
|
case eValueTypeFileAddress: return eAddressTypeFile;
|
|
|
|
case eValueTypeHostAddress: return eAddressTypeHost;
|
|
|
|
}
|
|
|
|
return eAddressTypeInvalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Value::ContextType
|
|
|
|
Value::GetContextType() const
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetContextType ();
|
|
|
|
|
|
|
|
return m_context_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Value::SetValueType (Value::ValueType value_type)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
((Value*)m_context)->SetValueType(value_type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_value_type = value_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Value::ClearContext ()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
((Value*)m_context)->ClearContext();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_context = NULL;
|
|
|
|
m_context_type = eContextTypeInvalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Value::SetContext (Value::ContextType context_type, void *p)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
((Value*)m_context)->SetContext(context_type, p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_context_type = context_type;
|
|
|
|
m_context = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterInfo *
|
|
|
|
Value::GetRegisterInfo()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetRegisterInfo();
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
if (m_context_type == eContextTypeRegisterInfo)
|
2010-06-09 00:52:24 +08:00
|
|
|
return static_cast<RegisterInfo *> (m_context);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Type *
|
|
|
|
Value::GetType()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetType();
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
if (m_context_type == eContextTypeLLDBType)
|
2010-06-09 00:52:24 +08:00
|
|
|
return static_cast<Type *> (m_context);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scalar &
|
|
|
|
Value::GetScalar()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetScalar();
|
|
|
|
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Value::ResizeData(int len)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
((Value*)m_context)->ResizeData(len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_value_type = eValueTypeHostAddress;
|
|
|
|
m_data_buffer.SetByteSize(len);
|
|
|
|
m_value = (uintptr_t)m_data_buffer.GetBytes();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Value::ValueOf(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->ValueOf(exe_ctx, ast_context);
|
|
|
|
|
|
|
|
switch (m_context_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case eContextTypeInvalid:
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeClangType: // clang::Type *
|
|
|
|
case eContextTypeRegisterInfo: // RegisterInfo *
|
|
|
|
case eContextTypeLLDBType: // Type *
|
2010-06-09 00:52:24 +08:00
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeVariable: // Variable *
|
2010-06-09 00:52:24 +08:00
|
|
|
ResolveValue(exe_ctx, ast_context);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
Value::GetValueByteSize (clang::ASTContext *ast_context, Error *error_ptr)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetValueByteSize(ast_context, error_ptr);
|
|
|
|
|
|
|
|
size_t byte_size = 0;
|
|
|
|
|
|
|
|
switch (m_context_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case eContextTypeInvalid:
|
|
|
|
// If we have no context, there is no way to know how much memory to read
|
|
|
|
if (error_ptr)
|
|
|
|
error_ptr->SetErrorString ("Invalid context type, there is no way to know how much memory to read.");
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeClangType:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (ast_context == NULL)
|
|
|
|
{
|
|
|
|
if (error_ptr)
|
|
|
|
error_ptr->SetErrorString ("Can't determine size of opaque clang type with NULL ASTContext *.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-08-03 08:35:52 +08:00
|
|
|
uint64_t bit_width = ClangASTType::GetClangTypeBitWidth (ast_context, m_context);
|
2010-06-09 00:52:24 +08:00
|
|
|
byte_size = (bit_width + 7 ) / 8;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeRegisterInfo: // RegisterInfo *
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetRegisterInfo())
|
|
|
|
byte_size = GetRegisterInfo()->byte_size;
|
|
|
|
else if (error_ptr)
|
|
|
|
error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *.");
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeLLDBType: // Type *
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetType())
|
|
|
|
byte_size = GetType()->GetByteSize();
|
|
|
|
else if (error_ptr)
|
|
|
|
error_ptr->SetErrorString ("Can't determine byte size with NULL Type *.");
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeVariable: // Variable *
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetVariable())
|
|
|
|
byte_size = GetVariable()->GetType()->GetByteSize();
|
|
|
|
else if (error_ptr)
|
|
|
|
error_ptr->SetErrorString ("Can't determine byte size with NULL Variable *.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error_ptr)
|
|
|
|
{
|
|
|
|
if (byte_size == 0)
|
|
|
|
{
|
|
|
|
if (error_ptr->Success())
|
|
|
|
error_ptr->SetErrorString("Unable to determine byte size.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error_ptr->Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return byte_size;
|
|
|
|
}
|
|
|
|
|
2011-02-17 07:00:21 +08:00
|
|
|
clang_type_t
|
2010-09-29 09:12:09 +08:00
|
|
|
Value::GetClangType ()
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
2010-09-29 09:12:09 +08:00
|
|
|
return ((Value*)m_context)->GetClangType();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
switch (m_context_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case eContextTypeInvalid:
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeClangType:
|
2010-06-09 00:52:24 +08:00
|
|
|
return m_context;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeRegisterInfo:
|
2010-06-09 00:52:24 +08:00
|
|
|
break; // TODO: Eventually convert into a clang type?
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeLLDBType:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetType())
|
2011-02-17 07:00:21 +08:00
|
|
|
return GetType()->GetClangForwardType();
|
2010-06-09 00:52:24 +08:00
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeVariable:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetVariable())
|
2011-02-17 07:00:21 +08:00
|
|
|
return GetVariable()->GetType()->GetClangForwardType();
|
2010-06-09 00:52:24 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::Format
|
|
|
|
Value::GetValueDefaultFormat ()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetValueDefaultFormat();
|
|
|
|
|
|
|
|
switch (m_context_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case eContextTypeInvalid:
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeClangType:
|
2010-07-22 06:12:05 +08:00
|
|
|
return ClangASTType::GetFormat (m_context);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeRegisterInfo:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetRegisterInfo())
|
|
|
|
return GetRegisterInfo()->format;
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeLLDBType:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetType())
|
|
|
|
return GetType()->GetFormat();
|
|
|
|
break;
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeVariable:
|
2010-06-09 00:52:24 +08:00
|
|
|
if (GetVariable())
|
|
|
|
return GetVariable()->GetType()->GetFormat();
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return a good default in case we can't figure anything out
|
|
|
|
return eFormatHex;
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
bool
|
|
|
|
Value::GetData (DataExtractor &data)
|
|
|
|
{
|
|
|
|
switch (m_value_type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeScalar:
|
|
|
|
if (m_value.GetData (data))
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeLoadAddress:
|
|
|
|
case eValueTypeFileAddress:
|
|
|
|
case eValueTypeHostAddress:
|
|
|
|
if (m_data_buffer.GetByteSize())
|
|
|
|
{
|
|
|
|
data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), data.GetByteOrder());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
Error
|
|
|
|
Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset)
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetValueAsData(exe_ctx, ast_context, data, data_offset);
|
|
|
|
|
|
|
|
data.Clear();
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
lldb::addr_t address = LLDB_INVALID_ADDRESS;
|
2011-03-25 05:19:54 +08:00
|
|
|
AddressType address_type = eAddressTypeFile;
|
2010-06-09 00:52:24 +08:00
|
|
|
switch (m_value_type)
|
|
|
|
{
|
|
|
|
default:
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorStringWithFormat("invalid value type %i", m_value_type);
|
2010-06-09 00:52:24 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeScalar:
|
2011-02-01 09:31:41 +08:00
|
|
|
data.SetByteOrder (lldb::endian::InlHostByteOrder());
|
2011-02-25 05:23:14 +08:00
|
|
|
if (m_context_type == eContextTypeClangType && ast_context)
|
|
|
|
{
|
|
|
|
uint32_t ptr_bit_width = ClangASTType::GetClangTypeBitWidth (ast_context,
|
|
|
|
ClangASTContext::GetVoidPtrType(ast_context, false));
|
|
|
|
uint32_t ptr_byte_size = (ptr_bit_width + 7) / 8;
|
|
|
|
data.SetAddressByteSize (ptr_byte_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
data.SetAddressByteSize(sizeof(void *));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (m_value.GetData (data))
|
|
|
|
return error; // Success;
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorStringWithFormat("extracting data from value failed");
|
2010-06-09 00:52:24 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeLoadAddress:
|
|
|
|
if (exe_ctx == NULL)
|
|
|
|
{
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorString ("can't read memory (no execution context)");
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
else if (exe_ctx->process == NULL)
|
|
|
|
{
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorString ("can't read memory (invalid process)");
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
|
|
|
|
address_type = eAddressTypeLoad;
|
2011-02-16 05:59:32 +08:00
|
|
|
data.SetByteOrder(exe_ctx->process->GetTarget().GetArchitecture().GetByteOrder());
|
|
|
|
data.SetAddressByteSize(exe_ctx->process->GetTarget().GetArchitecture().GetAddressByteSize());
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeFileAddress:
|
|
|
|
{
|
|
|
|
// The only thing we can currently lock down to a module so that
|
|
|
|
// we can resolve a file address, is a variable.
|
|
|
|
Variable *variable = GetVariable();
|
|
|
|
|
|
|
|
if (GetVariable())
|
|
|
|
{
|
|
|
|
lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
|
|
|
|
if (file_addr != LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
SymbolContext var_sc;
|
|
|
|
variable->CalculateSymbolContext(&var_sc);
|
|
|
|
if (var_sc.module_sp)
|
|
|
|
{
|
|
|
|
ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
|
|
|
|
if (objfile)
|
|
|
|
{
|
|
|
|
Address so_addr(file_addr, objfile->GetSectionList());
|
2010-09-15 07:36:40 +08:00
|
|
|
address = so_addr.GetLoadAddress (exe_ctx->target);
|
2010-06-09 00:52:24 +08:00
|
|
|
if (address != LLDB_INVALID_ADDRESS)
|
2010-08-19 02:28:52 +08:00
|
|
|
{
|
2010-06-09 00:52:24 +08:00
|
|
|
address_type = eAddressTypeLoad;
|
2011-02-16 05:59:32 +08:00
|
|
|
data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder());
|
|
|
|
data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize());
|
2010-08-19 02:28:52 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data.SetByteOrder(objfile->GetByteOrder());
|
|
|
|
data.SetAddressByteSize(objfile->GetAddressByteSize());
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
if (address_type == eAddressTypeFile)
|
|
|
|
error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", file_addr, variable->GetName().AsCString(""));
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error.SetErrorString ("Invalid file address.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Can't convert a file address to anything valid without more
|
|
|
|
// context (which Module it came from)
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorString ("can't read memory from file address without more context");
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeHostAddress:
|
|
|
|
address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
|
2011-02-01 09:31:41 +08:00
|
|
|
data.SetByteOrder(lldb::endian::InlHostByteOrder());
|
2010-06-09 00:52:24 +08:00
|
|
|
data.SetAddressByteSize(sizeof(void *));
|
|
|
|
address_type = eAddressTypeHost;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bail if we encountered any errors
|
|
|
|
if (error.Fail())
|
|
|
|
return error;
|
|
|
|
|
|
|
|
if (address == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
|
2010-06-09 00:52:24 +08:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we got here, we need to read the value from memory
|
|
|
|
uint32_t byte_size = GetValueByteSize (ast_context, &error);
|
|
|
|
|
|
|
|
// Bail if we encountered any errors getting the byte size
|
|
|
|
if (error.Fail())
|
|
|
|
return error;
|
|
|
|
|
|
|
|
// Make sure we have enough room within "data", and if we don't make
|
|
|
|
// something large enough that does
|
|
|
|
if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
|
|
|
|
{
|
|
|
|
DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
|
|
|
|
data.SetData(data_sp);
|
|
|
|
}
|
|
|
|
|
2010-07-10 04:39:50 +08:00
|
|
|
uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (dst != NULL)
|
|
|
|
{
|
|
|
|
if (address_type == eAddressTypeHost)
|
|
|
|
{
|
|
|
|
// The address is an address in this process, so just copy it
|
|
|
|
memcpy (dst, (uint8_t*)NULL + address, byte_size);
|
|
|
|
}
|
|
|
|
else if (address_type == eAddressTypeLoad)
|
|
|
|
{
|
|
|
|
if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size)
|
|
|
|
{
|
|
|
|
if (error.Success())
|
|
|
|
error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size);
|
2010-11-02 09:50:16 +08:00
|
|
|
else
|
|
|
|
error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-25 05:19:54 +08:00
|
|
|
error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-02 09:50:16 +08:00
|
|
|
error.SetErrorStringWithFormat ("out of memory");
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scalar &
|
|
|
|
Value::ResolveValue(ExecutionContext *exe_ctx, clang::ASTContext *ast_context)
|
|
|
|
{
|
|
|
|
Scalar scalar;
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
{
|
|
|
|
// Resolve the proxy
|
|
|
|
|
2011-01-26 07:55:37 +08:00
|
|
|
Value * rhs = (Value*)m_context;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2011-01-26 07:55:37 +08:00
|
|
|
m_value = rhs->m_value;
|
|
|
|
m_value_type = rhs->m_value_type;
|
|
|
|
m_context = rhs->m_context;
|
|
|
|
m_context_type = rhs->m_context_type;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2011-01-26 07:55:37 +08:00
|
|
|
if ((uintptr_t)rhs->m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs->m_data_buffer.GetBytes())
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2011-01-26 07:55:37 +08:00
|
|
|
m_data_buffer.CopyData(rhs->m_data_buffer.GetBytes(),
|
|
|
|
rhs->m_data_buffer.GetByteSize());
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
m_value = (uintptr_t)m_data_buffer.GetBytes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
if (m_context_type == eContextTypeClangType)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-09-29 09:12:09 +08:00
|
|
|
void *opaque_clang_qual_type = GetClangType();
|
2010-06-09 00:52:24 +08:00
|
|
|
switch (m_value_type)
|
|
|
|
{
|
|
|
|
case eValueTypeScalar: // raw scalar value
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case eValueTypeFileAddress:
|
|
|
|
m_value.Clear();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eValueTypeLoadAddress: // load address value
|
|
|
|
case eValueTypeHostAddress: // host address value (for memory in the process that is using liblldb)
|
|
|
|
{
|
2011-03-25 05:19:54 +08:00
|
|
|
AddressType address_type = m_value_type == eValueTypeLoadAddress ? eAddressTypeLoad : eAddressTypeHost;
|
2010-06-09 00:52:24 +08:00
|
|
|
lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
|
|
|
|
DataExtractor data;
|
2010-07-22 06:12:05 +08:00
|
|
|
if (ClangASTType::ReadFromMemory (ast_context, opaque_clang_qual_type, exe_ctx, addr, address_type, data))
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-07-22 06:12:05 +08:00
|
|
|
if (ClangASTType::GetValueAsScalar (ast_context, opaque_clang_qual_type, data, 0, data.GetByteSize(), scalar))
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
m_value = scalar;
|
|
|
|
m_value_type = eValueTypeScalar;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
|
|
|
|
{
|
|
|
|
m_value.Clear();
|
|
|
|
m_value_type = eValueTypeScalar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes())
|
|
|
|
{
|
|
|
|
m_value.Clear();
|
|
|
|
m_value_type = eValueTypeScalar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
Variable *
|
|
|
|
Value::GetVariable()
|
|
|
|
{
|
|
|
|
if (m_context_type == eContextTypeValue)
|
|
|
|
return ((Value*)m_context)->GetVariable();
|
|
|
|
|
2010-11-13 11:52:47 +08:00
|
|
|
if (m_context_type == eContextTypeVariable)
|
2010-06-09 00:52:24 +08:00
|
|
|
return static_cast<Variable *> (m_context);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
Value::GetValueTypeAsCString (ValueType value_type)
|
|
|
|
{
|
|
|
|
switch (value_type)
|
|
|
|
{
|
|
|
|
case eValueTypeScalar: return "scalar";
|
|
|
|
case eValueTypeFileAddress: return "file address";
|
|
|
|
case eValueTypeLoadAddress: return "load address";
|
|
|
|
case eValueTypeHostAddress: return "host address";
|
|
|
|
};
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
Value::GetContextTypeAsCString (ContextType context_type)
|
|
|
|
{
|
|
|
|
switch (context_type)
|
|
|
|
{
|
|
|
|
case eContextTypeInvalid: return "invalid";
|
2010-11-13 11:52:47 +08:00
|
|
|
case eContextTypeClangType: return "clang::Type *";
|
|
|
|
case eContextTypeRegisterInfo: return "RegisterInfo *";
|
|
|
|
case eContextTypeLLDBType: return "Type *";
|
|
|
|
case eContextTypeVariable: return "Variable *";
|
2010-07-10 04:39:50 +08:00
|
|
|
case eContextTypeValue: return "Value"; // TODO: Sean, more description here?
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueList::ValueList (const ValueList &rhs)
|
|
|
|
{
|
|
|
|
m_values = rhs.m_values;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ValueList &
|
|
|
|
ValueList::operator= (const ValueList &rhs)
|
|
|
|
{
|
|
|
|
m_values = rhs.m_values;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ValueList::PushValue (const Value &value)
|
|
|
|
{
|
|
|
|
m_values.push_back (value);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
ValueList::GetSize()
|
|
|
|
{
|
|
|
|
return m_values.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *
|
|
|
|
ValueList::GetValueAtIndex (size_t idx)
|
|
|
|
{
|
|
|
|
if (idx < GetSize())
|
|
|
|
{
|
|
|
|
return &(m_values[idx]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ValueList::Clear ()
|
|
|
|
{
|
|
|
|
m_values.clear();
|
|
|
|
}
|