[Lldb-commits] [lldb] r136763 - in /lldb/trunk: include/lldb/Core/FormatManager.h source/Core/ValueObject.cpp source/Core/ValueObjectDynamicValue.cpp source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
Enrico Granata
granata.enrico at gmail.com
Tue Aug 2 19:18:51 PDT 2011
Author: enrico
Date: Tue Aug 2 21:18:51 2011
New Revision: 136763
URL: http://llvm.org/viewvc/llvm-project?rev=136763&view=rev
Log:
Fixed an issue where the KVO swizzled type would be returned as the dynamic type instead of the actual user-level type
- see the test case in lang/objc/objc-dynamic-value for an example
Objective-C dynamic type lookup now works for every Objective-C type
- previously, true dynamic lookup was only performed for type id
Modified:
lldb/trunk/include/lldb/Core/FormatManager.h
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Tue Aug 2 21:18:51 2011
@@ -360,12 +360,13 @@
if (log)
log->Printf("appended bitfield info, final result is %s", name.GetCString());
}
+ const char* typeName = name.GetCString();
if (log)
log->Printf("trying to get %s for VO name %s of type %s",
m_name.c_str(),
vobj.GetName().AsCString(),
- name.AsCString());
- if (Get(name.GetCString(), entry))
+ typeName);
+ if (Get(typeName, entry))
{
if (log)
log->Printf("direct match found, returning");
@@ -385,7 +386,8 @@
}
}
if (use_dynamic != lldb::eNoDynamicValues &&
- typePtr == vobj.GetClangAST()->ObjCBuiltinIdTy.getTypePtr())
+ (/*strstr(typeName, "id") == typeName ||*/
+ ClangASTType::GetMinimumLanguage(vobj.GetClangAST(), vobj.GetClangType()) == lldb::eLanguageTypeObjC))
{
if (log)
log->Printf("this is an ObjC 'id', let's do dynamic search");
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Tue Aug 2 21:18:51 2011
@@ -93,7 +93,7 @@
m_is_bitfield_for_scalar(false),
m_is_expression_path_child(false),
m_is_child_at_offset(false),
- m_is_expression_result(false),
+ m_is_expression_result(parent.m_is_expression_result),
m_dump_printable_counter(0)
{
m_manager->ManageObject(this);
@@ -240,7 +240,7 @@
m_synthetic_value = NULL;
- Debugger::Formatting::ValueFormats::Get(*this, use_dynamic, m_last_value_format);
+ Debugger::Formatting::ValueFormats::Get(*this, lldb::eNoDynamicValues, m_last_value_format);
Debugger::Formatting::GetSummaryFormat(*this, use_dynamic, m_last_summary_format);
Debugger::Formatting::GetSyntheticFilter(*this, use_dynamic, m_last_synthetic_filter);
@@ -2599,23 +2599,26 @@
// Always show the type for the top level items.
if (show_types || (curr_depth == 0 && !flat_output))
{
- s.Printf("(%s", valobj->GetTypeName().AsCString("<invalid type>"));
- if (use_dynamic != lldb::eNoDynamicValues &&
- strcmp(valobj->GetTypeName().AsCString("NULL"), "id") == 0)
+ const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
+ s.Printf("(%s", typeName);
+ // only show dynamic types if the user really wants to see types
+ if (show_types && use_dynamic != lldb::eNoDynamicValues &&
+ (/*strstr(typeName, "id") == typeName ||*/
+ ClangASTType::GetMinimumLanguage(valobj->GetClangAST(), valobj->GetClangType()) == lldb::eLanguageTypeObjC))
{
Process* process = valobj->GetUpdatePoint().GetProcessSP().get();
if (process == NULL)
- s.Printf(") ");
+ s.Printf(", dynamic type: unknown) ");
else
{
ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
if (runtime == NULL)
- s.Printf(") ");
+ s.Printf(", dynamic type: unknown) ");
else
{
ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(*valobj);
if (!runtime->IsValidISA(isa))
- s.Printf(") ");
+ s.Printf(", dynamic type: unknown) ");
else
s.Printf(", dynamic type: %s) ",
runtime->GetActualTypeName(isa).GetCString());
Modified: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Tue Aug 2 21:18:51 2011
@@ -160,7 +160,7 @@
{
LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
if (objc_runtime)
- found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
+ found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
}
}
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Tue Aug 2 21:18:51 2011
@@ -26,6 +26,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -566,9 +567,35 @@
lldb_private::ObjCLanguageRuntime::ObjCISA
AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
{
+
+ if (valobj.GetIsExpressionResult() &&
+ valobj.GetValue().GetValueType() == Value::eValueTypeHostAddress)
+ {
+ // when using the expression parser, an additional layer of "frozen data"
+ // can be created, which is basically a byte-exact copy of the data returned
+ // by the expression, but in host memory. because Python code might need to read
+ // into the object memory in non-obvious ways, we need to hand it the target version
+ // of the expression output
+ lldb::addr_t tgt_address = valobj.GetValueAsUnsigned();
+ ValueObjectSP target_object = ValueObjectConstResult::Create (valobj.GetExecutionContextScope(),
+ valobj.GetClangAST(),
+ valobj.GetClangType(),
+ valobj.GetName(),
+ tgt_address,
+ eAddressTypeLoad,
+ valobj.GetUpdatePoint().GetProcessSP()->GetAddressByteSize());
+ return GetISA(*target_object);
+ }
+
if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != lldb::eLanguageTypeObjC)
return 0;
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
+ return 0;
+
uint32_t offset = 0;
uint64_t isa_pointer = valobj.GetDataExtractor().GetPointer(&offset);
@@ -583,6 +610,8 @@
return isa;
}
+// TODO: should we have a transparent_kvo parameter here to say if we
+// want to replace the KVO swizzled class with the actual user-level type?
ConstString
AppleObjCRuntimeV2::GetActualTypeName(lldb_private::ObjCLanguageRuntime::ObjCISA isa)
{
@@ -625,7 +654,20 @@
//printf("name_pointer: %llx\n", name_pointer);
char* cstr = new char[512];
if (m_process->ReadCStringFromMemory(name_pointer, cstr, 512) > 0)
- return ConstString(cstr);
+ {
+ if (::strstr(cstr, "NSKVONotify") == cstr)
+ {
+ // the ObjC runtime implements KVO by replacing the isa with a special
+ // NSKVONotifying_className that overrides the relevant methods
+ // the side effect on us is that getting the typename for a KVO-ed object
+ // will return the swizzled class instead of the actual one
+ // this swizzled class is a descendant of the real class, so just
+ // return the parent type and all should be fine
+ return GetActualTypeName(GetParentClass(isa));
+ }
+ else
+ return ConstString(cstr);
+ }
else
return ConstString("unknown");
}
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py Tue Aug 2 21:18:51 2011
@@ -226,9 +226,12 @@
substrs = ['Process Name: a.out Process Id:'])
self.expect('frame variable dyn_test', matching=False,
substrs = ['Process Name: a.out Process Id:'])
- self.expect('frame variable dyn_test -d run-target',
+ self.expect('frame variable dyn_test -d run-target -T',
substrs = ['(id, dynamic type:',
'Process Name: a.out Process Id:'])
+ self.expect('frame variable dyn_test -d run-target',
+ substrs = ['(id)',
+ 'Process Name: a.out Process Id:'])
# check that we can format stuff out of the expression parser
Modified: lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py (original)
+++ lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py Tue Aug 2 21:18:51 2011
@@ -93,6 +93,14 @@
self.expect('frame var -d run-target myObserver->_source', 'frame var finds its way into a child member',
patterns = ['\(SourceDerived \*\)'])
+
+ # check that our ObjC GetISA() does a good job at hiding KVO swizzled classes
+
+ self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden',
+ substrs = ['dynamic type: SourceDerived'])
+
+ self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching = False,
+ substrs = ['dynamic type: NSKVONotify'])
# This test is not entirely related to the main thrust of this test case, but since we're here,
# try stepping into setProperty, and make sure we get into the version in Source:
More information about the lldb-commits
mailing list