[Lldb-commits] [lldb] r136525 - in /lldb/trunk: examples/synthetic/CFString.py test/functionalities/data-formatter/data-formatter-objc/CFString.py test/functionalities/data-formatter/data-formatter-objc/Makefile test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py test/functionalities/data-formatter/data-formatter-objc/main.m
Enrico Granata
granata.enrico at gmail.com
Fri Jul 29 14:31:47 PDT 2011
Author: enrico
Date: Fri Jul 29 16:31:46 2011
New Revision: 136525
URL: http://llvm.org/viewvc/llvm-project?rev=136525&view=rev
Log:
new synthetic children provider for CFString and related classes ; test case for it
Added:
lldb/trunk/examples/synthetic/CFString.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile
lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m
Added: lldb/trunk/examples/synthetic/CFString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/CFString.py?rev=136525&view=auto
==============================================================================
--- lldb/trunk/examples/synthetic/CFString.py (added)
+++ lldb/trunk/examples/synthetic/CFString.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,206 @@
+# synthetic children provider for CFString
+# (and related NSString class)
+import lldb
+class CFStringSynthProvider:
+ def __init__(self,valobj,dict):
+ self.valobj = valobj;
+ self.update()
+ # children other than "content" are for debugging only and must not be used in production code
+ def num_children(self):
+ return 6;
+ def read_unicode(self, pointer):
+ process = self.valobj.GetTarget().GetProcess()
+ error = lldb.SBError()
+ pystr = u''
+ # cannot do the read at once because the length value has
+ # a weird encoding. better play it safe here
+ while True:
+ content = process.ReadMemory(pointer, 2, error)
+ new_bytes = bytearray(content)
+ b0 = new_bytes[0]
+ b1 = new_bytes[1]
+ pointer = pointer + 2
+ if b0 == 0 and b1 == 0:
+ break
+ # rearrange bytes depending on endianness
+ # (do we really need this or is Cocoa going to
+ # use Windows-compatible little-endian even
+ # if the target is big endian?)
+ if self.is_little:
+ value = b1 * 256 + b0
+ else:
+ value = b0 * 256 + b1
+ pystr = pystr + unichr(value)
+ return pystr
+ # handle the special case strings
+ # only use the custom code for the tested LP64 case
+ def handle_special(self):
+ if self.lp64 == False:
+ # for 32bit targets, use safe ObjC code
+ return self.handle_unicode_string_safe()
+ offset = 12
+ pointer = int(self.valobj.GetValue(), 0) + offset
+ pystr = self.read_unicode(pointer)
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + pystr.encode('utf-8') + "\"")
+ # last resort call, use ObjC code to read; the final aim is to
+ # be able to strip this call away entirely and only do the read
+ # ourselves
+ def handle_unicode_string_safe(self):
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + self.valobj.GetObjectDescription() + "\"");
+ def handle_unicode_string(self):
+ # step 1: find offset
+ if self.inline:
+ pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ if self.explicit == False:
+ # untested, use the safe code path
+ return self.handle_unicode_string_safe();
+ else:
+ # not sure why 8 bytes are skipped here
+ # (lldb) mem read -c 50 0x00000001001154f0
+ # 0x1001154f0: 98 1a 85 71 ff 7f 00 00 90 07 00 00 01 00 00 00 ...q?...........
+ # 0x100115500: 03 00 00 00 00 00 00 00 *c3 03 78 00 78 00 00 00 ........?.x.x...
+ # 0x100115510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ # 0x100115520: 00 00 ..
+ # content begins at * (i.e. 8 bytes into variants, skipping void* buffer in
+ # __notInlineImmutable1 entirely, while the length byte is correctly located
+ # for an inline string)
+ pointer = pointer + 8;
+ else:
+ pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ # read 8 bytes here and make an address out of them
+ vopointer = self.valobj.CreateChildAtOffset("dummy",
+ pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+ pointer = int(vopointer.GetValue(), 0)
+ # step 2: read Unicode data at pointer
+ pystr = self.read_unicode(pointer)
+ # step 3: return it
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + pystr.encode('utf-8') + "\"")
+ # we read at "the right place" into the __CFString object instead of running code
+ # we are replicating the functionality of __CFStrContents in CFString.c here
+ def handle_UTF8_inline(self):
+ offset = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ if self.explicit == False:
+ offset = offset + 1;
+ return self.valobj.CreateValueFromAddress("content",
+ offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+ def handle_UTF8_not_inline(self):
+ offset = self.size_of_cfruntime_base();
+ return self.valobj.CreateChildAtOffset("content",
+ offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+ def get_child_at_index(self,index):
+ if index == 0:
+ return self.valobj.CreateValueFromExpression("mutable",
+ str(int(self.mutable)));
+ if index == 1:
+ return self.valobj.CreateValueFromExpression("inline",
+ str(int(self.inline)));
+ if index == 2:
+ return self.valobj.CreateValueFromExpression("explicit",
+ str(int(self.explicit)));
+ if index == 3:
+ return self.valobj.CreateValueFromExpression("unicode",
+ str(int(self.unicode)));
+ if index == 4:
+ return self.valobj.CreateValueFromExpression("special",
+ str(int(self.special)));
+ if index == 5:
+ if self.unicode == True:
+ return self.handle_unicode_string();
+ elif self.special == True:
+ return self.handle_special();
+ elif self.inline == True:
+ return self.handle_UTF8_inline();
+ else:
+ return self.handle_UTF8_not_inline();
+ def get_child_index(self,name):
+ if name == "content":
+ return self.num_children() - 1;
+ if name == "mutable":
+ return 0;
+ if name == "inline":
+ return 1;
+ if name == "explicit":
+ return 2;
+ if name == "unicode":
+ return 3;
+ if name == "special":
+ return 4;
+ def is_64bit(self):
+ if self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8:
+ return True;
+ else:
+ return False;
+ def is_little_endian(self):
+ # 4 is eByteOrderLittle
+ if self.valobj.GetTarget().GetProcess().GetByteOrder() == 4:
+ return True;
+ else:
+ return False;
+ # CFRuntimeBase is defined as having an additional
+ # 4 bytes (padding?) on LP64 architectures
+ # to get its size we add up sizeof(pointer)+4
+ # and then add 4 more bytes if we are on a 64bit system
+ def size_of_cfruntime_base(self):
+ if self.lp64 == True:
+ return 8+4+4;
+ else:
+ return 4+4;
+ # the info bits are part of the CFRuntimeBase structure
+ # to get at them we have to skip a uintptr_t and then get
+ # at the least-significant byte of a 4 byte array. If we are
+ # on big-endian this means going to byte 3, if we are on
+ # little endian (OSX & iOS), this means reading byte 0
+ def offset_of_info_bits(self):
+ if self.lp64 == True:
+ offset = 8;
+ else:
+ offset = 4;
+ if self.is_little == False:
+ offset = offset + 3;
+ return offset;
+ def read_info_bits(self):
+ cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
+ self.offset_of_info_bits(),
+ self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+ cfinfo.SetFormat(11)
+ info = cfinfo.GetValue();
+ return int(info,0);
+ # calculating internal flag bits of the CFString object
+ # this stuff is defined and discussed in CFString.c
+ def is_mutable(self):
+ return (self.info_bits & 1) == 1;
+ def is_inline(self):
+ return (self.info_bits & 0x60) == 0;
+ # this flag's name is ambiguous, it turns out
+ # we must skip a length byte to get at the data
+ # when this flag is False
+ def has_explicit_length(self):
+ return (self.info_bits & (1 | 4)) != 4;
+ # probably a subclass of NSString. obtained this from [str pathExtension]
+ # here info_bits = 0 and Unicode data at the start of the padding word
+ # in the long run using the isa value might be safer as a way to identify this
+ # instead of reading the info_bits
+ def is_special_case(self):
+ return self.info_bits == 0;
+ def is_unicode(self):
+ return (self.info_bits & 0x10) == 0x10;
+ # preparing ourselves to read into memory
+ # by adjusting architecture-specific info
+ def adjust_for_architecture(self):
+ self.lp64 = self.is_64bit();
+ self.is_little = self.is_little_endian();
+ # reading info bits out of the CFString and computing
+ # useful values to get at the real data
+ def compute_flags(self):
+ self.info_bits = self.read_info_bits();
+ self.mutable = self.is_mutable();
+ self.inline = self.is_inline();
+ self.explicit = self.has_explicit_length();
+ self.unicode = self.is_unicode();
+ self.special = self.is_special_case();
+ def update(self):
+ self.adjust_for_architecture();
+ self.compute_flags();
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/CFString.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,206 @@
+# synthetic children provider for CFString
+# (and related NSString class)
+import lldb
+class CFStringSynthProvider:
+ def __init__(self,valobj,dict):
+ self.valobj = valobj;
+ self.update()
+ # children other than "content" are for debugging only and must not be used in production code
+ def num_children(self):
+ return 6;
+ def read_unicode(self, pointer):
+ process = self.valobj.GetTarget().GetProcess()
+ error = lldb.SBError()
+ pystr = u''
+ # cannot do the read at once because the length value has
+ # a weird encoding. better play it safe here
+ while True:
+ content = process.ReadMemory(pointer, 2, error)
+ new_bytes = bytearray(content)
+ b0 = new_bytes[0]
+ b1 = new_bytes[1]
+ pointer = pointer + 2
+ if b0 == 0 and b1 == 0:
+ break
+ # rearrange bytes depending on endianness
+ # (do we really need this or is Cocoa going to
+ # use Windows-compatible little-endian even
+ # if the target is big endian?)
+ if self.is_little:
+ value = b1 * 256 + b0
+ else:
+ value = b0 * 256 + b1
+ pystr = pystr + unichr(value)
+ return pystr
+ # handle the special case strings
+ # only use the custom code for the tested LP64 case
+ def handle_special(self):
+ if self.lp64 == False:
+ # for 32bit targets, use safe ObjC code
+ return self.handle_unicode_string_safe()
+ offset = 12
+ pointer = int(self.valobj.GetValue(), 0) + offset
+ pystr = self.read_unicode(pointer)
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + pystr.encode('utf-8') + "\"")
+ # last resort call, use ObjC code to read; the final aim is to
+ # be able to strip this call away entirely and only do the read
+ # ourselves
+ def handle_unicode_string_safe(self):
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + self.valobj.GetObjectDescription() + "\"");
+ def handle_unicode_string(self):
+ # step 1: find offset
+ if self.inline:
+ pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ if self.explicit == False:
+ # untested, use the safe code path
+ return self.handle_unicode_string_safe();
+ else:
+ # not sure why 8 bytes are skipped here
+ # (lldb) mem read -c 50 0x00000001001154f0
+ # 0x1001154f0: 98 1a 85 71 ff 7f 00 00 90 07 00 00 01 00 00 00 ...q?...........
+ # 0x100115500: 03 00 00 00 00 00 00 00 *c3 03 78 00 78 00 00 00 ........?.x.x...
+ # 0x100115510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ # 0x100115520: 00 00 ..
+ # content begins at * (i.e. 8 bytes into variants, skipping void* buffer in
+ # __notInlineImmutable1 entirely, while the length byte is correctly located
+ # for an inline string)
+ pointer = pointer + 8;
+ else:
+ pointer = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ # read 8 bytes here and make an address out of them
+ vopointer = self.valobj.CreateChildAtOffset("dummy",
+ pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+ pointer = int(vopointer.GetValue(), 0)
+ # step 2: read Unicode data at pointer
+ pystr = self.read_unicode(pointer)
+ # step 3: return it
+ return self.valobj.CreateValueFromExpression("content",
+ "(char*)\"" + pystr.encode('utf-8') + "\"")
+ # we read at "the right place" into the __CFString object instead of running code
+ # we are replicating the functionality of __CFStrContents in CFString.c here
+ def handle_UTF8_inline(self):
+ offset = int(self.valobj.GetValue(), 0) + self.size_of_cfruntime_base();
+ if self.explicit == False:
+ offset = offset + 1;
+ return self.valobj.CreateValueFromAddress("content",
+ offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+ def handle_UTF8_not_inline(self):
+ offset = self.size_of_cfruntime_base();
+ return self.valobj.CreateChildAtOffset("content",
+ offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+ def get_child_at_index(self,index):
+ if index == 0:
+ return self.valobj.CreateValueFromExpression("mutable",
+ str(int(self.mutable)));
+ if index == 1:
+ return self.valobj.CreateValueFromExpression("inline",
+ str(int(self.inline)));
+ if index == 2:
+ return self.valobj.CreateValueFromExpression("explicit",
+ str(int(self.explicit)));
+ if index == 3:
+ return self.valobj.CreateValueFromExpression("unicode",
+ str(int(self.unicode)));
+ if index == 4:
+ return self.valobj.CreateValueFromExpression("special",
+ str(int(self.special)));
+ if index == 5:
+ if self.unicode == True:
+ return self.handle_unicode_string();
+ elif self.special == True:
+ return self.handle_special();
+ elif self.inline == True:
+ return self.handle_UTF8_inline();
+ else:
+ return self.handle_UTF8_not_inline();
+ def get_child_index(self,name):
+ if name == "content":
+ return self.num_children() - 1;
+ if name == "mutable":
+ return 0;
+ if name == "inline":
+ return 1;
+ if name == "explicit":
+ return 2;
+ if name == "unicode":
+ return 3;
+ if name == "special":
+ return 4;
+ def is_64bit(self):
+ if self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8:
+ return True;
+ else:
+ return False;
+ def is_little_endian(self):
+ # 4 is eByteOrderLittle
+ if self.valobj.GetTarget().GetProcess().GetByteOrder() == 4:
+ return True;
+ else:
+ return False;
+ # CFRuntimeBase is defined as having an additional
+ # 4 bytes (padding?) on LP64 architectures
+ # to get its size we add up sizeof(pointer)+4
+ # and then add 4 more bytes if we are on a 64bit system
+ def size_of_cfruntime_base(self):
+ if self.lp64 == True:
+ return 8+4+4;
+ else:
+ return 4+4;
+ # the info bits are part of the CFRuntimeBase structure
+ # to get at them we have to skip a uintptr_t and then get
+ # at the least-significant byte of a 4 byte array. If we are
+ # on big-endian this means going to byte 3, if we are on
+ # little endian (OSX & iOS), this means reading byte 0
+ def offset_of_info_bits(self):
+ if self.lp64 == True:
+ offset = 8;
+ else:
+ offset = 4;
+ if self.is_little == False:
+ offset = offset + 3;
+ return offset;
+ def read_info_bits(self):
+ cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
+ self.offset_of_info_bits(),
+ self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+ cfinfo.SetFormat(11)
+ info = cfinfo.GetValue();
+ return int(info,0);
+ # calculating internal flag bits of the CFString object
+ # this stuff is defined and discussed in CFString.c
+ def is_mutable(self):
+ return (self.info_bits & 1) == 1;
+ def is_inline(self):
+ return (self.info_bits & 0x60) == 0;
+ # this flag's name is ambiguous, it turns out
+ # we must skip a length byte to get at the data
+ # when this flag is False
+ def has_explicit_length(self):
+ return (self.info_bits & (1 | 4)) != 4;
+ # probably a subclass of NSString. obtained this from [str pathExtension]
+ # here info_bits = 0 and Unicode data at the start of the padding word
+ # in the long run using the isa value might be safer as a way to identify this
+ # instead of reading the info_bits
+ def is_special_case(self):
+ return self.info_bits == 0;
+ def is_unicode(self):
+ return (self.info_bits & 0x10) == 0x10;
+ # preparing ourselves to read into memory
+ # by adjusting architecture-specific info
+ def adjust_for_architecture(self):
+ self.lp64 = self.is_64bit();
+ self.is_little = self.is_little_endian();
+ # reading info bits out of the CFString and computing
+ # useful values to get at the real data
+ def compute_flags(self):
+ self.info_bits = self.read_info_bits();
+ self.mutable = self.is_mutable();
+ self.inline = self.is_inline();
+ self.explicit = self.has_explicit_length();
+ self.unicode = self.is_unicode();
+ self.special = self.is_special_case();
+ def update(self):
+ self.adjust_for_architecture();
+ self.compute_flags();
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/Makefile Fri Jul 29 16:31:46 2011
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation
Added: 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=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py Fri Jul 29 16:31:46 2011
@@ -0,0 +1,231 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class DataFormatterTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-objc")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ def test_with_dsym_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDsym()
+ self.data_formatter_commands()
+
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.m', '// Set break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ self.expect("breakpoint set -f main.m -l %d" % self.line,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 1: file ='main.m', line = %d, locations = 1" %
+ self.line)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs = ['stopped',
+ 'stop reason = breakpoint'])
+
+ # This is the function to remove the custom formats in order to have a
+ # clean slate for the next test case.
+ def cleanup():
+ self.runCmd('type format clear', check=False)
+ self.runCmd('type summary clear', check=False)
+ self.runCmd('type synth clear', check=False)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ self.runCmd("type summary add -f \"${var%@}\" MyClass")
+
+ self.expect("frame variable object2",
+ substrs = ['MyOtherClass']);
+
+ self.expect("frame variable *object2",
+ substrs = ['MyOtherClass']);
+
+ # Now let's delete the 'MyClass' custom summary.
+ self.runCmd("type summary delete MyClass")
+
+ # The type format list should not show 'MyClass' at this point.
+ self.expect("type summary list", matching=False,
+ substrs = ['MyClass'])
+
+ self.runCmd("type summary add -f \"a test\" MyClass")
+
+ self.expect("frame variable object2",
+ substrs = ['a test']);
+
+ self.expect("frame variable *object2",
+ substrs = ['a test']);
+
+ self.expect("frame variable object",
+ substrs = ['a test']);
+
+ self.expect("frame variable *object",
+ substrs = ['a test']);
+
+ self.runCmd("type summary add -f \"a test\" MyClass -C no")
+
+ self.expect("frame variable *object2",
+ substrs = ['*object2 = {',
+ 'MyClass = a test',
+ 'backup = ']);
+
+ self.expect("frame variable object2", matching=False,
+ substrs = ['a test']);
+
+ self.expect("frame variable object",
+ substrs = ['a test']);
+
+ self.expect("frame variable *object",
+ substrs = ['a test']);
+
+ # Now check that the synth for CFString works
+ self.runCmd("script from CFString import *")
+ self.runCmd("type synth add -l CFStringSynthProvider NSString")
+
+ self.expect('frame variable str -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'A rather short ASCII NSString object is here'])
+
+ self.expect('frame variable str2 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'A rather short UTF8 NSString object is here'])
+
+ self.expect('frame variable str3 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'A string made with the at sign is here'])
+
+ self.expect('frame variable str4 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'This is string number 4 right here'])
+
+ self.expect('frame variable str5 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ '{{1, 1}, {5, 5}}'])
+
+ self.expect('frame variable str6 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ '1ST'])
+
+ self.expect('frame variable str7 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ '\\xcf\\x83xx'])
+
+ self.expect('frame variable str8 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'hasVeryLongExtensionThisTime'])
+
+ self.expect('frame variable str9 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+
+ self.expect('frame variable str10 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'This is a Unicode string \\xcf\\x83 number 4 right here'])
+
+ self.expect('frame variable str11 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ '__NSCFString'])
+
+ self.expect('frame variable processName -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'a.out'])
+
+ self.expect('frame variable str12 -P 1',
+ substrs = ['mutable =',
+ 'inline = ',
+ 'explicit = ',
+ 'content = ',
+ 'Process Name: a.out Process Id:'])
+
+ # make it a summary
+ self.runCmd("type summary add -f \"${svar.content}\" NSString")
+
+ self.expect('frame variable str',
+ substrs = ['A rather short ASCII NSString object is here'])
+ self.expect('frame variable str2',
+ substrs = ['A rather short UTF8 NSString object is here'])
+ self.expect('frame variable str3',
+ substrs = ['A string made with the at sign is here'])
+ self.expect('frame variable str4',
+ substrs = ['This is string number 4 right here'])
+ self.expect('frame variable str5',
+ substrs = ['{{1, 1}, {5, 5}}'])
+ self.expect('frame variable str6',
+ substrs = ['1ST'])
+ self.expect('frame variable str7',
+ substrs = ['\\xcf\\x83xx'])
+ self.expect('frame variable str8',
+ substrs = ['hasVeryLongExtensionThisTime'])
+ self.expect('frame variable str9',
+ substrs = ['a very much boring task to write a string this way!!\\xe4\\x8c\\xb3'])
+ self.expect('frame variable str10',
+ substrs = ['This is a Unicode string \\xcf\\x83 number 4 right here'])
+ self.expect('frame variable str11',
+ substrs = ['__NSCFString'])
+ self.expect('frame variable processName',
+ substrs = ['a.out'])
+ self.expect('frame variable str12',
+ substrs = ['Process Name: a.out Process Id:'])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m?rev=136525&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/main.m Fri Jul 29 16:31:46 2011
@@ -0,0 +1,124 @@
+//===-- main.m ------------------------------------------------*- ObjC -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#import <Foundation/Foundation.h>
+
+ at interface MyClass : NSObject
+{
+ int i;
+ char c;
+ float f;
+}
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z;
+- (int)doIncrementByInt: (int)x;
+
+ at end
+
+ at interface MyOtherClass : MyClass
+{
+ int i2;
+ MyClass *backup;
+}
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q;
+
+ at end
+
+ at implementation MyClass
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z
+{
+ self = [super init];
+ if (self) {
+ self->i = x;
+ self->f = y;
+ self->c = z;
+ }
+ return self;
+}
+
+- (int)doIncrementByInt: (int)x
+{
+ self->i += x;
+ return self->i;
+}
+
+ at end
+
+ at implementation MyOtherClass
+
+- (id)initWithInt: (int)x andFloat:(float)y andChar:(char)z andOtherInt:(int)q
+{
+ self = [super initWithInt:x andFloat:y andChar:z];
+ if (self) {
+ self->i2 = q;
+ self->backup = [[MyClass alloc] initWithInt:x andFloat:y andChar:z];
+ }
+ return self;
+}
+
+ at end
+
+int main (int argc, const char * argv[])
+{
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ MyClass *object = [[MyClass alloc] initWithInt:1 andFloat:3.14 andChar: 'E'];
+
+ [object doIncrementByInt:3];
+
+ MyOtherClass *object2 = [[MyOtherClass alloc] initWithInt:2 andFloat:6.28 andChar: 'G' andOtherInt:-1];
+
+ [object2 doIncrementByInt:3];
+
+ NSString *str = [NSString stringWithCString:"A rather short ASCII NSString object is here" encoding:NSASCIIStringEncoding];
+
+ NSString *str2 = [NSString stringWithUTF8String:"A rather short UTF8 NSString object is here"];
+
+ NSString *str3 = @"A string made with the at sign is here";
+
+ NSString *str4 = [NSString stringWithFormat:@"This is string number %ld right here", (long)4];
+
+ NSRect rect = NSMakeRect(1,1,5,5);
+
+ NSString* str5 = NSStringFromRect(rect);
+
+ NSString* str6 = [@"/usr/doc/README.1ST" pathExtension];
+
+ const unichar myCharacters[] = {0x03C3,'x','x'};
+ NSString *str7 = [NSString stringWithCharacters: myCharacters
+ length: sizeof myCharacters / sizeof *myCharacters];
+
+ NSString* str8 = [@"/usr/doc/file.hasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTimehasVeryLongExtensionThisTime" pathExtension];
+
+ const unichar myOtherCharacters[] = {'a',' ', 'v','e','r','y',' ',
+ 'm','u','c','h',' ','b','o','r','i','n','g',' ','t','a','s','k',
+ ' ','t','o',' ','w','r','i','t','e', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ',
+ 't','h','i','s',' ','w','a','y','!','!','0x03C3'};
+ NSString *str9 = [NSString stringWithCharacters: myOtherCharacters
+ length: sizeof myOtherCharacters / sizeof *myOtherCharacters];
+
+ const unichar myNextCharacters[] = {0x03C3, 0x0000};
+
+ NSString *str10 = [NSString stringWithFormat:@"This is a Unicode string %S number %ld right here", myNextCharacters, (long)4];
+
+ NSString *str11 = [str10 className];
+
+ NSString *label1 = @"Process Name: ";
+ NSString *label2 = @"Process Id: ";
+ NSString *processName = [[NSProcessInfo processInfo] processName];
+ NSString *processID = [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]];
+ NSString *str12 = [NSString stringWithFormat:@"%@ %@ %@ %@", label1, processName, label2, processID];
+
+ // Set break point at this line.
+ [pool drain];
+ return 0;
+}
+
More information about the lldb-commits
mailing list