[Lldb-commits] [lldb] r224306 - If a binary was stripped we sometimes didn't show the ivars of an Objective C class correctly. Now we do as we consult the runtime data for the class so we don't have to have a symbol in the symbol table.
Greg Clayton
gclayton at apple.com
Mon Dec 15 17:33:17 PST 2014
Author: gclayton
Date: Mon Dec 15 19:33:17 2014
New Revision: 224306
URL: http://llvm.org/viewvc/llvm-project?rev=224306&view=rev
Log:
If a binary was stripped we sometimes didn't show the ivars of an Objective C class correctly. Now we do as we consult the runtime data for the class so we don't have to have a symbol in the symbol table.
Fixed:
1 - try the symbol table symbol for an ObjC ivar and use it if available
2 - fall back to using the runtime data since it is slower to gather via memory read
3 - Fixed our hidden ivars test case to test this to ensure we don't regress
4 - split out a test case in the hidden ivars to cover only the part that was failing so we don't have an expected failure for all of the other content in the test.
<rdar://problem/18882687>
Modified:
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/trunk/test/lang/objc/hidden-ivars/TestHiddenIvars.py
lldb/trunk/test/lang/objc/hidden-ivars/main.m
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=224306&r1=224305&r2=224306&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Mon Dec 15 19:33:17 2014
@@ -554,36 +554,52 @@ AppleObjCRuntimeV2::CreateObjectChecker(
size_t
AppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const char *ivar_name)
{
+ uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
+
const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
+ if (class_name && class_name[0] && ivar_name && ivar_name[0])
+ {
+ //----------------------------------------------------------------------
+ // Make the objective C V2 mangled name for the ivar offset from the
+ // class name and ivar name
+ //----------------------------------------------------------------------
+ std::string buffer("OBJC_IVAR_$_");
+ buffer.append (class_name);
+ buffer.push_back ('.');
+ buffer.append (ivar_name);
+ ConstString ivar_const_str (buffer.c_str());
+
+ //----------------------------------------------------------------------
+ // Try to get the ivar offset address from the symbol table first using
+ // the name we created above
+ //----------------------------------------------------------------------
+ SymbolContextList sc_list;
+ Target &target = m_process->GetTarget();
+ target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
+
+ addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
+
+ Error error;
+ SymbolContext ivar_offset_symbol;
+ if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol))
+ {
+ if (ivar_offset_symbol.symbol)
+ ivar_offset_address = ivar_offset_symbol.symbol->GetAddress().GetLoadAddress (&target);
+ }
+
+ //----------------------------------------------------------------------
+ // If we didn't get the ivar offset address from the symbol table, fall
+ // back to getting it from the runtime
+ //----------------------------------------------------------------------
+ if (ivar_offset_address == LLDB_INVALID_ADDRESS)
+ ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
- if (!class_name || *class_name == '\0' || !ivar_name || *ivar_name == '\0')
- return LLDB_INVALID_IVAR_OFFSET;
-
- std::string buffer("OBJC_IVAR_$_");
- buffer.append (class_name);
- buffer.push_back ('.');
- buffer.append (ivar_name);
- ConstString ivar_const_str (buffer.c_str());
-
- SymbolContextList sc_list;
- Target &target = m_process->GetTarget();
-
- target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
-
- SymbolContext ivar_offset_symbol;
- if (sc_list.GetSize() != 1
- || !sc_list.GetContextAtIndex(0, ivar_offset_symbol)
- || ivar_offset_symbol.symbol == NULL)
- return LLDB_INVALID_IVAR_OFFSET;
-
- addr_t ivar_offset_address = ivar_offset_symbol.symbol->GetAddress().GetLoadAddress (&target);
-
- Error error;
-
- uint32_t ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
- 4,
- LLDB_INVALID_IVAR_OFFSET,
- error);
+ if (ivar_offset_address != LLDB_INVALID_ADDRESS)
+ ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
+ 4,
+ LLDB_INVALID_IVAR_OFFSET,
+ error);
+ }
return ivar_offset;
}
Modified: lldb/trunk/test/lang/objc/hidden-ivars/TestHiddenIvars.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/hidden-ivars/TestHiddenIvars.py?rev=224306&r1=224305&r2=224306&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/hidden-ivars/TestHiddenIvars.py (original)
+++ lldb/trunk/test/lang/objc/hidden-ivars/TestHiddenIvars.py Mon Dec 15 19:33:17 2014
@@ -5,6 +5,7 @@ import unittest2
import lldb
from lldbtest import *
import lldbutil
+import subprocess
class HiddenIvarsTestCase(TestBase):
@@ -15,34 +16,74 @@ class HiddenIvarsTestCase(TestBase):
def test_expr_with_dsym(self):
if self.getArchitecture() == 'i386':
self.skipTest("requires modern objc runtime")
- self.buildDsym()
- self.expr()
+ else:
+ self.buildDsym()
+ self.expr(False)
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_expr_stripped_with_dsym(self):
+ if self.getArchitecture() == 'i386':
+ self.skipTest("requires modern objc runtime")
+ else:
+ self.buildDsym()
+ self.expr(True)
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dwarf_test
def test_expr_with_dwarf(self):
if self.getArchitecture() == 'i386':
self.skipTest("requires modern objc runtime")
- self.buildDwarf()
- self.expr()
+ else:
+ self.buildDwarf()
+ self.expr(False)
- @unittest2.expectedFailure("rdar://18683637")
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dsym_test
def test_frame_variable_with_dsym(self):
if self.getArchitecture() == 'i386':
self.skipTest("requires modern objc runtime")
- self.buildDsym()
- self.frame_var()
+ else:
+ self.buildDsym()
+ self.frame_var(False)
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_frame_variable_stripped_with_dsym(self):
+ if self.getArchitecture() == 'i386':
+ self.skipTest("requires modern objc runtime")
+ else:
+ self.buildDsym()
+ self.frame_var(True)
- @unittest2.expectedFailure("rdar://18683637")
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dwarf_test
def test_frame_variable_with_dwarf(self):
if self.getArchitecture() == 'i386':
self.skipTest("requires modern objc runtime")
- self.buildDwarf()
- self.frame_var()
+ else:
+ self.buildDwarf()
+ self.frame_var(False)
+
+ @unittest2.expectedFailure("rdar://18683637")
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_frame_variable_across_modules_with_dsym(self):
+ if self.getArchitecture() == 'i386':
+ self.skipTest("requires modern objc runtime")
+ else:
+ self.buildDsym()
+ self.frame_var_type_access_across_module()
+
+ @unittest2.expectedFailure("rdar://18683637")
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dwarf_test
+ def test_frame_variable_across_modules_with_dwarf(self):
+ if self.getArchitecture() == 'i386':
+ self.skipTest("requires modern objc runtime")
+ else:
+ self.buildDwarf()
+ self.frame_var_type_access_across_module()
def setUp(self):
# Call super's setUp().
@@ -54,8 +95,12 @@ class HiddenIvarsTestCase(TestBase):
# The names should have no loading "lib" or extension as they will be localized
self.shlib_names = ["InternalDefiner"]
- def common_setup(self):
+ def common_setup(self, strip):
+ if strip:
+ self.assertTrue(subprocess.call(['/usr/bin/strip', '-Sx', 'libInternalDefiner.dylib']) == 0, 'stripping dylib succeeded')
+ self.assertTrue(subprocess.call(['/bin/rm', '-rf', 'libInternalDefiner.dylib.dSYM']) == 0, 'remove dylib dSYM file succeeded')
+ self.assertTrue(subprocess.call(['/usr/bin/strip', '-Sx', 'a.out']) == 0, 'stripping a.out succeeded')
# Create a target by the debugger.
target = self.dbg.CreateTarget("a.out")
self.assertTrue(target, VALID_TARGET)
@@ -88,8 +133,8 @@ class HiddenIvarsTestCase(TestBase):
self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
substrs = [' resolved, hit count = 1'])
- def expr(self):
- self.common_setup()
+ def expr(self, strip):
+ self.common_setup(strip)
# This should display correctly.
self.expect("expression (j->_definer->foo)", VARIABLES_DISPLAYED_CORRECTLY,
@@ -97,9 +142,13 @@ class HiddenIvarsTestCase(TestBase):
self.expect("expression (j->_definer->bar)", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["= 5"])
-
- self.expect("expression *(j->_definer)", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["foo = 4", "bar = 5"])
+
+ if strip:
+ self.expect("expression *(j->_definer)", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 4"])
+ else:
+ self.expect("expression *(j->_definer)", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 4", "bar = 5"])
self.expect("expression (k->foo)", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["= 2"])
@@ -107,30 +156,52 @@ class HiddenIvarsTestCase(TestBase):
self.expect("expression (k->bar)", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["= 3"])
- self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["foo = 2", "bar = 3"])
+ self.expect("expression k.filteredDataSource", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = [' = 0x', '"2 objects"'])
- def frame_var(self):
- self.common_setup()
+ if strip:
+ self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 2", ' = 0x', '"2 objects"'])
+ else:
+ self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 2", "bar = 3", '_filteredDataSource = 0x', '"2 objects"'])
+
+ def frame_var(self, strip):
+ self.common_setup(strip)
# This should display correctly.
self.expect("frame variable j->_definer->foo", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["= 4"])
- self.expect("frame variable j->_definer->bar", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["= 5"])
+ if not strip:
+ self.expect("frame variable j->_definer->bar", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["= 5"])
- self.expect("frame variable *j->_definer", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["foo = 4", "bar = 5"])
+ if strip:
+ self.expect("frame variable *j->_definer", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 4"])
+ else:
+ self.expect("frame variable *j->_definer", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 4", "bar = 5"])
self.expect("frame variable k->foo", VARIABLES_DISPLAYED_CORRECTLY,
substrs = ["= 2"])
- self.expect("frame variable k->bar", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["= 3"])
+ self.expect("frame variable k->_filteredDataSource", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = [' = 0x', '"2 objects"'])
+
+ if strip:
+ self.expect("frame variable *k", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 2", '_filteredDataSource = 0x', '"2 objects"'])
+ else:
+ self.expect("frame variable *k", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["foo = 2", "bar = 3", '_filteredDataSource = 0x', '"2 objects"'])
+
+ def frame_var_type_access_across_module(self):
+ self.common_setup(False)
+
+ self.expect("frame variable k->bar", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["= 3"])
- self.expect("frame variable *k", VARIABLES_DISPLAYED_CORRECTLY,
- substrs = ["foo = 2", "bar = 3"])
if __name__ == '__main__':
import atexit
Modified: lldb/trunk/test/lang/objc/hidden-ivars/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/hidden-ivars/main.m?rev=224306&r1=224305&r2=224306&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/hidden-ivars/main.m (original)
+++ lldb/trunk/test/lang/objc/hidden-ivars/main.m Mon Dec 15 19:33:17 2014
@@ -23,9 +23,7 @@
@end
@interface InheritContainer : InternalDefiner
-{
-}
-
+ at property (nonatomic, strong) NSMutableArray *filteredDataSource;
-(id)init;
@end
@@ -35,6 +33,7 @@
{
if (self = [super initWithFoo:2 andBar:3])
{
+ self.filteredDataSource = [NSMutableArray arrayWithObjects:@"hello", @"world", nil];
}
return self;
}
More information about the lldb-commits
mailing list