forked from OSchip/llvm-project
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:
parent
9585fbfc67
commit
6d37cc6501
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue