Skip to content

Commit

Permalink
Make chisel compatible with Python 3 (#266)
Browse files Browse the repository at this point in the history
* Make chisel compatible with Python 3

Xcode 11 shipped with Python 3 now. Unfortunately, chisel was written in
Python 2 style and will fail load for lldb. This PR fixed the Python 3
compatibility issues.

* Addressed comment. Updated with file output.

* Properly resolve the conflict.

* Import from future on print.

* Address @lsavino comment.
  • Loading branch information
liuliu authored and kolinkrewinkel committed Oct 11, 2019
1 parent dcff372 commit 7782bdd
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 109 deletions.
8 changes: 4 additions & 4 deletions commands/FBAccessibilityCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ def printAccessibilityHierarchy(view, indent = 0):

#if we don't have any accessibility string - we should have some children
if int(a11yLabel.GetValue(), 16) == 0:
print indentString + ('{} {}'.format(classDesc, view))
print(indentString + ('{} {}'.format(classDesc, view)))
#We call private method that gives back all visible accessibility children for view
a11yElements = accessibilityElements(view)
accessibilityElementsCount = int(fb.evaluateExpression('(int)[%s count]' % a11yElements))
for index in range(0, accessibilityElementsCount):
subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (a11yElements, index))
printAccessibilityHierarchy(subview, indent + 1)
else:
print indentString + ('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription()))
print(indentString + ('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription())))

def printAccessibilityIdentifiersHierarchy(view, indent = 0):
a11yIdentifier = accessibilityIdentifier(view)
Expand All @@ -143,12 +143,12 @@ def printAccessibilityIdentifiersHierarchy(view, indent = 0):

#if we don't have any accessibility identifier - we should have some children
if int(a11yIdentifier.GetValue(), 16) == 0:
print indentString + ('{} {}'.format(classDesc, view))
print(indentString + ('{} {}'.format(classDesc, view)))
#We call private method that gives back all visible accessibility children for view
a11yElements = accessibilityElements(view)
accessibilityElementsCount = int(fb.evaluateExpression('(int)[%s count]' % a11yElements))
for index in range(0, accessibilityElementsCount):
subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (a11yElements, index))
printAccessibilityIdentifiersHierarchy(subview, indent + 1)
else:
print indentString + ('({} {}) {}'.format(classDesc, view, a11yIdentifier.GetObjectDescription()))
print(indentString + ('({} {}) {}'.format(classDesc, view, a11yIdentifier.GetObjectDescription())))
2 changes: 1 addition & 1 deletion commands/FBAutoLayoutCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def run(self, arguments, options):
view = fb.evaluateInputExpression(arguments[0])
opt = fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]')
traceCall = '_autolayoutTraceRecursively:1' if opt else '_autolayoutTrace'
print fb.describeObject('[{} {}]'.format(view, traceCall))
print(fb.describeObject('[{} {}]'.format(view, traceCall)))


def setBorderOnAmbiguousViewRecursive(view, width, color):
Expand Down
20 changes: 10 additions & 10 deletions commands/FBClassDump.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ def run(self, arguments, options):
cls = getClassFromArgument(arguments[0], options.clsname)

if options.clsmethod:
print 'Class Methods:'
print('Class Methods:')
printClassMethods(cls, options.showaddr)

if options.insmethod:
print '\nInstance Methods:'
print('\nInstance Methods:')
printInstanceMethods(cls, options.showaddr)

if not options.clsmethod and not options.insmethod:
print 'Class Methods:'
print('Class Methods:')
printClassMethods(cls, options.showaddr)
print '\nInstance Methods:'
print('\nInstance Methods:')
printInstanceMethods(cls, options.showaddr)


Expand Down Expand Up @@ -147,15 +147,15 @@ def run(self, arguments, options):

signature = json['signature']
if not signature:
print 'Imp: ' + hex(json['invoke'])
print('Imp: ' + hex(json['invoke']))
return

sigStr = '{} ^('.format(decode(signature[0]))
# the block`s implementation always take the block as it`s first argument, so we ignore it
sigStr += ', '.join([decode(m) for m in signature[2:]])
sigStr += ');'

print 'Imp: ' + hex(json['invoke']) + ' Signature: ' + sigStr
print('Imp: ' + hex(json['invoke']) + ' Signature: ' + sigStr)

# helpers
def isClassObject(arg):
Expand All @@ -178,21 +178,21 @@ def getClassFromArgument(arg, is_classname):
def printInstanceMethods(cls, showaddr=False, prefix='-'):
methods = getMethods(cls)
if not methods:
print "No methods were found"
print("No methods were found")

for m in methods:
if showaddr:
print prefix + ' ' + m.prettyPrintString() + ' ' + str(m.imp)
print(prefix + ' ' + m.prettyPrintString() + ' ' + str(m.imp))
else:
print prefix + ' ' + m.prettyPrintString()
print(prefix + ' ' + m.prettyPrintString())

def printClassMethods(cls, showaddr=False):
printInstanceMethods(runtimeHelpers.object_getClass(cls), showaddr, '+')

def printProperties(cls, showvalue=False):
props = getProperties(cls)
for p in props:
print p.prettyPrintString()
print(p.prettyPrintString())

def decode(code):
encodeMap = {
Expand Down
8 changes: 4 additions & 4 deletions commands/FBComponentCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ def options(self):
def run(self, arguments, options):
if options.set:
fb.evaluateEffect('[CKComponentDebugController setDebugMode:YES]')
print 'Debug mode for ComponentKit has been set.'
print('Debug mode for ComponentKit has been set.')
elif options.unset:
fb.evaluateEffect('[CKComponentDebugController setDebugMode:NO]')
print 'Debug mode for ComponentKit has been unset.'
print('Debug mode for ComponentKit has been unset.')
else:
print 'No option for ComponentKit Debug mode specified.'
print('No option for ComponentKit Debug mode specified.')

class FBComponentsPrintCommand(fb.FBCommand):
def name(self):
Expand All @@ -67,7 +67,7 @@ def run(self, arguments, options):
# assume it's a CKComponent
view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view)

print fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']')
print(fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']'))

