The data formatters for NSArray, NSDictionary and (only partially) NSSet contain logic to inspect the objects without running code.

However, they also contain fallback logic that - in cases where LLDB can't recognize the specific subclass - actually does run code in order to inspect those objects.

The argument for this logic was that these data types are critical enough that the risk of getting it wrong is outweighed by the advantage of always providing accurate child information.

Practical experience however shows that "po" - a code running data-inspection command - is quite frequently used, and not considered burdensome by users.
As such, this makes the code-running fallback in the data formatters a risk that carries very little actual reward. Also, unlike the time this code was originally written, we now have accurate class information for Objective-C, and thus we are less likely to improperly identify classes.

This commit removes support for the code-running fallback, and aligns the data formatters for NSArray, NSDictionary and NSSet to the general no-code-running behavior of other data formatters.

While it is possible for us to add support for some subclasses that are now no longer covered by static inspection alone, this is beyond the scope of this commit.

llvm-svn: 260664
This commit is contained in:
Enrico Granata 2016-02-12 07:50:15 +00:00
parent 47134196fc
commit 2543d29048
7 changed files with 8 additions and 222 deletions

View File

@ -214,18 +214,13 @@ class ObjCDataFormatterTestCase(TestBase):
'(NSNumber *) num_at4 = ',' (double)-12.5'])
def nscontainers_data_formatter_commands(self):
self.expect('frame variable newArray newDictionary newMutableDictionary cfdict_ref mutable_dict_ref cfarray_ref mutable_array_ref',
self.expect('frame variable newArray newDictionary newMutableDictionary cfarray_ref mutable_array_ref',
substrs = ['(NSArray *) newArray = ','@"50 elements"',
'(NSDictionary *) newDictionary = ',' 12 key/value pairs',
'(NSDictionary *) newMutableDictionary = ',' 21 key/value pairs',
'(CFDictionaryRef) cfdict_ref = ','3 key/value pairs',
'(CFMutableDictionaryRef) mutable_dict_ref = ','12 key/value pairs',
'(CFArrayRef) cfarray_ref = ','@"3 elements"',
'(CFMutableArrayRef) mutable_array_ref = ','@"11 elements"'])
self.expect('frame variable nscounted_set',
substrs = ['(NSCountedSet *) nscounted_set = ','5 elements'])
self.expect('frame variable iset1 iset2 imset',
substrs = ['4 indexes','512 indexes','10 indexes'])

View File

@ -415,41 +415,6 @@ int main (int argc, const char * argv[])
CFStringRef cfstring_ref = CFSTR("HELLO WORLD");
CFSetRef set_ref = CFSetCreate(NULL, data_set, 3, NULL);
CFMutableSetRef mutable_set_ref = CFSetCreateMutable(NULL, 5, NULL);
CFSetAddValue(mutable_set_ref, str1);
CFSetAddValue(mutable_set_ref, str2);
CFSetAddValue(mutable_set_ref, str3);
CFSetAddValue(mutable_set_ref, str4);
CFSetAddValue(mutable_set_ref, str5);
CFSetAddValue(mutable_set_ref, str6);
CFSetAddValue(mutable_set_ref, str7);
CFSetAddValue(mutable_set_ref, str8);
CFSetAddValue(mutable_set_ref, str9);
CFSetAddValue(mutable_set_ref, str10);
CFSetAddValue(mutable_set_ref, str11);
CFSetAddValue(mutable_set_ref, str12);
CFDictionaryRef cfdict_ref = CFDictionaryCreate(NULL, data_set, data_set, 3, NULL, NULL);
CFMutableDictionaryRef mutable_dict_ref = CFDictionaryCreateMutable(NULL, 16, NULL, NULL);
CFDictionarySetValue(mutable_dict_ref, str1, str1);
CFDictionarySetValue(mutable_dict_ref, str2, str2);
CFDictionarySetValue(mutable_dict_ref, str3, str3);
CFDictionarySetValue(mutable_dict_ref, str4, str1);
CFDictionarySetValue(mutable_dict_ref, str5, str2);
CFDictionarySetValue(mutable_dict_ref, str6, str3);
CFDictionarySetValue(mutable_dict_ref, str7, str1);
CFDictionarySetValue(mutable_dict_ref, str8, str2);
CFDictionarySetValue(mutable_dict_ref, str9, str3);
CFDictionarySetValue(mutable_dict_ref, str10, str1);
CFDictionarySetValue(mutable_dict_ref, str11, str2);
CFDictionarySetValue(mutable_dict_ref, str12, str3);
CFArrayRef cfarray_ref = CFArrayCreate(NULL, data_set, 3, NULL);
CFMutableArrayRef mutable_array_ref = CFArrayCreateMutable(NULL, 16, NULL);
@ -556,16 +521,6 @@ int main (int argc, const char * argv[])
CFAbsoluteTime date3_abs = CFDateGetAbsoluteTime(date3);
CFAbsoluteTime date4_abs = CFDateGetAbsoluteTime(date4);
NSCountedSet *nscounted_set = [[NSCountedSet alloc] initWithCapacity:5];
[nscounted_set addObject:str0];
[nscounted_set addObject:str1];
[nscounted_set addObject:str0];
[nscounted_set addObject:str0];
[nscounted_set addObject:@"foo1"];
[nscounted_set addObject:@"foo2"];
[nscounted_set addObject:@"foo3"];
NSIndexSet *iset1 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 4)];
NSIndexSet *iset2 = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(1, 512)];

