mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 23:45:25 +08:00
A long time ago we start with clang types that were created by the symbol files and there were many functions in lldb_private::ClangASTContext that helped. Later we create ClangASTType which contains a clang::ASTContext and an opauque QualType, but we didn't switch over to fully using it. There were a lot of places where we would pass around a raw clang_type_t and also pass along a clang::ASTContext separately. This left room for error. This checkin change all type code over to use ClangASTType everywhere and I cleaned up the interfaces quite a bit. Any code that was in ClangASTContext that was type related, was moved over into ClangASTType. All code that used these types was switched over to use all of the new goodness. llvm-svn: 186130
372 lines
11 KiB
C++
372 lines
11 KiB
C++
//===-- NSArray.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/lldb-python.h"
|
|
|
|
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
|
|
|
#include "lldb/Core/DataBufferHeap.h"
|
|
#include "lldb/Core/Error.h"
|
|
#include "lldb/Core/Stream.h"
|
|
#include "lldb/Core/ValueObject.h"
|
|
#include "lldb/Core/ValueObjectConstResult.h"
|
|
#include "lldb/Host/Endian.h"
|
|
#include "lldb/Symbol/ClangASTContext.h"
|
|
#include "lldb/Target/ObjCLanguageRuntime.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::formatters;
|
|
|
|
bool
|
|
lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
|
|
{
|
|
ProcessSP process_sp = valobj.GetProcessSP();
|
|
if (!process_sp)
|
|
return false;
|
|
|
|
ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
|
|
|
|
if (!runtime)
|
|
return false;
|
|
|
|
ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
|
|
|
|
if (!descriptor.get() || !descriptor->IsValid())
|
|
return false;
|
|
|
|
uint32_t ptr_size = process_sp->GetAddressByteSize();
|
|
|
|
lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
|
|
|
|
if (!valobj_addr)
|
|
return false;
|
|
|
|
uint64_t value = 0;
|
|
|
|
const char* class_name = descriptor->GetClassName().GetCString();
|
|
|
|
if (!class_name || !*class_name)
|
|
return false;
|
|
|
|
if (!strcmp(class_name,"__NSArrayI"))
|
|
{
|
|
Error error;
|
|
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
|
|
if (error.Fail())
|
|
return false;
|
|
}
|
|
else if (!strcmp(class_name,"__NSArrayM"))
|
|
{
|
|
Error error;
|
|
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
|
|
if (error.Fail())
|
|
return false;
|
|
}
|
|
else if (!strcmp(class_name,"__NSCFArray"))
|
|
{
|
|
Error error;
|
|
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
|
|
if (error.Fail())
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
|
|
return false;
|
|
}
|
|
|
|
stream.Printf("@\"%" PRIu64 " object%s\"",
|
|
value,
|
|
value == 1 ? "" : "s");
|
|
return true;
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
|
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
|
m_exe_ctx_ref(),
|
|
m_ptr_size(8),
|
|
m_data_32(NULL),
|
|
m_data_64(NULL)
|
|
{
|
|
if (valobj_sp)
|
|
{
|
|
clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext();
|
|
if (ast)
|
|
m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
|
|
}
|
|
}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
|
|
{
|
|
if (m_data_32)
|
|
return m_data_32->_used;
|
|
if (m_data_64)
|
|
return m_data_64->_used;
|
|
return 0;
|
|
}
|
|
|
|
lldb::ValueObjectSP
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
|
{
|
|
if (!m_data_32 && !m_data_64)
|
|
return lldb::ValueObjectSP();
|
|
if (idx >= CalculateNumChildren())
|
|
return lldb::ValueObjectSP();
|
|
lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
|
|
size_t pyhs_idx = idx;
|
|
pyhs_idx += (m_data_32 ? m_data_32->offset : m_data_64->offset);
|
|
if ((m_data_32 ? m_data_32->_size : m_data_64->_size) <= pyhs_idx)
|
|
pyhs_idx -= (m_data_32 ? m_data_32->_size : m_data_64->_size);
|
|
object_at_idx += (pyhs_idx * m_ptr_size);
|
|
StreamString idx_name;
|
|
idx_name.Printf("[%zu]",idx);
|
|
lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
|
|
object_at_idx,
|
|
m_exe_ctx_ref,
|
|
m_id_type);
|
|
m_children.push_back(retval_sp);
|
|
return retval_sp;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
|
|
{
|
|
m_children.clear();
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
m_ptr_size = 0;
|
|
delete m_data_32;
|
|
m_data_32 = NULL;
|
|
delete m_data_64;
|
|
m_data_64 = NULL;
|
|
if (!valobj_sp)
|
|
return false;
|
|
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
|
Error error;
|
|
error.Clear();
|
|
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
|
|
if (!process_sp)
|
|
return false;
|
|
m_ptr_size = process_sp->GetAddressByteSize();
|
|
uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
|
|
if (m_ptr_size == 4)
|
|
{
|
|
m_data_32 = new DataDescriptor_32();
|
|
process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
|
|
}
|
|
else
|
|
{
|
|
m_data_64 = new DataDescriptor_64();
|
|
process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
|
|
}
|
|
if (error.Fail())
|
|
return false;
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
|
{
|
|
if (!m_data_32 && !m_data_64)
|
|
return UINT32_MAX;
|
|
const char* item_name = name.GetCString();
|
|
uint32_t idx = ExtractIndexFromString(item_name);
|
|
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
|
return UINT32_MAX;
|
|
return idx;
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
|
|
{
|
|
delete m_data_32;
|
|
m_data_32 = NULL;
|
|
delete m_data_64;
|
|
m_data_64 = NULL;
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
|
SyntheticChildrenFrontEnd (*valobj_sp.get()),
|
|
m_exe_ctx_ref (),
|
|
m_ptr_size (8),
|
|
m_items (0),
|
|
m_data_ptr (0)
|
|
{
|
|
if (valobj_sp)
|
|
{
|
|
clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext();
|
|
if (ast)
|
|
m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
|
|
}
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
|
|
{
|
|
}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
|
{
|
|
const char* item_name = name.GetCString();
|
|
uint32_t idx = ExtractIndexFromString(item_name);
|
|
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
|
return UINT32_MAX;
|
|
return idx;
|
|
}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
|
|
{
|
|
return m_items;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
|
|
{
|
|
m_ptr_size = 0;
|
|
m_items = 0;
|
|
m_data_ptr = 0;
|
|
m_children.clear();
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
if (!valobj_sp)
|
|
return false;
|
|
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
|
Error error;
|
|
error.Clear();
|
|
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
|
|
if (!process_sp)
|
|
return false;
|
|
m_ptr_size = process_sp->GetAddressByteSize();
|
|
uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
|
|
m_items = process_sp->ReadPointerFromMemory(data_location, error);
|
|
if (error.Fail())
|
|
return false;
|
|
m_data_ptr = data_location+m_ptr_size;
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
lldb::ValueObjectSP
|
|
lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
|
{
|
|
if (idx >= CalculateNumChildren())
|
|
return lldb::ValueObjectSP();
|
|
lldb::addr_t object_at_idx = m_data_ptr;
|
|
object_at_idx += (idx * m_ptr_size);
|
|
ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
|
|
if (!process_sp)
|
|
return lldb::ValueObjectSP();
|
|
Error error;
|
|
if (error.Fail())
|
|
return lldb::ValueObjectSP();
|
|
StreamString idx_name;
|
|
idx_name.Printf("[%zu]",idx);
|
|
lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx, m_exe_ctx_ref, m_id_type);
|
|
m_children.push_back(retval_sp);
|
|
return retval_sp;
|
|
}
|
|
|
|
SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
|
{
|
|
lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
|
|
if (!process_sp)
|
|
return NULL;
|
|
ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
|
|
if (!runtime)
|
|
return NULL;
|
|
|
|
if (!valobj_sp->IsPointerType())
|
|
{
|
|
Error error;
|
|
valobj_sp = valobj_sp->AddressOf(error);
|
|
if (error.Fail() || !valobj_sp)
|
|
return NULL;
|
|
}
|
|
|
|
ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
|
|
|
|
if (!descriptor.get() || !descriptor->IsValid())
|
|
return NULL;
|
|
|
|
const char* class_name = descriptor->GetClassName().GetCString();
|
|
|
|
if (!class_name || !*class_name)
|
|
return NULL;
|
|
|
|
if (!strcmp(class_name,"__NSArrayI"))
|
|
{
|
|
return (new NSArrayISyntheticFrontEnd(valobj_sp));
|
|
}
|
|
else if (!strcmp(class_name,"__NSArrayM"))
|
|
{
|
|
return (new NSArrayMSyntheticFrontEnd(valobj_sp));
|
|
}
|
|
else
|
|
{
|
|
return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
|
|
}
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
|
SyntheticChildrenFrontEnd(*valobj_sp.get())
|
|
{}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
|
|
{
|
|
uint64_t count = 0;
|
|
if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
|
|
return count;
|
|
return 0;
|
|
}
|
|
|
|
lldb::ValueObjectSP
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
|
{
|
|
StreamString idx_name;
|
|
idx_name.Printf("[%zu]",idx);
|
|
lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
|
|
if (valobj_sp)
|
|
valobj_sp->SetName(ConstString(idx_name.GetData()));
|
|
return valobj_sp;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
|
|
{}
|