forked from OSchip/llvm-project
Add support for displaying Java array types on Andorid
Differential revision: http://reviews.llvm.org/D19540 llvm-svn: 268622
This commit is contained in:
parent
d00698f4c1
commit
2ff833060c
|
@ -335,8 +335,8 @@ public:
|
|||
CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size);
|
||||
|
||||
CompilerType
|
||||
CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression,
|
||||
const lldb::addr_t data_offset);
|
||||
CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type,
|
||||
const DWARFExpression &length_expression, const lldb::addr_t data_offset);
|
||||
|
||||
CompilerType
|
||||
CreateReferenceType(const CompilerType &pointee_type);
|
||||
|
@ -360,6 +360,12 @@ public:
|
|||
static ConstString
|
||||
GetLinkageName(const CompilerType &type);
|
||||
|
||||
static uint32_t
|
||||
CalculateArraySize(const CompilerType &type, ValueObject &in_value);
|
||||
|
||||
static uint64_t
|
||||
CalculateArrayElementOffset(const CompilerType &type, size_t index);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// llvm casting support
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -14,11 +14,100 @@
|
|||
#include "JavaFormatterFunctions.h"
|
||||
#include "lldb/DataFormatters/FormattersHelpers.h"
|
||||
#include "lldb/DataFormatters/StringPrinter.h"
|
||||
#include "lldb/Symbol/JavaASTContext.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp)
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
}
|
||||
|
||||
size_t
|
||||
CalculateNumChildren() override
|
||||
{
|
||||
ValueObjectSP valobj = GetDereferencedValueObject();
|
||||
if (!valobj)
|
||||
return 0;
|
||||
|
||||
CompilerType type = valobj->GetCompilerType();
|
||||
uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj);
|
||||
if (size == UINT32_MAX)
|
||||
return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
GetChildAtIndex(size_t idx) override
|
||||
{
|
||||
ValueObjectSP valobj = GetDereferencedValueObject();
|
||||
if (!valobj)
|
||||
return nullptr;
|
||||
|
||||
ProcessSP process_sp = valobj->GetProcessSP();
|
||||
if (!process_sp)
|
||||
return nullptr;
|
||||
|
||||
CompilerType type = valobj->GetCompilerType();
|
||||
CompilerType element_type = type.GetArrayElementType();
|
||||
lldb::addr_t address = valobj->GetAddressOf() + JavaASTContext::CalculateArrayElementOffset(type, idx);
|
||||
|
||||
Error error;
|
||||
size_t byte_size = element_type.GetByteSize(nullptr);
|
||||
DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
|
||||
size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(), byte_size, error);
|
||||
if (error.Fail() || byte_size != bytes_read)
|
||||
return nullptr;
|
||||
|
||||
StreamString name;
|
||||
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
|
||||
DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
|
||||
return CreateValueObjectFromData(name.GetData(), data, valobj->GetExecutionContextRef(),
|
||||
element_type);
|
||||
}
|
||||
|
||||
bool
|
||||
Update() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MightHaveChildren() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
GetIndexOfChildWithName(const ConstString &name) override
|
||||
{
|
||||
return ExtractIndexFromString(name.GetCString());
|
||||
}
|
||||
|
||||
private:
|
||||
ValueObjectSP
|
||||
GetDereferencedValueObject()
|
||||
{
|
||||
if (!m_backend.IsPointerOrReferenceType())
|
||||
m_backend.GetSP();
|
||||
|
||||
Error error;
|
||||
return m_backend.Dereference(error);
|
||||
}
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
bool
|
||||
lldb_private::formatters::JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts)
|
||||
{
|
||||
|
@ -69,3 +158,29 @@ lldb_private::formatters::JavaStringSummaryProvider(ValueObject &valobj, Stream
|
|||
stream.Printf("Summary Unavailable");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
|
||||
{
|
||||
if (valobj.IsPointerOrReferenceType())
|
||||
{
|
||||
Error error;
|
||||
ValueObjectSP deref = valobj.Dereference(error);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
return JavaArraySummaryProvider(*deref, stream, options);
|
||||
}
|
||||
|
||||
CompilerType type = valobj.GetCompilerType();
|
||||
uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
|
||||
if (size == UINT32_MAX)
|
||||
return false;
|
||||
stream.Printf("[%u]{...}", size);
|
||||
return true;
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@ namespace formatters
|
|||
bool
|
||||
JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
|
||||
|
||||
bool
|
||||
JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
|
|
|
@ -88,11 +88,22 @@ JavaLanguage::GetFormatters()
|
|||
DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
|
||||
if (g_category)
|
||||
{
|
||||
const char* array_regexp = "^.*\\[\\]&?$";
|
||||
|
||||
lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
|
||||
TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaStringSummaryProvider,
|
||||
"java.lang.String summary provider"));
|
||||
|
||||
g_category->GetTypeSummariesContainer()->Add(ConstString("java::lang::String"), string_summary_sp);
|
||||
|
||||
lldb::TypeSummaryImplSP array_summary_sp(new CXXFunctionSummaryFormat(
|
||||
TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaArraySummaryProvider,
|
||||
"Java array summary provider"));
|
||||
g_category->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(array_regexp)),
|
||||
array_summary_sp);
|
||||
|
||||
AddCXXSynthetic(g_category, lldb_private::formatters::JavaArraySyntheticFrontEndCreator,
|
||||
"Java array synthetic children", ConstString(array_regexp),
|
||||
SyntheticChildren::Flags().SetCascades(true), true);
|
||||
}
|
||||
});
|
||||
return g_category;
|
||||
|
|
|
@ -147,7 +147,7 @@ DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die)
|
|||
|
||||
CompilerType element_compiler_type = element_type->GetForwardCompilerType();
|
||||
CompilerType array_compiler_type =
|
||||
m_ast.CreateArrayType(element_compiler_type, length_expression, data_offset);
|
||||
m_ast.CreateArrayType(linkage_name, element_compiler_type, length_expression, data_offset);
|
||||
|
||||
Declaration decl;
|
||||
TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr,
|
||||
|
|
|
@ -755,20 +755,21 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu,
|
|||
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_inlined_subroutine:
|
||||
case DW_TAG_array_type:
|
||||
case DW_TAG_base_type:
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_constant:
|
||||
case DW_TAG_enumeration_type:
|
||||
case DW_TAG_string_type:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_inlined_subroutine:
|
||||
case DW_TAG_namespace:
|
||||
case DW_TAG_variable:
|
||||
case DW_TAG_string_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_unspecified_type:
|
||||
case DW_TAG_variable:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -980,15 +981,16 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu,
|
|||
}
|
||||
break;
|
||||
|
||||
case DW_TAG_array_type:
|
||||
case DW_TAG_base_type:
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_constant:
|
||||
case DW_TAG_enumeration_type:
|
||||
case DW_TAG_string_type:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_unspecified_type:
|
||||
if (name && !is_declaration)
|
||||
types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
|
||||
|
|
|
@ -141,7 +141,60 @@ private:
|
|||
const TypeKind m_type_kind;
|
||||
};
|
||||
|
||||
class JavaObjectType : public JavaASTContext::JavaType
|
||||
class JavaDynamicType : public JavaASTContext::JavaType
|
||||
{
|
||||
public:
|
||||
JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) :
|
||||
JavaType(kind),
|
||||
m_linkage_name(linkage_name),
|
||||
m_dynamic_type_id(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ConstString
|
||||
GetLinkageName() const
|
||||
{
|
||||
return m_linkage_name;
|
||||
}
|
||||
|
||||
void
|
||||
SetDynamicTypeId(const DWARFExpression &type_id)
|
||||
{
|
||||
m_dynamic_type_id = type_id;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj)
|
||||
{
|
||||
if (!m_dynamic_type_id.IsValid())
|
||||
return UINT64_MAX;
|
||||
|
||||
Value obj_load_address = value_obj.GetValue();
|
||||
obj_load_address.ResolveValue(exe_ctx);
|
||||
obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
|
||||
|
||||
Value result;
|
||||
if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address,
|
||||
nullptr, result, nullptr))
|
||||
{
|
||||
Error error;
|
||||
|
||||
lldb::addr_t type_id_addr = result.GetScalar().UInt();
|
||||
lldb::ProcessSP process_sp = exe_ctx->GetProcessSP();
|
||||
if (process_sp)
|
||||
return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(),
|
||||
UINT64_MAX, error);
|
||||
}
|
||||
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
public:
|
||||
ConstString m_linkage_name;
|
||||
DWARFExpression m_dynamic_type_id;
|
||||
};
|
||||
|
||||
class JavaObjectType : public JavaDynamicType
|
||||
{
|
||||
public:
|
||||
struct Field
|
||||
|
@ -152,13 +205,11 @@ public:
|
|||
};
|
||||
|
||||
JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size)
|
||||
: JavaType(JavaType::eKindObject),
|
||||
: JavaDynamicType(JavaType::eKindObject, linkage_name),
|
||||
m_name(name),
|
||||
m_linkage_name(linkage_name),
|
||||
m_byte_size(byte_size),
|
||||
m_base_class_offset(0),
|
||||
m_is_complete(false),
|
||||
m_dynamic_type_id(nullptr)
|
||||
m_is_complete(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -168,12 +219,6 @@ public:
|
|||
return m_name;
|
||||
}
|
||||
|
||||
ConstString
|
||||
GetLinkageName() const
|
||||
{
|
||||
return m_linkage_name;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetByteSize() const
|
||||
{
|
||||
|
@ -270,38 +315,6 @@ public:
|
|||
m_fields.push_back({name, type, offset});
|
||||
}
|
||||
|
||||
void
|
||||
SetDynamicTypeId(const DWARFExpression &type_id)
|
||||
{
|
||||
m_dynamic_type_id = type_id;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj)
|
||||
{
|
||||
if (!m_dynamic_type_id.IsValid())
|
||||
return UINT64_MAX;
|
||||
|
||||
Value obj_load_address = value_obj.GetValue();
|
||||
obj_load_address.ResolveValue(exe_ctx);
|
||||
obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
|
||||
|
||||
Value result;
|
||||
if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address,
|
||||
nullptr, result, nullptr))
|
||||
{
|
||||
Error error;
|
||||
|
||||
lldb::addr_t type_id_addr = result.GetScalar().UInt();
|
||||
lldb::ProcessSP process_sp = exe_ctx->GetProcessSP();
|
||||
if (process_sp)
|
||||
return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(),
|
||||
UINT64_MAX, error);
|
||||
}
|
||||
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
static bool
|
||||
classof(const JavaType *jt)
|
||||
{
|
||||
|
@ -310,14 +323,12 @@ public:
|
|||
|
||||
private:
|
||||
ConstString m_name;
|
||||
ConstString m_linkage_name;
|
||||
uint32_t m_byte_size;
|
||||
CompilerType m_base_class;
|
||||
uint32_t m_base_class_offset;
|
||||
std::vector<CompilerType> m_interfaces;
|
||||
std::vector<Field> m_fields;
|
||||
bool m_is_complete;
|
||||
DWARFExpression m_dynamic_type_id;
|
||||
};
|
||||
|
||||
class JavaReferenceType : public JavaASTContext::JavaType
|
||||
|
@ -360,13 +371,15 @@ private:
|
|||
CompilerType m_pointee_type;
|
||||
};
|
||||
|
||||
class JavaArrayType : public JavaASTContext::JavaType
|
||||
class JavaArrayType : public JavaDynamicType
|
||||
{
|
||||
public:
|
||||
JavaArrayType(CompilerType element_type, const DWARFExpression &length_expression, const lldb::addr_t data_offset)
|
||||
: JavaType(JavaType::eKindArray),
|
||||
JavaArrayType(const ConstString& linkage_name, CompilerType element_type, const DWARFExpression &length_expression,
|
||||
lldb::addr_t data_offset)
|
||||
: JavaDynamicType(JavaType::eKindArray, linkage_name),
|
||||
m_element_type(element_type),
|
||||
m_length_expression(length_expression)
|
||||
m_length_expression(length_expression),
|
||||
m_data_offset(data_offset)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -402,25 +415,37 @@ public:
|
|||
}
|
||||
|
||||
uint32_t
|
||||
GetNumElements(const ValueObject *value_obj)
|
||||
GetNumElements(ValueObject *value_obj)
|
||||
{
|
||||
if (!m_length_expression.IsValid())
|
||||
return false;
|
||||
return UINT32_MAX;
|
||||
|
||||
Value obj_load_address = value_obj->GetValue();
|
||||
Error error;
|
||||
ValueObjectSP address_obj = value_obj->AddressOf(error);
|
||||
if (error.Fail())
|
||||
return UINT32_MAX;
|
||||
|
||||
Value obj_load_address = address_obj->GetValue();
|
||||
obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
|
||||
|
||||
Value result;
|
||||
if (m_length_expression.Evaluate(nullptr, nullptr, nullptr, nullptr, 0, nullptr, &obj_load_address, result,
|
||||
nullptr))
|
||||
ExecutionContextScope* exec_ctx_scope = value_obj->GetExecutionContextRef().Lock(true).GetBestExecutionContextScope();
|
||||
if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, nullptr, &obj_load_address, result, nullptr))
|
||||
return result.GetScalar().UInt();
|
||||
|
||||
return 0;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
GetElementOffset(size_t idx)
|
||||
{
|
||||
return m_data_offset + idx * m_element_type.GetByteSize(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
CompilerType m_element_type;
|
||||
DWARFExpression m_length_expression;
|
||||
lldb::addr_t m_data_offset;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@ -998,6 +1023,10 @@ JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextSc
|
|||
{
|
||||
return 32; // References are always 4 byte long in java
|
||||
}
|
||||
else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type)))
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
|
||||
{
|
||||
return obj->GetByteSize() * 8;
|
||||
|
@ -1450,14 +1479,15 @@ JavaASTContext::CreateObjectType(const ConstString &name, const ConstString &lin
|
|||
}
|
||||
|
||||
CompilerType
|
||||
JavaASTContext::CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression,
|
||||
const lldb::addr_t data_offset)
|
||||
JavaASTContext::CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type,
|
||||
const DWARFExpression &length_expression, const lldb::addr_t data_offset)
|
||||
{
|
||||
ConstString name = element_type.GetTypeName();
|
||||
auto it = m_array_type_map.find(name);
|
||||
if (it == m_array_type_map.end())
|
||||
{
|
||||
std::unique_ptr<JavaType> array_type(new JavaArrayType(element_type, length_expression, data_offset));
|
||||
std::unique_ptr<JavaType> array_type(new JavaArrayType(linkage_name, element_type, length_expression,
|
||||
data_offset));
|
||||
it = m_array_type_map.emplace(name, std::move(array_type)).first;
|
||||
}
|
||||
return CompilerType(this, it->second.get());
|
||||
|
@ -1512,6 +1542,24 @@ JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, const Compiler
|
|||
{
|
||||
if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
|
||||
return obj->CalculateDynamicTypeId(exe_ctx, in_value);
|
||||
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
|
||||
return arr->CalculateDynamicTypeId(exe_ctx, in_value);
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
JavaASTContext::CalculateArraySize(const CompilerType &type, ValueObject &in_value)
|
||||
{
|
||||
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
|
||||
return arr->GetNumElements(&in_value);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, size_t index)
|
||||
{
|
||||
if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
|
||||
return arr->GetElementOffset(index);
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue