This checkin removes the last Cocoa formatters that were implemented in Python and reimplements them in C++. The Python Cocoa formatters are not shipped as part of LLDB anymore, but still exist in the source repository for user reference. Python formatters still exist for STL classes and users can still define their own Python formatters

llvm-svn: 177366
This commit is contained in:
Enrico Granata 2013-03-19 00:27:22 +00:00
parent 9585fbfc67
commit 6d37cc6501
7 changed files with 150 additions and 46 deletions

View File

@ -5,7 +5,8 @@ part of The LLVM Compiler Infrastructure
This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
# summary provider for NSDate
# example summary provider for NSDate
# the real summary is now C++ code built into LLDB
import lldb
import ctypes
import lldb.runtime.objc.objc_runtime

View File

@ -115,6 +115,12 @@ namespace lldb_private {
bool
CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream);
bool
NSDateSummaryProvider (ValueObject& valobj, Stream& stream);
bool
CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream);
bool
NSBundleSummaryProvider (ValueObject& valobj, Stream& stream);

View File

@ -223,38 +223,11 @@ package_files="${SRC_ROOT}/examples/synthetic/gnu_libstdcpp.py
${SRC_ROOT}/examples/synthetic/libcxx.py"
create_python_package "/formatters/cpp" "${package_files}"
# lldb/formatters/objc
package_files="${SRC_ROOT}/examples/summaries/cocoa/Selector.py
${SRC_ROOT}/examples/summaries/objc.py
${SRC_ROOT}/examples/summaries/cocoa/Class.py
${SRC_ROOT}/examples/summaries/cocoa/CFArray.py
${SRC_ROOT}/examples/summaries/cocoa/CFBag.py
${SRC_ROOT}/examples/summaries/cocoa/CFBinaryHeap.py
${SRC_ROOT}/examples/summaries/cocoa/CFBitVector.py
${SRC_ROOT}/examples/summaries/cocoa/CFDictionary.py
${SRC_ROOT}/examples/summaries/cocoa/CFString.py
${SRC_ROOT}/examples/summaries/cocoa/NSBundle.py
${SRC_ROOT}/examples/summaries/cocoa/NSData.py
${SRC_ROOT}/examples/summaries/cocoa/NSDate.py
${SRC_ROOT}/examples/summaries/cocoa/NSException.py
${SRC_ROOT}/examples/summaries/cocoa/NSIndexSet.py
${SRC_ROOT}/examples/summaries/cocoa/NSMachPort.py
${SRC_ROOT}/examples/summaries/cocoa/NSNotification.py
${SRC_ROOT}/examples/summaries/cocoa/NSNumber.py
${SRC_ROOT}/examples/summaries/cocoa/NSSet.py
${SRC_ROOT}/examples/summaries/cocoa/NSURL.py"
create_python_package "/formatters/objc" "${package_files}"
# make an empty __init__.py in lldb/runtime
# this is required for Python to recognize lldb.runtime as a valid package
# (and hence, lldb.runtime.objc as a valid contained package)
create_python_package "/runtime" ""
# lldb/runtime/objc
package_files="${SRC_ROOT}/examples/summaries/cocoa/objc_runtime.py"
create_python_package "/runtime/objc" "${package_files}"
# lldb/formatters
# having these files copied here ensures that lldb/formatters is a valid package itself
package_files="${SRC_ROOT}/examples/summaries/cocoa/cache.py

View File

@ -9,6 +9,8 @@
#include "lldb/lldb-python.h"
#include <time.h>
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "llvm/Support/ConvertUTF.h"
@ -1618,6 +1620,131 @@ lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& s
return true;
}
// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
// this call gives the POSIX equivalent of the Cocoa epoch
time_t
GetOSXEpoch ()
{
static time_t epoch = 0;
if (!epoch)
{
tzset();
tm tm_epoch;
tm_epoch.tm_sec = 0;
tm_epoch.tm_hour = 0;
tm_epoch.tm_min = 0;
tm_epoch.tm_mon = 0;
tm_epoch.tm_mday = 1;
tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
tm_epoch.tm_isdst = -1;
tm_epoch.tm_gmtoff = 0;
tm_epoch.tm_zone = NULL;
epoch = timegm(&tm_epoch);
}
return epoch;
}
bool
lldb_private::formatters::NSDateSummaryProvider (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 date_value_bits = 0;
double date_value = 0.0;
const char* class_name = descriptor->GetClassName().GetCString();
if (!class_name || !*class_name)
return false;
if (strcmp(class_name,"NSDate") == 0 ||
strcmp(class_name,"__NSDate") == 0 ||
strcmp(class_name,"__NSTaggedDate") == 0)
{
if (descriptor->IsTagged())
{
uint64_t info_bits = (valobj_addr & 0xF0ULL) >> 4;
uint64_t value_bits = (valobj_addr & ~0x0000000000000000FFULL) >> 8;
date_value_bits = ((value_bits << 8) | (info_bits << 4));
date_value = *((double*)&date_value_bits);
}
else
{
Error error;
date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error);
date_value = *((double*)&date_value_bits);
if (error.Fail())
return false;
}
}
else if (!strcmp(class_name,"NSCalendarDate"))
{
Error error;
date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error);
date_value = *((double*)&date_value_bits);
if (error.Fail())
return false;
}
else
{
if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false)
return false;
date_value = *((double*)&date_value_bits);
}
if (date_value == -63114076800)
{
stream.Printf("0001-12-30 00:00:00 +0000");
return true;
}
// this snippet of code assumes that time_t == seconds since Jan-1-1970
// this is generally true and POSIXly happy, but might break if a library
// vendor decides to get creative
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)date_value;
tm *tm_date = localtime(&epoch);
if (!tm_date)
return false;
std::string buffer(1024,0);
if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
return false;
stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
return true;
}
bool
lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream)
{
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
tm *tm_date = localtime(&epoch);
if (!tm_date)
return false;
std::string buffer(1024,0);
if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
return false;
stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
return true;
}
size_t
lldb_private::formatters::ExtractIndexFromString (const char* item_name)
{

View File

@ -974,10 +974,10 @@ FormatManager::LoadObjCFormatters()
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.NSDate_SummaryProvider", ConstString("NSDate"), appkit_flags);
AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.NSDate_SummaryProvider", ConstString("__NSDate"), appkit_flags);
AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.NSDate_SummaryProvider", ConstString("__NSTaggedDate"), appkit_flags);
AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.NSDate_SummaryProvider", ConstString("NSCalendarDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags);
@ -986,7 +986,7 @@ FormatManager::LoadObjCFormatters()
// CFAbsoluteTime is actually a double rather than a pointer to an object
// we do not care about the numeric value, since it is probably meaningless to users
appkit_flags.SetDontShowValue(true);
AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.CFAbsoluteTime_SummaryProvider", ConstString("CFAbsoluteTime"), appkit_flags);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
appkit_flags.SetDontShowValue(false);
AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);

View File

@ -489,7 +489,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
// and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
run_string.Clear();
run_string.Printf ("run_one_line (%s, 'import lldb.runtime.objc, lldb.formatters, lldb.formatters.objc, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
int new_count = Debugger::TestDebuggerRefCount();

View File

@ -1433,16 +1433,16 @@ public:
m_class_bits = (value & 0xE) >> 1;
lldb::TargetSP target_sp = isa_pointer.GetTargetSP();
LazyBool is_lion = IsLion(target_sp);
uint32_t foundation_version = GetFoundationVersion(target_sp);
// TODO: check for OSX version - for now assume Mtn Lion
if (is_lion == eLazyBoolCalculate)
if (foundation_version == UINT32_MAX)
{
// if we can't determine the matching table (e.g. we have no Foundation),
// assume this is not a valid tagged pointer
m_valid = false;
}
else if (is_lion == eLazyBoolNo)
else if (foundation_version >= 900)
{
switch (m_class_bits)
{
@ -1571,13 +1571,14 @@ public:
{}
protected:
// TODO make this into a smarter OS version detector
LazyBool
IsLion (lldb::TargetSP &target_sp)
// we use the version of Foundation to make assumptions about the ObjC runtime on a target
uint32_t
GetFoundationVersion (lldb::TargetSP &target_sp)
{
if (!target_sp)
return eLazyBoolCalculate;
const ModuleList& modules = target_sp->GetImages();
uint32_t major = UINT32_MAX;
for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
{
lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
@ -1585,15 +1586,11 @@ protected:
continue;
if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
{
uint32_t major = UINT32_MAX;
module_sp->GetVersion(&major,1);
if (major == UINT32_MAX)
return eLazyBoolCalculate;
return (major > 900 ? eLazyBoolNo : eLazyBoolYes);
break;
}
}
return eLazyBoolCalculate;
return major;
}
private: