示例#1
0
def classItselfImplementsSelector(klass, selector):
    thisMethod = objc.class_getInstanceMethod(klass, selector)
    if thisMethod == 0:
        return False

    superklass = objc.class_getSuperclass(klass)
    superMethod = objc.class_getInstanceMethod(superklass, selector)
    if thisMethod == superMethod:
        return False
    else:
        return True
示例#2
0
    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(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(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(breakpointFullName, breakpointCondition))
        else:
            breakpointPattern = r"{}\[{}(\(.+\))? {}\]".format(
                methodTypeCharacter, breakpointClassName, selector)
            lldb.debugger.HandleCommand(
                'breakpoint set --skip-prologue false --func-regex "{}" --condition "{}"'
                .format(breakpointPattern, breakpointCondition))