Files
clang-p2996/lldb/source/Core/ValueObjectChild.cpp
Greg Clayton 8f92f0a35c Fixed an expression parsing issue where if you were stopped somewhere without
debug information and you evaluated an expression, a crash would occur as a
result of an unchecked pointer.

Added the ability to get the expression path for a ValueObject. For a rectangle
point child "x" the expression path would be something like: "rect.top_left.x".
This will allow GUI and command lines to get ahold of the expression path for
a value object without having to explicitly know about the hierarchy. This
means the ValueObject base class now has a "ValueObject *m_parent;" member.
All ValueObject subclasses now correctly track their lineage and are able
to provide value expression paths as well.

Added a new "--flat" option to the "frame variable" to allow for flat variable
output. An example of the current and new outputs:

(lldb) frame variable 
argc = 1
argv = 0x00007fff5fbffe80
pt = {
  x = 2
  y = 3
}
rect = {
  bottom_left = {
    x = 1
    y = 2
  }
  top_right = {
    x = 3
    y = 4
  }
}
(lldb) frame variable --flat 
argc = 1
argv = 0x00007fff5fbffe80
pt.x = 2
pt.y = 3
rect.bottom_left.x = 1
rect.bottom_left.y = 2
rect.top_right.x = 3
rect.top_right.y = 4


As you can see when there is a lot of hierarchy it can help flatten things out.
Also if you want to use a member in an expression, you can copy the text from
the "--flat" output and not have to piece it together manually. This can help
when you want to use parts of the STL in expressions:

(lldb) frame variable --flat
argc = 1
argv = 0x00007fff5fbffea8
hello_world._M_dataplus._M_p = 0x0000000000000000
(lldb) expr hello_world._M_dataplus._M_p[0] == '\0'

llvm-svn: 116532
2010-10-14 22:52:14 +00:00

208 lines
5.9 KiB
C++

//===-- ValueObjectChild.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/ValueObjectChild.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Symbol/ClangASTType.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"
#include "lldb/Target/Target.h"
using namespace lldb_private;
ValueObjectChild::ValueObjectChild
(
ValueObject* parent,
clang::ASTContext *clang_ast,
void *clang_type,
const ConstString &name,
uint32_t byte_size,
int32_t byte_offset,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset,
bool is_base_class
) :
ValueObject (parent),
m_clang_ast (clang_ast),
m_clang_type (clang_type),
m_byte_size (byte_size),
m_byte_offset (byte_offset),
m_bitfield_bit_size (bitfield_bit_size),
m_bitfield_bit_offset (bitfield_bit_offset),
m_is_base_class (is_base_class)
{
m_name = name;
}
ValueObjectChild::~ValueObjectChild()
{
}
void *
ValueObjectChild::GetClangType()
{
return m_clang_type;
}
lldb::ValueType
ValueObjectChild::GetValueType() const
{
return m_parent->GetValueType();
}
uint32_t
ValueObjectChild::CalculateNumChildren()
{
return ClangASTContext::GetNumChildren (m_clang_type, true);
}
clang::ASTContext *
ValueObjectChild::GetClangAST ()
{
return m_clang_ast;
}
size_t
ValueObjectChild::GetByteSize()
{
return m_byte_size;
}
off_t
ValueObjectChild::GetByteOffset()
{
return m_byte_offset;
}
uint32_t
ValueObjectChild::GetBitfieldBitSize()
{
return m_bitfield_bit_size;
}
uint32_t
ValueObjectChild::GetBitfieldBitOffset()
{
return m_bitfield_bit_offset;
}
ConstString
ValueObjectChild::GetTypeName()
{
if (m_type_name.IsEmpty())
{
m_type_name = ClangASTType::GetClangTypeName (GetClangType());
if (m_type_name)
{
if (m_bitfield_bit_size > 0)
{
const char *clang_type_name = m_type_name.AsCString();
if (clang_type_name)
{
std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
m_type_name.SetCString(&bitfield_type_name.front());
}
}
}
}
return m_type_name;
}
void
ValueObjectChild::UpdateValue (ExecutionContextScope *exe_scope)
{
m_error.Clear();
SetValueIsValid (false);
ValueObject* parent = m_parent;
if (parent)
{
if (parent->UpdateValueIfNeeded(exe_scope))
{
m_value.SetContext(Value::eContextTypeOpaqueClangQualType, m_clang_type);
// Copy the parent scalar value and the scalar value type
m_value.GetScalar() = parent->GetValue().GetScalar();
Value::ValueType value_type = parent->GetValue().GetValueType();
m_value.SetValueType (value_type);
if (ClangASTContext::IsPointerOrReferenceType (parent->GetClangType()))
{
uint32_t offset = 0;
m_value.GetScalar() = parent->GetDataExtractor().GetPointer(&offset);
// For pointers, m_byte_offset should only ever be set if we
// ValueObject::GetSyntheticArrayMemberFromPointer() was called
if (ClangASTContext::IsPointerType (parent->GetClangType()) && m_byte_offset)
m_value.GetScalar() += m_byte_offset;
if (value_type == Value::eValueTypeScalar ||
value_type == Value::eValueTypeFileAddress)
m_value.SetValueType (Value::eValueTypeLoadAddress);
}
else
{
switch (value_type)
{
case Value::eValueTypeLoadAddress:
case Value::eValueTypeFileAddress:
case Value::eValueTypeHostAddress:
{
lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == LLDB_INVALID_ADDRESS || addr == 0)
{
m_error.SetErrorStringWithFormat("Parent address is invalid: 0x%llx.\n", addr);
break;
}
// Set this object's scalar value to the address of its
// value be adding its byte offset to the parent address
m_value.GetScalar() += GetByteOffset();
}
break;
case Value::eValueTypeScalar:
// TODO: What if this is a register value? Do we try and
// extract the child value from within the parent data?
// Probably...
default:
m_error.SetErrorString ("Parent has invalid value.");
break;
}
}
if (m_error.Success())
{
ExecutionContext exe_ctx (exe_scope);
m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0);
}
}
else
{
m_error.SetErrorStringWithFormat("Parent failed to evaluate: %s.\n", parent->GetError().AsCString());
}
}
else
{
m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
}
}
bool
ValueObjectChild::IsInScope (StackFrame *frame)
{
return m_parent->IsInScope (frame);
}