View File

@ -69,10 +69,6 @@ class DataFormatterOneIsSingularTestCase(TestBase):
substrs = ['@"1 value"'])
self.expect('frame variable mutable_bag_ref', matching=False,
substrs = ['1 values'])
self.expect('frame variable nscounted_set',
substrs = ['1 element'])
self.expect('frame variable nscounted_set', matching=False,
substrs = ['1 elements'])
self.expect('frame variable imset',
substrs = ['1 index'])
self.expect('frame variable imset', matching=False,
@ -81,10 +77,6 @@ class DataFormatterOneIsSingularTestCase(TestBase):
substrs = ['@"1 item"'])
self.expect('frame variable binheap_ref', matching=False,
substrs = ['1 items'])
self.expect('frame variable nsset',
substrs = ['1 element'])
self.expect('frame variable nsset', matching=False,
substrs = ['1 elements'])
self.expect('frame variable immutableData',
substrs = ['1 byte'])
self.expect('frame variable immutableData', matching=False,

View File

@ -22,17 +22,12 @@ int main (int argc, const char * argv[])
CFMutableBagRef mutable_bag_ref = CFBagCreateMutable(NULL, 15, NULL);
CFBagSetValue(mutable_bag_ref, CFSTR("Hello world"));
NSCountedSet *nscounted_set = [[NSCountedSet alloc] initWithCapacity:5];
[nscounted_set addObject:@"foo"];
NSMutableIndexSet *imset = [[NSMutableIndexSet alloc] init];
[imset addIndex:4];
CFBinaryHeapRef binheap_ref = CFBinaryHeapCreate(NULL, 15, &kCFStringBinaryHeapCallBacks, NULL);
CFBinaryHeapAddValue(binheap_ref, CFSTR("Hello world"));
NSSet* nsset = [[NSSet alloc] initWithObjects:@"foo",nil];
NSData *immutableData = [[NSData alloc] initWithBytes:"HELLO" length:1];

View File

@ -227,29 +227,6 @@ namespace lldb_private {
size_t
GetIndexOfChildWithName(const ConstString &name) override;
};
class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
~NSArrayCodeRunningSyntheticFrontEnd() override = default;
size_t
CalculateNumChildren() override;
lldb::ValueObjectSP
GetChildAtIndex(size_t idx) override;
bool
Update() override;
bool
MightHaveChildren() override;
size_t
GetIndexOfChildWithName(const ConstString &name) override;
};
} // namespace formatters
} // namespace lldb_private
@ -312,10 +289,7 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s
return false;
}
else
{
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
return false;
}
std::string prefix,suffix;
if (Language* language = Language::FindPlugin(options.GetLanguage()))
@ -740,53 +714,6 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
else
return (new NSArrayMSyntheticFrontEnd_109(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("[%" PRIu64 "]", (uint64_t)idx);
lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
if (valobj_sp)
{
valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage());
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;
return nullptr;
}

View File

@ -190,29 +190,6 @@ namespace lldb_private {
CompilerType m_pair_type;
std::vector<DictionaryItemDescriptor> m_children;
};
class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
~NSDictionaryCodeRunningSyntheticFrontEnd() override = default;
size_t
CalculateNumChildren() override;
lldb::ValueObjectSP
GetChildAtIndex(size_t idx) override;
bool
Update() override;
bool
MightHaveChildren() override;
size_t
GetIndexOfChildWithName(const ConstString &name) override;
};
} // namespace formatters
} // namespace lldb_private
@ -282,7 +259,7 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
return iter->second(valobj, stream, options);
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
else
return false;
}
@ -350,64 +327,9 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
return iter->second(synth, valobj_sp);
return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
}
}
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get())
{}
size_t
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
{
uint64_t count = 0;
if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
return count;
return 0;
}
lldb::ValueObjectSP
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
StreamString key_fetcher_expr;
key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
StreamString value_fetcher_expr;
value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
StreamString object_fetcher_expr;
object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
lldb::ValueObjectSP child_sp;
EvaluateExpressionOptions options;
options.SetKeepInMemory(true);
options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
options.SetResultIsInternal(true);
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
GetViableFrame(m_backend.GetTargetSP().get()),
child_sp,
options);
if (child_sp)
child_sp->SetName(ConstString(idx_name.GetData()));
return child_sp;
}
bool
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
{
return false;
}
bool
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
{
return true;
}
size_t
lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
return 0;
return nullptr;
}
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :

View File

@ -277,7 +277,7 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
return iter->second(valobj, stream, options);
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
else
return false;
}
@ -349,7 +349,7 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
return iter->second(synth, valobj_sp);
return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
return nullptr;
}
}