Пример #1
0
def properties(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        properties <className/classInstance>

    Examples:
        (lldb) properties UIViewController
        (lldb) properties [NSObject new]

        (lldb) expression -l objc -O -- [NSObject new]
        <NSObject: 0x60000372f760>
        (lldb) properties 0x60000372f760

    This command is implemented in HMClassInfoCommands.py
    """

    if len(command) == 0:
        HM.DPrint(
            "Requires a argument, Please enter \"help properties\" for help.")
        return

    value = HM.evaluateExpressionValue(
        expression=
        f'(NSString *)[{command} performSelector:NSSelectorFromString(@"_propertyDescription")]',
        printErrors=False)
    if HM.successOfSBError(value.GetError()):
        HM.DPrint(value.GetObjectDescription())
        return

    clsPrefixesValue = HM.getClassPrefixes()[1]
    command_script = f'''
        Class inputClass = objc_lookUpClass("{command}");

        if (inputClass == nil) {{   //  Find prefixed class
            for (NSString *prefix in (NSMutableArray *){clsPrefixesValue.GetValue()}) {{
                NSString *clsName = [prefix stringByAppendingString:@".{command}"];
                inputClass = objc_lookUpClass((char *)[clsName UTF8String]);
                if (inputClass) {{
                    break;
                }}
            }}
        }}

        NSMutableString *result = [[NSMutableString alloc] init];
        if (inputClass == nil) {{
            [result appendString:@"Unable to resolve {command} or find {command} class, maybe {command} is not a subclass of NSObject\\n"];
        }} else {{
            if ((BOOL)[(Class)inputClass respondsToSelector:(SEL)NSSelectorFromString(@"_propertyDescription")]) {{
                [result appendString:(NSString *)[inputClass performSelector:NSSelectorFromString(@"_propertyDescription")]];
            }} else {{
                [result appendString:@"{command} is not a subclass of NSObject"];
            }}
        }}

        result;
    '''

    result = HM.evaluateExpressionValue(command_script).GetObjectDescription()
    HM.DPrint(result)
Пример #2
0
def findSuperClass(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        fsuperclass <className>

    Examples:
        (lldb) fsuperclass UIButton

    This command is implemented in HMClassInfoCommands.py
    """

    if len(command) == 0:
        HM.DPrint(
            "Requires a argument, Please enter \"help fsuperclass\" for help.")
        return

    clsPrefixesValue = HM.getClassPrefixes()[1]
    command_script = f'''
        Class inputClass = objc_lookUpClass("{command}");

        if (inputClass == nil) {{   //  Find prefixed class
            for (NSString *prefix in (NSMutableArray *){clsPrefixesValue.GetValue()}) {{
                NSString *clsName = [prefix stringByAppendingString:@".{command}"];
                inputClass = objc_lookUpClass((char *)[clsName UTF8String]);
                if (inputClass) {{
                    break;
                }}
            }}
        }}

        NSMutableString *result = [[NSMutableString alloc] init];
        if (inputClass == nil) {{
            [result appendString:@"Can't find {command} class\\n"];
        }} else {{
            [result appendString:[[NSString alloc] initWithUTF8String:class_getName(inputClass)]];
            for (Class superClass = class_getSuperclass(inputClass); superClass != nil; superClass = class_getSuperclass(superClass)) {{
                NSString *name = [[NSString alloc] initWithUTF8String:class_getName(superClass)];
                [result appendFormat:@" : %@", name];
            }}
        }}

        result;
    '''

    classNames = HM.evaluateExpressionValue(
        command_script).GetObjectDescription()
    HM.DPrint(classNames)
Пример #3
0
def push(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        push <className>
        push [--instance] <instance>

    Options:
        --instance/-i; Push the UIViewController instance.

    Examples:
        (lldb) push PersonalViewController
        (lldb) push -i [[PersonalViewController alloc] init]

        (lldb) expression -l objc -O -- [PersonalViewController new]
        <PersonalViewController: 0x7fed30c5a070>
        (lldb) push -i 0x7fed30c5a070

    Notice:
        "push MyViewController" needs to execute "[[MyViewController alloc] init]" first.
        If the initializer of the class requires parameters, or the class needs to pass parameters after initialization, this command may cause errors.

    This command is implemented in HMPushViewController.py
    """

    # HM.DPrint(type(command))  # <class 'str'>
    # HM.DPrint(type(exe_ctx))  # <class 'lldb.SBExecutionContext'>
    # HM.DPrint(type(result))  # <class 'lldb.SBCommandReturnObject'>
    # HM.DPrint(type(internal_dict))  # <class 'dict'>


    command_args = shlex.split(command)
    parser = generate_option_parser()
    try:
        # options: optparse.Values
        # args: list
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    if len(args) == 0:
        HM.DPrint("Error input, plase enter 'help push' for more infomation")
        return

    HM.DPrint("Waiting...")

    navigationVC = getNavigationVC()
    if navigationVC is None:
        HM.DPrint("Cannot find a UINavigationController")
        return

    state = False
    if options.instance:
        instanceExpr: str = ""
        for string in args:
            instanceExpr += string + " "
        instanceExpr = instanceExpr.rstrip()
        VCObject = HM.evaluateExpressionValue(instanceExpr).GetValue()
    else:
        makeVCExpression = f"(UIViewController *)[[NSClassFromString(@\"{args[0]}\") alloc] init]"
        VCObject = HM.evaluateExpressionValue(makeVCExpression).GetValue()     # address

    if verifyObjIsKindOfClass(VCObject, "UIViewController"):
        pushExpression = f"(void)[{navigationVC} pushViewController:(id){VCObject} animated:YES]"
        debugger.HandleCommand('expression -l objc -O -- ' + pushExpression)
        state = True
    elif not options.instance:
        classPrefixes = HM.getClassPrefixes()[0]
        for prefix in classPrefixes:  # for Swift file
            className = f"{prefix}.{args[0]}"
            if not HM.existClass(className):
                continue

            makeVCExpression = f"(UIViewController *)[[NSClassFromString(@\"{className}\") alloc] init]"
            VCObject = HM.evaluateExpressionValue(makeVCExpression).GetValue()  # address
            if verifyObjIsKindOfClass(VCObject, "UIViewController"):
                pushExpression = f"(void)[{navigationVC} pushViewController:(id){VCObject} animated:YES]"
                debugger.HandleCommand('expression -l objc -O -- ' + pushExpression)
                state = True
                break

    HM.DPrint("push succeed" if state else "push failed")
    if state:
        HM.processContinue()
Пример #4
0
def methods(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        methods [--short] <className/classInstance>

    Examples:
        (lldb) methods UIViewController
        (lldb) methods -s UIViewController
        (lldb) methods [UIView new]

        (lldb) expression -l objc -O -- [NSObject new]
        <NSObject: 0x60000375f9a0>
        (lldb) methods 0x60000375f9a0

    Options:
        --short/-s; Use [inputClass _shortMethodDescription] instead of [inputClass _methodDescription]

    This command is implemented in HMClassInfoCommands.py
    """

    command_args = shlex.split(command)
    parser = generate_methods_option_parser()
    try:
        # options: optparse.Values
        # args: list
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    inputStr: str = ""
    for string in args:
        inputStr += string + " "
    inputStr = inputStr.rstrip()

    if len(inputStr) == 0:
        HM.DPrint(
            "Requires a argument, Please enter \"help methods\" for help.")
        return

    if options.short:
        selName = "_shortMethodDescription"
    else:
        selName = "_methodDescription"

    value = HM.evaluateExpressionValue(
        expression=
        f'(NSString *)[{inputStr} performSelector:NSSelectorFromString(@"{selName}")]',
        printErrors=False)
    if HM.successOfSBError(value.GetError()):
        HM.DPrint(value.GetObjectDescription())
        return

    clsPrefixesValue = HM.getClassPrefixes()[1]
    command_script = f'''
        Class inputClass = objc_lookUpClass("{inputStr}");

        if (inputClass == nil) {{   //  Find prefixed class
            for (NSString *prefix in (NSMutableArray *){clsPrefixesValue.GetValue()}) {{
                NSString *clsName = [prefix stringByAppendingString:@".{inputStr}"];
                inputClass = objc_lookUpClass((char *)[clsName UTF8String]);
                if (inputClass) {{
                    break;
                }}
            }}
        }}

        NSMutableString *result = [[NSMutableString alloc] init];
        if (inputClass == nil) {{
            [result appendString:@"Unable to resolve {inputStr} or find {inputStr} class, maybe {inputStr} is not a subclass of NSObject\\n"];
        }} else {{
            if ((BOOL)[(Class)inputClass respondsToSelector:(SEL)NSSelectorFromString(@"{selName}")]) {{
                [result appendString:(NSString *)[inputClass performSelector:NSSelectorFromString(@"{selName}")]];
            }} else {{
                [result appendString:@"{inputStr} is not a subclass of NSObject"];
            }}
        }}

        result;
    '''

    result = HM.evaluateExpressionValue(command_script).GetObjectDescription()
    HM.DPrint(result)
Пример #5
0
def findMethod(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        fmethod <methodName>  (Case insensitive.)
        fmethod [--class] <className>

    Options:
        --class/-c; Find all method in the class

    Examples:
        (lldb) fmethod viewdid
        (lldb) fmethod viewDidLayoutSubviews
        (lldb) fmethod -c UITableViewController

    This command is implemented in HMClassInfoCommands.py
    """

    command_args = shlex.split(command)
    parser = generate_findMethod_option_parser()
    try:
        # options: optparse.Values
        # args: list
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    if not options.cls:
        if len(args) != 1:
            HM.DPrint("Error input, Please enter \"help fmethod\" for help.")
            return
        elif len(args[0]) <= 5:
            HM.DPrint("Argument length must be greater than 5.")
            return

    HM.DPrint("Waiting...")

    if options.cls:
        clsPrefixesValue = HM.getClassPrefixes()[1]
        command_script = f'''
            NSMutableString *result = [[NSMutableString alloc] init];
            Class inputClass = objc_lookUpClass("{options.cls}");
            if (inputClass == nil) {{   //  Find prefixed class
                for (NSString *prefix in (NSMutableArray *){clsPrefixesValue.GetValue()}) {{
                    NSString *clsName = [prefix stringByAppendingString:@".{options.cls}"];
                    inputClass = objc_lookUpClass((char *)[clsName UTF8String]);
                    if (inputClass) {{
                        break;
                    }}
                }}
            }}

            if (inputClass == nil) {{
                [result appendString:@"Can't find {options.cls} class\\n"];
            }} else {{
                unsigned int instanceMethodCount;
                Method *instanceMethodList = class_copyMethodList(inputClass, &instanceMethodCount);
                for (int j = 0; j < instanceMethodCount; ++j) {{
                    Method method = instanceMethodList[j];
                    SEL sel = method_getName(method);
                    NSString *selName = [[NSString alloc] initWithUTF8String:sel_getName(sel)];
                    [result appendFormat:@"(-) %@\\n\\tType encoding:%s\\n", selName, method_getTypeEncoding(method)];
                }}
                free(instanceMethodList);
                
                unsigned int classMethodCount = 0;
                Class metaCls = object_getClass(inputClass);
                if (class_isMetaClass(metaCls)) {{
                    Method *classMethodList = class_copyMethodList(metaCls, &classMethodCount);
                    for (int j = 0; j < classMethodCount; ++j) {{
                        Method method = classMethodList[j];
                        SEL sel = method_getName(method);
                        NSString *selName = [[NSString alloc] initWithUTF8String:sel_getName(sel)];
                        [result appendFormat:@"(+) %@\\n\\tType encoding:%s\\n", selName, method_getTypeEncoding(method)];
                    }}
                    free(classMethodList);
                }}
                
                if (instanceMethodCount + classMethodCount == 0) {{
                    [result insertString:@"No method found.\\n" atIndex:0];
                }} else {{
                    [result insertString:[[NSString alloc] initWithFormat:@"Instance methods count: %u. Class method count: %u.\\n", instanceMethodCount, classMethodCount] atIndex:0];
                    NSString *clsName = [[NSString alloc] initWithUTF8String:class_getName(inputClass)];
                    [result insertString:[[NSString alloc] initWithFormat:@"Class: %@ (%p)\\n", clsName, inputClass] atIndex:0];
                }}
            }}
            
            result;
        '''

    else:
        inputMethodName = args[0].lower()
        command_script = f'''
            NSString *inputMethodName = [[NSString alloc] initWithUTF8String:"{inputMethodName}"];
            
            NSMutableString *result = [[NSMutableString alloc] init];
        
            unsigned int classCount;
            unsigned int findCount = 0;
            Class *classList = objc_copyClassList(&classCount);
        
            for (int i = 0; i < classCount; ++i) {{
                Class cls = classList[i];
                // Instance Methods
                unsigned int instanceMethodCount;
                Method *instanceMethodList = class_copyMethodList(cls, &instanceMethodCount);
        
                for (int j = 0; j < instanceMethodCount; ++j) {{
                    Method method = instanceMethodList[j];
                    SEL sel = method_getName(method);
                    NSString *selName = [[NSString alloc] initWithUTF8String:sel_getName(sel)];
                    if ([[selName lowercaseString] containsString:inputMethodName]) {{
                        NSString *clsName = [[NSString alloc] initWithUTF8String:class_getName(cls)];
                        [result appendFormat:@"(-) %@\\n\\tType encoding:%s\\n\\tClass:%@\\n", selName, method_getTypeEncoding(method), clsName];
                        findCount += 1;
                    }}
                }}
                free(instanceMethodList);
                
                // Class Methods
                Class metaCls = object_getClass(cls);
                if (!class_isMetaClass(metaCls)) {{
                    continue;
                }}
                unsigned int classMethodCount;
                Method *classMethodList = class_copyMethodList(metaCls, &classMethodCount);
        
                for (int j = 0; j < classMethodCount; ++j) {{
                    Method method = classMethodList[j];
                    SEL sel = method_getName(method);
                    NSString *selName = [[NSString alloc] initWithUTF8String:sel_getName(sel)];
                    if ([[selName lowercaseString] containsString:inputMethodName]) {{
                        NSString *clsName = [[NSString alloc] initWithUTF8String:class_getName(cls)];
                        [result appendFormat:@"(+) %@\\n\\tType encoding:%s\\n\\tClass:%@\\n", selName, method_getTypeEncoding(method), clsName];
                        findCount += 1;
                    }}
                }}
                free(classMethodList);
            }}
            if (findCount == 0) {{
                [result insertString:@"No method found.\\n" atIndex:0];
            }} else {{
                [result insertString:[[NSString alloc] initWithFormat:@"Methods count: %u \\n", findCount] atIndex:0];
            }}

            free(classList);
            result;
        '''

    result = HM.evaluateExpressionValue(command_script).GetObjectDescription()
    HM.DPrint(result)
Пример #6
0
def findSubclass(debugger, command, exe_ctx, result, internal_dict):
    """
    Syntax:
        fsubclass [--nonrecursively] <className>

    Options:
        --nonrecursively/-n; Find subclass non-recursively

    Examples:
        (lldb) fsubclass UIViewController
        (lldb) fsubclass -n UIViewController


    This command is implemented in HMClassInfoCommands.py
    """

    command_args = shlex.split(command)
    parser = generate_findSubclass_option_parser()
    try:
        # options: optparse.Values
        # args: list
        (options, args) = parser.parse_args(command_args)
    except:
        result.SetError(parser.usage)
        return

    if len(args) != 1:
        HM.DPrint(
            "Requires a argument, Please enter \"help fsubclass\" for help.")
        return

    HM.DPrint("Waiting...")

    if options.nonrecursively:
        compareScript = '''
            if (class_getSuperclass(cls) == inputClass){
                NSString *name = [[NSString alloc] initWithUTF8String:class_getName(cls)];
                [result appendFormat:@"%@\\n", name];
                findCount += 1;
            }
        '''

    else:
        compareScript = '''
            for (Class superClass = class_getSuperclass(cls); superClass != nil; superClass = class_getSuperclass(superClass)) {
                if (superClass == inputClass) {
                    NSString *name = [[NSString alloc] initWithUTF8String:class_getName(cls)];
                    [result appendFormat:@"%@\\n", name];
                    findCount += 1;

                    break;
                }
            }
        '''

    clsPrefixesValue = HM.getClassPrefixes()[1]
    command_script = f'''
        Class inputClass = objc_lookUpClass("{args[0]}");

        if (inputClass == nil) {{   //  Find prefixed class
            for (NSString *prefix in (NSMutableArray *){clsPrefixesValue.GetValue()}) {{
                NSString *clsName = [prefix stringByAppendingString:@".{args[0]}"];
                inputClass = objc_lookUpClass((char *)[clsName UTF8String]);
                if (inputClass) {{
                    break;
                }}
            }}
        }}

        NSMutableString *result = [[NSMutableString alloc] init];
        if (inputClass == nil) {{
            [result appendString:@"Can't find {args[0]} class\\n"];
        }} else {{
            unsigned int classCount;
            unsigned int findCount = 0;
            Class *classList = objc_copyClassList(&classCount);

            for (int i = 0; i < classCount; i++) {{
                Class cls = classList[i];
                {compareScript}
            }}

            if (findCount == 0) {{
                [result insertString:@"No subclass found.\\n" atIndex:0];
            }} else {{
                [result insertString:[[NSString alloc] initWithFormat:@"Subclass count: %u \\n", findCount] atIndex:0];
            }}
            
            free(classList);
        }}

        result;
    '''

    classNames = HM.evaluateExpressionValue(
        command_script).GetObjectDescription()
    HM.DPrint(classNames)