diff options
author | Chris Lattner <sabre@nondot.org> | 2010-06-08 16:52:24 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-06-08 16:52:24 +0000 |
commit | 30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c (patch) | |
tree | f70013106f6a461a14abcd71c65f48a95a2979a6 /lldb/source/Core/Value.cpp | |
parent | 312c4c799da215b337f790fda330f70c4aa757cf (diff) | |
download | bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.tar.gz bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.zip |
Initial checkin of lldb code from internal Apple repo.
llvm-svn: 105619
Diffstat (limited to 'lldb/source/Core/Value.cpp')
-rw-r--r-- | lldb/source/Core/Value.cpp | 803 |
1 files changed, 803 insertions, 0 deletions
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp new file mode 100644 index 00000000000..c4c17dd0428 --- /dev/null +++ b/lldb/source/Core/Value.cpp @@ -0,0 +1,803 @@ +//===-- 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" +#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" + +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(); + } +} + +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; +} + +//#include "clang/Lex/LiteralSupport.h" +//#include "clang/AST/ASTContext.h" +//#include "clang/Frontend/CompilerInstance.h" +// +//Value::Value (const char *data, llvm::CompilerInstance *compiler) +//{ +// clang::NumericLiteralParser parser(data, data + strlen(data), clang::SourceLocation(), +// compiler->getPreprocessor()); +// if (parser.had_error) +// { +// } +// else if (parser.isBool) +// { +// APInt value; +// parser.GetIntegerValue(value); +// } +// else if (parser.isLong) +// { +// } +// else if (parser.isLongLong) +// { +// } +// else if (parser.isFloat) +// { +// } +// +//} +// +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)); +} + +void * +Value::GetOpaqueClangQualType() +{ + if (m_context_type == eContextTypeValue) + return ((Value*)m_context)->GetOpaqueClangQualType (); + + if (m_context_type == eContextTypeOpaqueClangQualType) + return m_context; + + return NULL; +} + +Value::ValueType +Value::GetValueType() const +{ + if (m_context_type == eContextTypeValue) + return ((Value*)m_context)->GetValueType (); + + return m_value_type; +} + +lldb::AddressType +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(); + + if (m_context_type == eContextTypeDCRegisterInfo) + return static_cast<RegisterInfo *> (m_context); + return NULL; +} + +Type * +Value::GetType() +{ + if (m_context_type == eContextTypeValue) + return ((Value*)m_context)->GetType(); + + if (m_context_type == eContextTypeDCType) + 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: + case eContextTypeOpaqueClangQualType: // clang::Type * + case eContextTypeDCRegisterInfo: // RegisterInfo * + case eContextTypeDCType: // Type * + break; + + case eContextTypeDCVariable: // Variable * + 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; + + case eContextTypeOpaqueClangQualType: + if (ast_context == NULL) + { + if (error_ptr) + error_ptr->SetErrorString ("Can't determine size of opaque clang type with NULL ASTContext *."); + } + else + { + uint64_t bit_width = ClangASTContext::GetTypeBitSize (ast_context, m_context); + byte_size = (bit_width + 7 ) / 8; + } + break; + + case eContextTypeDCRegisterInfo: // RegisterInfo * + if (GetRegisterInfo()) + byte_size = GetRegisterInfo()->byte_size; + else if (error_ptr) + error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *."); + + break; + + case eContextTypeDCType: // Type * + if (GetType()) + byte_size = GetType()->GetByteSize(); + else if (error_ptr) + error_ptr->SetErrorString ("Can't determine byte size with NULL Type *."); + break; + + case eContextTypeDCVariable: // Variable * + 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; +} + +void * +Value::GetValueOpaqueClangQualType () +{ + if (m_context_type == eContextTypeValue) + return ((Value*)m_context)->GetValueOpaqueClangQualType(); + + switch (m_context_type) + { + default: + case eContextTypeInvalid: + break; + + case eContextTypeOpaqueClangQualType: + return m_context; + + case eContextTypeDCRegisterInfo: + break; // TODO: Eventually convert into a clang type? + + case eContextTypeDCType: + if (GetType()) + return GetType()->GetOpaqueClangQualType(); + break; + + case eContextTypeDCVariable: + if (GetVariable()) + return GetVariable()->GetType()->GetOpaqueClangQualType(); + 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; + + case eContextTypeOpaqueClangQualType: + return Type::GetFormat (m_context); + + case eContextTypeDCRegisterInfo: + if (GetRegisterInfo()) + return GetRegisterInfo()->format; + break; + + case eContextTypeDCType: + if (GetType()) + return GetType()->GetFormat(); + break; + + case eContextTypeDCVariable: + if (GetVariable()) + return GetVariable()->GetType()->GetFormat(); + break; + + } + + // Return a good default in case we can't figure anything out + return eFormatHex; +} + +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; + lldb::AddressType address_type = eAddressTypeFile; + switch (m_value_type) + { + default: + error.SetErrorStringWithFormat("Invalid value type %i.\n", m_value_type); + break; + + case eValueTypeScalar: + data.SetByteOrder (eByteOrderHost); + data.SetAddressByteSize(sizeof(void *)); + if (m_value.GetData (data)) + return error; // Success; + error.SetErrorStringWithFormat("Extracting data from value failed.\n"); + break; + + case eValueTypeLoadAddress: + if (exe_ctx == NULL) + { + error.SetErrorString ("Can't read memory (no execution context)."); + } + else if (exe_ctx->process == NULL) + { + error.SetErrorString ("Can't read memory (invalid process)."); + } + else + { + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + address_type = eAddressTypeLoad; + data.SetByteOrder(exe_ctx->process->GetByteOrder()); + data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize()); + } + 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()); + address = so_addr.GetLoadAddress (exe_ctx->process); + if (address != LLDB_INVALID_ADDRESS) + address_type = eAddressTypeLoad; + } + if (address_type == eAddressTypeFile) + error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString()); + } + else + { + error.SetErrorStringWithFormat ("Unable to resolve the module for file address 0x%llx for variable '%s'.\n", file_addr, variable->GetName().AsCString("")); + } + } + else + { + error.SetErrorString ("Invalid file address."); + } + } + else + { + // Can't convert a file address to anything valid without more + // context (which Module it came from) + error.SetErrorString ("Can't read memory from file address without more context."); + } + } + break; + + case eValueTypeHostAddress: + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + data.SetByteOrder(eByteOrderHost); + data.SetAddressByteSize(sizeof(void *)); + address_type = eAddressTypeHost; + break; + } + + // Bail if we encountered any errors + if (error.Fail()) + return error; + + if (address == LLDB_INVALID_ADDRESS) + { + error.SetErrorStringWithFormat ("Invalid %s address.\n", address_type == eAddressTypeHost ? "host" : "load"); + 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); + } + + uint8_t* dst = (uint8_t*)data.PeekData (data_offset, byte_size); + 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); + } + } + else + { + error.SetErrorStringWithFormat ("Unsupported lldb::AddressType value (%i).\n", address_type); + } + } + else + { + error.SetErrorStringWithFormat ("Out of memory.\n"); + } + + return error; +} + +Scalar & +Value::ResolveValue(ExecutionContext *exe_ctx, clang::ASTContext *ast_context) +{ + Scalar scalar; + if (m_context_type == eContextTypeValue) + { + // Resolve the proxy + + Value * v = (Value*)m_context; + + 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(); + } + } + + if (m_context_type == eContextTypeOpaqueClangQualType) + { + void *opaque_clang_qual_type = GetOpaqueClangQualType(); + 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) + { + lldb::AddressType address_type = m_value_type == eValueTypeLoadAddress ? eAddressTypeLoad : eAddressTypeHost; + lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); + DataExtractor data; + if (Type::ReadFromMemory (exe_ctx, ast_context, opaque_clang_qual_type, addr, address_type, data)) + { + if (Type::GetValueAsScalar (ast_context, opaque_clang_qual_type, data, 0, data.GetByteSize(), scalar)) + { + 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(); + + if (m_context_type == eContextTypeDCVariable) + 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"; + case eContextTypeOpaqueClangQualType: return "clang::Type *"; + case eContextTypeDCRegisterInfo: return "RegisterInfo *"; + case eContextTypeDCType: return "Type *"; + case eContextTypeDCVariable: return "Variable *"; + }; + 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(); +} |