def functionPreambleExpressionForSelector(): import re arch = objc.currentArch() expressionForSelector = None if arch == 'i386': expressionForSelector = '*(id*)($esp+8)' elif arch == 'x86_64': expressionForSelector = '(id)$rsi' elif arch == 'arm64': expressionForSelector = '(id)$x1' elif re.match(r'^armv.*$', arch): expressionForSelector = '(id)$r1' return expressionForSelector
def isMac(): arch = objc.currentArch() if arch == "x86_64": return True return False
def is64Bit(): arch = objc.currentArch() if arch == "arm64": return True return False
def run(self, arguments, options): expression = arguments[0] methodPattern = re.compile( r""" (?P<scope>[-+])? \[ (?P<target>.*?) (?P<category>\(.+\))? \s+ (?P<selector>.*) \] """, re.VERBOSE, ) match = methodPattern.match(expression) if not match: print("Failed to parse expression. Do you even Objective-C?!") return expressionForSelf = objc.functionPreambleExpressionForSelf() if not expressionForSelf: arch = objc.currentArch() print( "Your architecture, {}, is truly fantastic. However, I don't currently support it." .format( # noqa B950 arch)) return methodTypeCharacter = match.group("scope") classNameOrExpression = match.group("target") category = match.group("category") selector = match.group("selector") methodIsClassMethod = methodTypeCharacter == "+" if not methodIsClassMethod: # The default is instance method, and methodTypeCharacter # may not actually be '-'. methodTypeCharacter = "-" targetIsClass = False targetObject = fb.evaluateObjectExpression( "({})".format(classNameOrExpression), False) if not targetObject: # If the expression didn't yield anything then it's likely a class. # Assume it is. We will check again that the class does actually # exist anyway. targetIsClass = True targetObject = fb.evaluateObjectExpression( "[{} class]".format(classNameOrExpression), False) 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)) return if methodIsClassMethod: targetClass = objc.object_getClass(targetClass) found = False nextClass = targetClass while not found and int(nextClass, 0) > 0: if classItselfImplementsSelector(nextClass, selector): found = True else: 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( # noqa B950 selector)) return breakpointClassName = objc.class_getName(nextClass) formattedCategory = category if category else "" breakpointFullName = "{}[{}{} {}]".format(methodTypeCharacter, breakpointClassName, formattedCategory, selector) if targetIsClass: breakpointCondition = "(void*)object_getClass({}) == {}".format( expressionForSelf, targetClass) else: breakpointCondition = "(void*){} == {}".format( expressionForSelf, targetObject) print("Setting a breakpoint at {} with condition {}".format( breakpointFullName, breakpointCondition)) if category: lldb.debugger.HandleCommand( 'breakpoint set --skip-prologue false --fullname "{}" --condition "{}"' .format( # noqa B950 breakpointFullName, breakpointCondition)) else: breakpointPattern = r"{}\[{}(\(.+\))? {}\]".format( methodTypeCharacter, breakpointClassName, selector) lldb.debugger.HandleCommand( 'breakpoint set --skip-prologue false --func-regex "{}" --condition "{}"' .format( # noqa B950 breakpointPattern, breakpointCondition))