class FBComponentsReflowCommand(fb.FBCommand):
def name(self):
Expand Down
47 changes: 25 additions & 22 deletions commands/FBDebugCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# Can be removed when Python 2 support is removed.
from __future__ import print_function

import lldb
import fblldbbase as fb
import fblldbobjcruntimehelpers as objc
Expand Down Expand Up @@ -58,9 +61,9 @@ def run(self, arguments, options):
watchpoint = lldb.debugger.GetSelectedTarget().WatchAddress(objectAddress + ivarOffset, ivarSize, False, True, error)

if error.Success():
print 'Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID())
print('Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID()))
else:
print 'Could not create the watchpoint: {}'.format(error.GetCString())
print('Could not create the watchpoint: {}'.format(error.GetCString()))

class FBFrameworkAddressBreakpointCommand(fb.FBCommand):
def name(self):
Expand Down Expand Up @@ -108,12 +111,12 @@ def run(self, arguments, options):
match = methodPattern.match(expression)

if not match:
print 'Failed to parse expression. Do you even Objective-C?!'
print('Failed to parse expression. Do you even Objective-C?!')
return

expressionForSelf = objc.functionPreambleExpressionForSelf()
if not expressionForSelf:
print 'Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch)
print('Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch))
return

methodTypeCharacter = match.group('scope')
Expand All @@ -139,7 +142,7 @@ def run(self, arguments, options):
targetClass = fb.evaluateObjectExpression('[{} class]'.format(targetObject), False)

if not targetClass or int(targetClass, 0) == 0:
print 'Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression)
print('Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression))
return

if methodIsClassMethod:
Expand All @@ -155,7 +158,7 @@ def run(self, arguments, options):
nextClass = objc.class_getSuperclass(nextClass)

if not found:
print 'There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector)
print('There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector))
return

breakpointClassName = objc.class_getName(nextClass)
Expand All @@ -167,7 +170,7 @@ def run(self, arguments, options):
else:
breakpointCondition = '(void*){} == {}'.format(expressionForSelf, targetObject)

print 'Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition)
print('Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition))

if category:
lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --fullname "{}" --condition "{}"'.format(breakpointFullName, breakpointCondition))
Expand Down Expand Up @@ -205,11 +208,11 @@ def switchBreakpointState(expression,on):
target = lldb.debugger.GetSelectedTarget()
for breakpoint in target.breakpoint_iter():
if breakpoint.IsEnabled() != on and (expression_pattern.search(str(breakpoint))):
print str(breakpoint)
print(str(breakpoint))
breakpoint.SetEnabled(on)
for location in breakpoint:
if location.IsEnabled() != on and (expression_pattern.search(str(location)) or expression == hex(location.GetAddress()) ):
print str(location)
print(str(location))
location.SetEnabled(on)

class FBMethodBreakpointEnableCommand(fb.FBCommand):
Expand Down Expand Up @@ -330,7 +333,7 @@ def run(self, arguments, options):
return

if len(arguments) == 0 or not arguments[0].strip():
print 'Usage: findinstances <classOrProtocol> [<predicate>]; Run `help findinstances`'
print('Usage: findinstances <classOrProtocol> [<predicate>]; Run `help findinstances`')
return

query = arguments[0]
Expand All @@ -348,7 +351,7 @@ def loadChiselIfNecessary(self):

path = self.chiselLibraryPath()
if not os.path.exists(path):
print 'Chisel library missing: ' + path
print('Chisel library missing: ' + path)
return False

module = fb.evaluateExpressionValue('(void*)dlopen("{}", 2)'.format(path))
Expand All @@ -361,17 +364,17 @@ def loadChiselIfNecessary(self):
error = fb.evaluateExpressionValue('(char*)dlerror()')
if errno == 50:
# KERN_CODESIGN_ERROR from <mach/kern_return.h>
print 'Error loading Chisel: Code signing failure; Must re-run codesign'
print('Error loading Chisel: Code signing failure; Must re-run codesign')
elif error.unsigned != 0:
print 'Error loading Chisel: ' + error.summary
print('Error loading Chisel: ' + error.summary)
elif errno != 0:
error = fb.evaluateExpressionValue('(char*)strerror({})'.format(errno))
if error.unsigned != 0:
print 'Error loading Chisel: ' + error.summary
print('Error loading Chisel: ' + error.summary)
else:
print 'Error loading Chisel (errno {})'.format(errno)
print('Error loading Chisel (errno {})'.format(errno))
else:
print 'Unknown error loading Chisel'
print('Unknown error loading Chisel')

return False

Expand Down Expand Up @@ -428,9 +431,9 @@ def isHeap(addr):

allocations = (addr for addr in pointers if isHeap(addr))
for addr in allocations:
print >>self.result, '0x{addr:x} {path}'.format(addr=addr, path=pointers[addr])
print('0x{addr:x} {path}'.format(addr=addr, path=pointers[addr]), file=self.result)
if not allocations:
print >>self.result, "No heap addresses found"
print("No heap addresses found", file=self.result)


class FBSequenceCommand(fb.FBCommand):
Expand All @@ -453,17 +456,17 @@ def run(self, arguments, options):

# Complete one command before running the next one in the sequence. Disable
# async to do this. Also, save the current async value to restore it later.
async = lldb.debugger.GetAsync()
asyncFlag = lldb.debugger.GetAsync()
lldb.debugger.SetAsync(False)

for command in commands[:-1]:
success = self.run_command(interpreter, command)
if not success:
lldb.debugger.SetAsync(async)
lldb.debugger.SetAsync(asyncFlag)
return

# Restore original async value.
lldb.debugger.SetAsync(async)
lldb.debugger.SetAsync(asyncFlag)

# If the last command is `continue`, call Continue() on the process
# instead. This is done because HandleCommand('continue') has strange
Expand All @@ -478,7 +481,7 @@ def run_command(self, interpreter, command):
ret = lldb.SBCommandReturnObject()
interpreter.HandleCommand(command, ret)
if ret.GetOutput():
print >>self.result, ret.GetOutput().strip()
print(ret.GetOutput().strip(), file=self.result)

if ret.Succeeded():
return True
Expand Down
2 changes: 1 addition & 1 deletion commands/FBFindCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,6 @@ def run(self, arguments, options):
@staticmethod
def taplog_callback(frame, bp_loc, internal_dict):
parameterExpr = objc.functionPreambleExpressionForObjectParameterAtIndex(0)
print fb.describeObject('[[[%s allTouches] anyObject] view]' % (parameterExpr))
print(fb.describeObject('[[[%s allTouches] anyObject] view]' % (parameterExpr)))
# We don't want to proceed event (click on button for example), so we just skip it
lldb.debugger.HandleCommand('thread return')
18 changes: 9 additions & 9 deletions commands/FBFlickerCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def args(self):
return [ fb.FBCommandArgument(arg='view', type='UIView*', help='The view to border.') ]

def run(self, arguments, options):
print '\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n'
print('\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n')

object = fb.evaluateInputExpression(arguments[0])
walker = FlickerWalker(object)
Expand All @@ -78,29 +78,29 @@ def inputCallback(self, input):
cmd = 'echo %s | tr -d "\n" | pbcopy' % oldView
os.system(cmd)

print '\nI hope ' + oldView + ' was what you were looking for. I put it on your clipboard.'
print('\nI hope ' + oldView + ' was what you were looking for. I put it on your clipboard.')
viewHelpers.unmaskView(oldView)
self.keepRunning = False

elif input == 'w':
v = superviewOfView(self.currentView)
if not v:
print 'There is no superview. Where are you trying to go?!'
print('There is no superview. Where are you trying to go?!')
self.setCurrentView(v, oldView)
elif input == 's':
v = firstSubviewOfView(self.currentView)
if not v:
print '\nThe view has no subviews.\n'
print('\nThe view has no subviews.\n')
self.setCurrentView(v, oldView)
elif input == 'd':
v = nthSiblingOfView(self.currentView, -1)
if v == oldView:
print '\nThere are no sibling views to this view.\n'
print('\nThere are no sibling views to this view.\n')
self.setCurrentView(v, oldView)
elif input == 'a':
v = nthSiblingOfView(self.currentView, 1)
if v == oldView:
print '\nThere are no sibling views to this view.\n'
print('\nThere are no sibling views to this view.\n')
self.setCurrentView(v, oldView)
elif input == 'p':
recursionName = 'recursiveDescription'
Expand All @@ -109,17 +109,17 @@ def inputCallback(self, input):
if isMac:
recursionName = '_subtreeDescription'

print fb.describeObject('[(id){} {}]'.format(oldView, recursionName))
print(fb.describeObject('[(id){} {}]'.format(oldView, recursionName)))
else:
print '\nI really have no idea what you meant by \'' + input + '\'... =\\\n'
print('\nI really have no idea what you meant by \'' + input + '\'... =\\\n')

def setCurrentView(self, view, oldView=None):
if view:
self.currentView = view
if oldView:
viewHelpers.unmaskView(oldView)
viewHelpers.maskView(self.currentView, 'red', '0.4')
print fb.describeObject(view)
print(fb.describeObject(view))

def superviewOfView(view):
superview = fb.evaluateObjectExpression('[' + view + ' superview]')
Expand Down
Loading

0 comments on commit 7782bdd

Please sign in to comment.