def _showLayer(layer): layer = '(' + layer + ')' size = '((CGRect)[(id)' + layer + ' bounds]).size' width = float(fb.evaluateExpression(size + '.width')) height = float(fb.evaluateExpression(size + '.height')) if width == 0.0 or height == 0.0: print 'Nothing to see here - the size of this element is {} x {}.'.format( width, height) return lldb.debugger.HandleCommand( 'eobjc (void)UIGraphicsBeginImageContextWithOptions(' + size + ', NO, 0.0)') lldb.debugger.HandleCommand( 'eobjc (void)[(id)' + layer + ' renderInContext:(void *)UIGraphicsGetCurrentContext()]') frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread( ).GetSelectedFrame() result = frame.EvaluateExpression( '(UIImage *)UIGraphicsGetImageFromCurrentImageContext()') if result.GetError() is not None and str(result.GetError()) != 'success': print result.GetError() else: image = result.GetValue() _showImage(image) lldb.debugger.HandleCommand('eobjc (void)UIGraphicsEndImageContext()')
def class_getInstanceMethodImplementation(klass, selector): command = '(void*)class_getInstanceMethod({},@selector({}))'.format( klass, selector) method = fb.evaluateExpression(command) command = '(void*)method_getImplementation({})'.format(method) imp = fb.evaluateExpression(command) return imp
def unmaskView(viewOrLayer): window = fb.evaluateExpression( '(UIWindow *)[[UIApplication sharedApplication] keyWindow]') mask = fb.evaluateExpression('(UIView *)[%s viewWithTag:(NSInteger)%s]' % (window, viewOrLayer)) lldb.debugger.HandleCommand('expr (void)[%s removeFromSuperview]' % mask) flushCoreAnimationTransaction()
def run(self, arguments, options): commandForObject, ivarName = arguments objectAddress = int(fb.evaluateObjectExpression(commandForObject), 0) ivarOffsetCommand = '(ptrdiff_t)ivar_getOffset((void*)object_getInstanceVariable((id){}, "{}", 0))'.format( objectAddress, ivarName) ivarOffset = int(fb.evaluateExpression(ivarOffsetCommand), 0) # A multi-statement command allows for variables scoped to the command, not permanent in the session like $variables. ivarSizeCommand = ( 'unsigned int size = 0;' 'char *typeEncoding = (char *)ivar_getTypeEncoding((void*)class_getInstanceVariable((Class)object_getClass((id){}), "{}"));' '(char *)NSGetSizeAndAlignment(typeEncoding, &size, 0);' 'size').format(objectAddress, ivarName) ivarSize = int(fb.evaluateExpression(ivarSizeCommand), 0) error = lldb.SBError() 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()) else: print 'Could not create the watchpoint: {}'.format( error.GetCString())
def maskView(viewOrLayer, color, alpha): unmaskView(viewOrLayer) window = fb.evaluateExpression( '(UIWindow *)[[UIApplication sharedApplication] keyWindow]') origin = convertPoint(0, 0, viewOrLayer, window) size = fb.evaluateExpressionValue('(CGSize)((CGRect)[(id)%s frame]).size' % viewOrLayer) rectExpr = '(CGRect){{%s, %s}, {%s, %s}}' % ( origin.GetChildMemberWithName('x').GetValue(), origin.GetChildMemberWithName('y').GetValue(), size.GetChildMemberWithName('width').GetValue(), size.GetChildMemberWithName('height').GetValue()) mask = fb.evaluateExpression('(id)[[UIView alloc] initWithFrame:%s]' % rectExpr) lldb.debugger.HandleCommand('expr (void)[%s setTag:(NSInteger)%s]' % (mask, viewOrLayer)) lldb.debugger.HandleCommand( 'expr (void)[%s setBackgroundColor:[UIColor %sColor]]' % (mask, color)) lldb.debugger.HandleCommand('expr (void)[%s setAlpha:(CGFloat)%s]' % (mask, alpha)) lldb.debugger.HandleCommand('expr (void)[%s addSubview:%s]' % (window, mask)) flushCoreAnimationTransaction()
def _showLayer(layer): layer = '(' + layer + ')' size = '((CGRect)[(id)' + layer + ' bounds]).size' width = float(fb.evaluateExpression('(CGFloat)(' + size + '.width)')) height = float(fb.evaluateExpression('(CGFloat)(' + size + '.height)')) if width == 0.0 or height == 0.0: print('Nothing to see here - the size of this element is {} x {}.'. format(width, height)) return fb.evaluateEffect('UIGraphicsBeginImageContextWithOptions(' + size + ', NO, 0.0)') fb.evaluateEffect( '[(id)' + layer + ' renderInContext:(void *)UIGraphicsGetCurrentContext()]') result = fb.evaluateExpressionValue( '(UIImage *)UIGraphicsGetImageFromCurrentImageContext()') if result.GetError() is not None and str(result.GetError()) != 'success': print(result.GetError()) else: image = result.GetValue() _showImage(image) fb.evaluateEffect('UIGraphicsEndImageContext()')
def unmaskView(viewOrLayer): window = fb.evaluateExpression( '(UIWindow *)[[UIApplication sharedApplication] keyWindow]') mask = fb.evaluateExpression('(UIView *)[%s viewWithTag:(NSInteger)%s]' % (window, viewOrLayer)) fb.evaluateEffect('[%s removeFromSuperview]' % mask) flushCoreAnimationTransaction()
def _responderChain(startResponder): responderAddress = fb.evaluateExpression(startResponder) while int(responderAddress, 16): yield fb.evaluateExpressionValue(responderAddress).GetObjectDescription() responderAddress = fb.evaluateExpression( "(id)[(id)" + responderAddress + " nextResponder]" )
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(vc, string, prefix, childPrefix): isMac = runtimeHelpers.isMacintoshArch() s = "%s%s%s\n" % (prefix, "" if prefix == "" else " ", _viewControllerDescription(vc)) nextPrefix = childPrefix + " |" numChildViewControllers = fb.evaluateIntegerExpression("(int)[(id)[%s childViewControllers] count]" % (vc)) childViewControllers = fb.evaluateExpression("(id)[%s childViewControllers]" % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression("(id)[(id)[%s childViewControllers] objectAtIndex:%d]" % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(viewController, string, nextPrefix, nextPrefix) if not isMac: isModal = fb.evaluateBooleanExpression( "%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s" % (vc, vc, vc) ) if isModal: modalVC = fb.evaluateObjectExpression("(id)[(id)%s presentedViewController]" % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + " *M", nextPrefix ) s += "\n// '*M' means the view controller is presented modally." return string + s
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression('(id)[(id)' + invocation + ' target]') description = fb.evaluateExpressionValue( '(id)' + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print('NSInvocation: ' + invocation) print('self: ' + fb.evaluateExpression('(id)' + object)) if len(argDescriptions) > 0: print('\n' + str(len(argDescriptions)) + ' Arguments:' if len(argDescriptions) > 1 else '\nArgument:') index = 2 for argDescription in argDescriptions: s = re.sub(r'argument [0-9]+: ', '', argDescription) address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(' ')[0] description = ' '.join(s.split(' ')[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print(readableString) else: if encoding[0] == '{': encoding = encoding[1:] print((hex(address) + ', address of ' + encoding + ' ' + description).strip()) index += 1
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression("(id)[(id)" + invocation + " target]") description = fb.evaluateExpressionValue( "(id)" + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print("NSInvocation: " + invocation) print("self: " + fb.evaluateExpression("(id)" + object)) if len(argDescriptions) > 0: print("\n" + str(len(argDescriptions)) + " Arguments:" if len(argDescriptions) > 1 else "\nArgument:") index = 2 for argDescription in argDescriptions: s = re.sub(r"argument [0-9]+: ", "", argDescription) address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(" ")[0] description = " ".join(s.split(" ")[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print(readableString) else: if encoding[0] == "{": encoding = encoding[1:] print((hex(address) + ", address of " + encoding + " " + description).strip()) index += 1
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression("(id)[(id)" + invocation + " target]") description = fb.evaluateExpressionValue("(id)" + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print "NSInvocation: " + invocation print "self: " + fb.evaluateExpression("(id)" + object) if len(argDescriptions) > 0: print "\n" + str(len(argDescriptions)) + " Arguments:" if len(argDescriptions) > 1 else "\nArgument:" index = 2 for argDescription in argDescriptions: s = re.sub(r"argument [0-9]+: ", "", argDescription) lldb.debugger.HandleCommand("expr void *$v") lldb.debugger.HandleCommand("expr (void)[" + invocation + " getArgument:&$v atIndex:" + str(index) + "]") address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(" ")[0] description = " ".join(s.split(" ")[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print readableString else: if encoding[0] == "{": encoding = encoding[1:] print (hex(address) + ", address of " + encoding + " " + description).strip() index += 1
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression('(id)[(id)' + invocation + ' target]') description = fb.evaluateExpressionValue('(id)' + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print 'NSInvocation: ' + invocation print 'self: ' + fb.evaluateExpression('(id)' + object) if len(argDescriptions) > 0: print '\n' + str(len(argDescriptions)) + ' Arguments:' if len(argDescriptions) > 1 else '\nArgument:' index = 2 for argDescription in argDescriptions: s = re.sub(r'argument [0-9]+: ', '', argDescription) address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(' ')[0] description = ' '.join(s.split(' ')[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print readableString else: if encoding[0] == '{': encoding = encoding[1:] print (hex(address) + ', address of ' + encoding + ' ' + description).strip() index += 1
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( vc, string, prefix, childPrefix): s = '%s%s%s\n' % (prefix, '' if prefix == '' else ' ', _viewControllerDescription(vc)) nextPrefix = childPrefix + ' |' numChildViewControllers = fb.evaluateIntegerExpression( '(int)[(id)[%s childViewControllers] count]' % (vc)) childViewControllers = fb.evaluateExpression( '(id)[%s childViewControllers]' % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression( '(id)[(id)[%s childViewControllers] objectAtIndex:%d]' % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( viewController, string, nextPrefix, nextPrefix) isModal = fb.evaluateBooleanExpression( '%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s' % (vc, vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression( '(id)[(id)%s presentedViewController]' % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + ' *M', nextPrefix) s += '\n// \'*M\' means the view controller is presented modally.' return string + s
def _showLayer(layer): layer = "(" + layer + ")" size = "((CGRect)[(id)" + layer + " bounds]).size" width = float(fb.evaluateExpression("(CGFloat)(" + size + ".width)")) height = float(fb.evaluateExpression("(CGFloat)(" + size + ".height)")) if width == 0.0 or height == 0.0: print("Nothing to see here - the size of this element is {} x {}.". format(width, height)) return fb.evaluateEffect("UIGraphicsBeginImageContextWithOptions(" + size + ", NO, 0.0)") fb.evaluateEffect( "[(id)" + layer + " renderInContext:(void *)UIGraphicsGetCurrentContext()]") result = fb.evaluateExpressionValue( "(UIImage *)UIGraphicsGetImageFromCurrentImageContext()") if result.GetError() is not None and str(result.GetError()) != "success": print(result.GetError()) else: image = result.GetValue() _showImage(image) fb.evaluateEffect("UIGraphicsEndImageContext()")
def _inheritanceHierarchy(instanceOfAClass): instanceAddress = fb.evaluateExpression(instanceOfAClass) instanceClass = fb.evaluateExpression('(id)[(id)' + instanceAddress + ' class]') while int(instanceClass, 16): yield fb.evaluateExpressionValue(instanceClass).GetObjectDescription() instanceClass = fb.evaluateExpression('(id)[(id)' + instanceClass + ' superclass]')
def accessibilityElements(view): if fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(accessibilityElements)]'): a11yElements = fb.evaluateExpression('(id)[%s accessibilityElements]' % view, False) if int(a11yElements, 16) != 0: return a11yElements if fb.evaluateBooleanExpression('[%s respondsToSelector:@selector(_accessibleSubviews)]' % view): return fb.evaluateExpression('(id)[%s _accessibleSubviews]' % (view), False) else: return fb.evaluateObjectExpression('[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]' % view)
def subviewsOfView(view): views = [(view, 0)] yield views[0] while views: (view, level) = views.pop(0) subviews = fb.evaluateExpression('(id)[%s subviews]' % view) subviewsCount = int(fb.evaluateExpression('(int)[(id)%s count]' % subviews)) for i in xrange(subviewsCount): subview = fb.evaluateExpression('(id)[%s objectAtIndex:%i]' % (subviews, i)) views.append((subview, level+1)) yield (subview, level+1)
def subviewsOfView(view): views = [(view, 0)] yield views[0] while views: (view, level) = views.pop(0) subviews = fb.evaluateExpression('(id)[%s subviews]' % view) subviewsCount = int( fb.evaluateExpression('(int)[(id)%s count]' % subviews)) for i in xrange(subviewsCount): subview = fb.evaluateExpression('(id)[%s objectAtIndex:%i]' % (subviews, i)) views.append((subview, level + 1)) yield (subview, level + 1)
def run(self, args, options): print '------ start config ------' if options.id == "" and options.url == "": print "error, -d or -u missing!" return # 1. Generate url and document path first if options.id is not None and options.id != "": tqms_dict = getTQMSInformationDict(options.id) for key in tqms_dict: if tqms_dict[key] is None or tqms_dict[key] == "": print "Error when get %s for TQMS: %s" % (key, options.id) config_url = tqms_dict['url'] document_path = tqms_dict['document'] path_separator = tqms_dict['separator'] elif options.url is not None and options.url != "": config_url = options.url config_url = self.getPureUrlLink(config_url) print "config_url = %s" % config_url print "document_path = %s" % document_path # 2. Config the document path into FolderPathSearcher if document_path is not None and path_separator is not None: lldb.debugger.HandleCommand('expression [FolderPathSearcher getInstance]') if document_path is not None and document_path != "": expr = '[[FolderPathSearcher getInstance] setSearchPath:@"'+ document_path +'" Separator:@"'+ path_separator +'"]' lldb.debugger.HandleCommand('expression ' + expr) # 3. Apply url link if config_url is not None: url = fb.evaluateExpression('(NSURL*)[NSURL URLWithString:@"%s"]' % config_url) application = fb.evaluateExpression('(UIApplication*)[UIApplication sharedApplication]') delegate = fb.evaluateExpression('[(UIApplication*)%s delegate]' % application) lldb.debugger.HandleCommand('expr (void)[%s application:%s openURL:%s sourceApplication:nil annotation:nil]' % (delegate, application, url)) print '------ end config ------' else: print 'Failed to generate the url link, please check your url or TQMS ID is correct!' # 4. Continue run our app lldb.debugger.SetAsync(True) lldb.debugger.GetSelectedTarget().GetProcess().Continue() # the following code is used for testing # config = MSIConfigCommand() # config.run(['880507'], config.options())
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression('(id)[(id)' + invocation + ' target]') selector = fb.evaluateExpressionValue('(char *)sel_getName((SEL)[(id)' + invocation + ' selector])').GetSummary() selector = re.sub(r'^"|"$', '', selector) objectClassValue = fb.evaluateExpressionValue('(id)object_getClass((id)' + object + ')') objectClass = objectClassValue.GetObjectDescription() description = fb.evaluateExpressionValue( '(id)' + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print 'NSInvocation: ' + invocation print 'self: ' + fb.evaluateExpression('(id)' + object) if len(argDescriptions) > 0: print '\n' + str(len(argDescriptions)) + ' Arguments:' if len( argDescriptions) > 1 else '\nArgument:' index = 2 for argDescription in argDescriptions: s = re.sub(r'argument [0-9]+: ', '', argDescription) lldb.debugger.HandleCommand('expr -l objc++ -- void *$v') lldb.debugger.HandleCommand('expr -l objc++ -- (void)[' + invocation + ' getArgument:&$v atIndex:' + str(index) + ']') address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(' ')[0] description = ' '.join(s.split(' ')[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print readableString else: if encoding[0] == '{': encoding = encoding[1:] print( hex(address) + ', address of ' + encoding + ' ' + description).strip() index += 1
def run(self, arguments, options): # pdb.set_trace() coreName = fb.evaluateExpression( '[CoreManager getCoreFromProtocol:(Protocol *)objc_getProtocol("' + arguments[0] + '")]') print('<{}: {}>'.format(arguments[0], coreName)) lldb.debugger.HandleCommand('po [%s %s]' % (coreName, arguments[1]))
def setBorderOnAmbiguousViewRecursive(view, width, color): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view): return isAmbiguous = fb.evaluateBooleanExpression('(BOOL)[%s hasAmbiguousLayout]' % view) if isAmbiguous: layer = viewHelpers.convertToLayer(view) fb.evaluateEffect('[%s setBorderWidth:(CGFloat)%s]' % (layer, width)) fb.evaluateEffect('[%s setBorderColor:(CGColorRef)[(id)[UIColor %sColor] CGColor]]' % (layer, color)) subviews = fb.evaluateExpression('(id)[%s subviews]' % view) subviewsCount = int(fb.evaluateExpression('(int)[(id)%s count]' % subviews)) if subviewsCount > 0: for i in range(0, subviewsCount): subview = fb.evaluateExpression('(id)[%s objectAtIndex:%i]' % (subviews, i)) setBorderOnAmbiguousViewRecursive(subview, width, color)
def convertToLayer(viewOrLayer): if fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[CALayer class]]' % viewOrLayer): return viewOrLayer elif fb.evaluateBooleanExpression('[(id)%s respondsToSelector:(SEL)@selector(layer)]' % viewOrLayer): return fb.evaluateExpression('(CALayer *)[%s layer]' % viewOrLayer) else: raise Exception('Argument must be a CALayer, UIView, or NSView.')
def upwardsRecursiveDescription(view, maxDepth=0): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view) and not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[NSView class]]' % view): return None currentView = view recursiveDescription = [] depth = 0 while currentView and (maxDepth <= 0 or depth <= maxDepth): depth += 1 viewDescription = fb.evaluateExpressionValue('(id)[%s debugDescription]' % (currentView)).GetObjectDescription() currentView = fb.evaluateExpression('(void*)[%s superview]' % (currentView)) try: if int(currentView, 0) == 0: currentView = None except: currentView = None if viewDescription: recursiveDescription.insert(0, viewDescription) if len(viewDescription) == 0: return None currentPrefix = "" builder = "" for viewDescription in recursiveDescription: builder += currentPrefix + viewDescription + "\n" currentPrefix += " | " return builder
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( vc, string, prefix, childPrefix): isMac = runtimeHelpers.isMacintoshArch() s = "%s%s%s\n" % ( prefix, "" if prefix == "" else " ", _viewControllerDescription(vc), ) nextPrefix = childPrefix + " |" numChildViewControllers = fb.evaluateIntegerExpression( "(int)[(id)[%s childViewControllers] count]" % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression( "(id)[(id)[%s childViewControllers] objectAtIndex:%d]" % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( viewController, string, nextPrefix, nextPrefix) if not isMac: isModal = fb.evaluateBooleanExpression( "%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s" # noqa B950 % (vc, vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression( "(id)[(id)%s presentedViewController]" % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + " *M", nextPrefix) s += "\n// '*M' means the view controller is presented modally." return string + s
def run(self, arguments, options): # pdb.set_trace() bridgeName = fb.evaluateExpression( '[[YYBridgeSet shareInstance] getBridgeWithProtocol:(Protocol *)objc_getProtocol("' + arguments[0] + '")]') print('<{}: {}>'.format(arguments[0], bridgeName)) lldb.debugger.HandleCommand('po [%s %s]' % (bridgeName, arguments[1]))
def convertToLayer(viewOrLayer): if fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[CALayer class]]' % viewOrLayer): return viewOrLayer elif fb.evaluateBooleanExpression('[(id)%s respondsToSelector:(SEL)@selector(layer)]' % viewOrLayer): return fb.evaluateExpression('(CALayer *)[%s layer]' % viewOrLayer) else: raise Exception('Argument must be a CALayer or a UIView')
def upwardsRecursiveDescription(view): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view): return None currentView = view recursiveDescription = [] while currentView: viewDescription = fb.evaluateExpressionValue('(id)[%s debugDescription]' % (currentView)).GetObjectDescription() currentView = fb.evaluateExpression('(void*)[%s superview]' % (currentView)) try: if int(currentView, 0) == 0: currentView = None except: currentView = None if viewDescription: recursiveDescription.insert(0, viewDescription) if len(viewDescription) == 0: return None currentPrefix = "" builder = "" for viewDescription in recursiveDescription: builder += currentPrefix + viewDescription + "\n" currentPrefix += " | " return builder
def printInvocationForFrame(frame): print(frame) symbolName = frame.GetSymbol().GetName() if not re.match(r"[-+]\s*\[.*\]", symbolName): return self = findArgAtIndexFromStackFrame(frame, 0) cmd = findArgAtIndexFromStackFrame(frame, 1) commandForSignature = ( "[(id)" + self + " methodSignatureForSelector:(char *)sel_getName((SEL)" + cmd + ")]") signatureValue = fb.evaluateExpressionValue("(id)" + commandForSignature) if (signatureValue.GetError() is not None and str(signatureValue.GetError()) != "success"): print( "My sincerest apologies. I couldn't find a method signature for the selector." # noqa B950 ) return signature = signatureValue.GetValue() arg0 = stackStartAddressInSelectedFrame(frame) commandForInvocation = ( "[NSInvocation _invocationWithMethodSignature:(id)" + signature + " frame:((void *)" + str(arg0) + ")]") invocation = fb.evaluateExpression("(id)" + commandForInvocation) if invocation: prettyPrintInvocation(frame, invocation) else: print(frame)
def printInvocationForFrame(frame): print frame symbolName = frame.GetSymbol().GetName() if not re.match(r'[-+]\s*\[.*\]', symbolName): return self = findArgAtIndexFromStackFrame(frame, 0) cmd = findArgAtIndexFromStackFrame(frame, 1) commandForSignature = '[(id)' + self + ' methodSignatureForSelector:(char *)sel_getName((SEL)' + cmd + ')]' signatureValue = fb.evaluateExpressionValue('(id)' + commandForSignature) if signatureValue.GetError() is not None and str(signatureValue.GetError()) != 'success': print "My sincerest apologies. I couldn't find a method signature for the selector." return signature = signatureValue.GetValue() arg0 = stackStartAddressInSelectedFrame(frame) commandForInvocation = '[NSInvocation _invocationWithMethodSignature:(id)' + signature + ' frame:((void *)' + str(arg0) + ')]' invocation = fb.evaluateExpression('(id)' + commandForInvocation) if invocation: prettyPrintInvocation(frame, invocation) else: print frame
def maskView(viewOrLayer, color, alpha): unmaskView(viewOrLayer) window = fb.evaluateExpression('(UIWindow *)[[UIApplication sharedApplication] keyWindow]') origin = convertPoint(0, 0, viewOrLayer, window) size = fb.evaluateExpressionValue('(CGSize)((CGRect)[(id)%s frame]).size' % viewOrLayer) rectExpr = '(CGRect){{%s, %s}, {%s, %s}}' % (origin.GetChildMemberWithName('x').GetValue(), origin.GetChildMemberWithName('y').GetValue(), size.GetChildMemberWithName('width').GetValue(), size.GetChildMemberWithName('height').GetValue()) mask = fb.evaluateExpression('(id)[[UIView alloc] initWithFrame:%s]' % rectExpr) lldb.debugger.HandleCommand('expr (void)[%s setTag:(NSInteger)%s]' % (mask, viewOrLayer)) lldb.debugger.HandleCommand('expr (void)[%s setBackgroundColor:[UIColor %sColor]]' % (mask, color)) lldb.debugger.HandleCommand('expr (void)[%s setAlpha:(CGFloat)%s]' % (mask, alpha)) lldb.debugger.HandleCommand('expr (void)[%s addSubview:%s]' % (window, mask)) flushCoreAnimationTransaction()
def run(self, arguments, options): upwards = 'YES' if options.upwards else 'NO' showViews = 'YES' if options.showViews == 'YES' else 'NO' view = fb.evaluateInputExpression(arguments[0]) if not viewHelpers.isView(view): # assume it's a CKComponent view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view) print fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']')
def run(self, arguments, options): upwards = 'YES' if options.upwards else 'NO' showViews = 'YES' if options.showViews == 'YES' else 'NO' view = fb.evaluateInputExpression(arguments[0]) if not viewHelpers.isView(view): # assume it's a CKComponent view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view) print(fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']'))
def run(self, arguments, options): object = fb.evaluateInputExpression(arguments[0]) ivarName = arguments[1] objectClass = fb.evaluateExpressionValue('(id)[(' + object + ') class]').GetObjectDescription() ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(object, ivarName) ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) result = fb.evaluateExpressionValue('(({} *)({}))->{}'.format(printCommand, objectClass, object, ivarName)) return result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result.GetValue()
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(vc, string, prefix, childPrefix): s = '%s%s%s\n' % (prefix, '' if prefix == '' else ' ', _viewControllerDescription(vc)) nextPrefix = childPrefix + ' |' numChildViewControllers = fb.evaluateIntegerExpression('(int)[(id)[%s childViewControllers] count]' % (vc)) childViewControllers = fb.evaluateExpression('(id)[%s childViewControllers]' % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression('(id)[(id)[%s childViewControllers] objectAtIndex:%d]' % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(viewController, string, nextPrefix, nextPrefix) isModal = fb.evaluateBooleanExpression('((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s' % (vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression('(id)[(id)%s presentedViewController]' % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(modalVC, string, childPrefix + ' *M' , nextPrefix) s += '\n// \'*M\' means the view controller is presented modally.' return string + s
def run(self, arguments, options): object = fb.evaluateInputExpression(arguments[0]) ivarName = arguments[1] objectClass = fb.evaluateExpressionValue('(id)[(' + object + ') class]').GetObjectDescription() ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(object, ivarName) ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) result = fb.evaluateExpressionValue('(({} *)({}))->{}'.format(objectClass, object, ivarName)) print result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result
def run(self, arguments, options): commandForObject, ivarName = arguments object = fb.evaluateObjectExpression(commandForObject) objectClass = fb.evaluateExpressionValue('(id)[(' + object + ') class]').GetObjectDescription() ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(object, ivarName) ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) printCommand = 'po' if ('@' in ivarTypeEncodingFirstChar) else 'p' lldb.debugger.HandleCommand('{} (({} *)({}))->{}'.format(printCommand, objectClass, object, ivarName))
def _showImage(commandForImage): imageDirectory = '/tmp/xcode_debug_images/' imageName = time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime()) + ".png" imagePath = imageDirectory + imageName try: os.makedirs(imageDirectory) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(imageDirectory): pass else: raise toPNG = '(id)UIImagePNGRepresentation((id){})'.format(commandForImage) imageDataAddress = fb.evaluateExpressionValue( toPNG, tryAllThreads=True).GetValue() imageBytesStartAddress = fb.evaluateExpression('(void *)[(id)' + imageDataAddress + ' bytes]') imageBytesLength = fb.evaluateExpression('(NSUInteger)[(id)' + imageDataAddress + ' length]') address = int(imageBytesStartAddress, 16) length = int(imageBytesLength) if not (address or length): print('Could not get image data.') return process = lldb.debugger.GetSelectedTarget().GetProcess() error = lldb.SBError() mem = process.ReadMemory(address, length, error) if error is not None and str(error) != 'success': print(error) else: imgFile = open(imagePath, 'wb') imgFile.write(mem) imgFile.close() os.system('open ' + imagePath)
def run(self, arguments, options): commandForObject = arguments[0] object = fb.evaluateObjectExpression(commandForObject) fb.evaluateExpressionValue('unsigned int $fblldb_ivar_count = 0', False) fb.evaluateExpressionValue('intptr_t *$fblldb_ivars = (intptr_t *)class_copyIvarList((Class)object_getClass({}), &$fblldb_ivar_count)'.format(object), False) ivarCount = int(fb.evaluateExpression('$fblldb_ivar_count')) for i in range(0, ivarCount): # TODO Unsure how to easily read the string properly, so just getting a summary and removing the quotes. ivarName = fb.evaluateExpressionValue('(char *)ivar_getName((void *)$fblldb_ivars[{}])'.format(i)).GetSummary()[1:-1] print '{} -> '.format(ivarName), FBPrintInstanceVariable().run([commandForObject, ivarName], options)
def run(self, arguments, options): # pdb.set_trace() object = lldb.SBCommandReturnObject() coreName = fb.evaluateExpression('((' + arguments[0] + ' *)[CoreManager getCore:[' + arguments[0] + ' class]])') result = fb.evaluateObjectExpression('(id)[' + coreName + ' %s]' % arguments[1]) print('result: {}'.format(result)) print('<{}: {}>'.format(arguments[0], coreName)) lldb.debugger.HandleCommand('po [(%s *)%s %s]' % (arguments[0], coreName, arguments[1]))
def prettyPrintInvocation(frame, invocation): object = fb.evaluateExpression('(id)[(id)' + invocation + ' target]') selector = fb.evaluateExpressionValue('(char *)sel_getName((SEL)[(id)' + invocation + ' selector])').GetSummary() selector = re.sub(r'^"|"$', '', selector) objectClassValue = fb.evaluateExpressionValue('(id)object_getClass((id)' + object + ')') objectClass = objectClassValue.GetObjectDescription() description = fb.evaluateExpressionValue('(id)' + invocation).GetObjectDescription() argDescriptions = description.splitlines(True)[4:] print 'NSInvocation: ' + invocation print 'self: ' + fb.evaluateExpression('(id)' + object) if len(argDescriptions) > 0: print '\n' + str(len(argDescriptions)) + ' Arguments:' if len(argDescriptions) > 1 else '\nArgument:' index = 2 for argDescription in argDescriptions: s = re.sub(r'argument [0-9]+: ', '', argDescription) lldb.debugger.HandleCommand('expr void *$v') lldb.debugger.HandleCommand('expr (void)[' + invocation + ' getArgument:&$v atIndex:' + str(index) + ']') address = findArgAdressAtIndexFromStackFrame(frame, index) encoding = s.split(' ')[0] description = ' '.join(s.split(' ')[1:]) readableString = argumentAsString(frame, address, encoding) if readableString: print readableString else: if encoding[0] == '{': encoding = encoding[1:len(encoding)-1] print (hex(address) + ', address of ' + encoding + ' ' + description).strip() index += 1
def run(self, arguments, options): commandForObject, ivarName = arguments object = fb.evaluateObjectExpression(commandForObject) objectClass = fb.evaluateExpressionValue("(id)[(" + object + ") class]").GetObjectDescription() ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, "{}", 0)))[0]'.format( object, ivarName ) ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) printCommand = "po" if ("@" in ivarTypeEncodingFirstChar) else "p" lldb.debugger.HandleCommand("{} (({} *)({}))->{}".format(printCommand, objectClass, object, ivarName))
def _showLayer(layer): layer = '(' + layer + ')' size = '((CGRect)[(id)' + layer + ' bounds]).size' width = float(fb.evaluateExpression(size + '.width')) height = float(fb.evaluateExpression(size + '.height')) if width == 0.0 or height == 0.0: print('Nothing to see here - the size of this element is {} x {}.'.format(width, height)) return lldb.debugger.HandleCommand('eobjc (void)UIGraphicsBeginImageContextWithOptions(' + size + ', NO, 0.0)') lldb.debugger.HandleCommand('eobjc (void)[(id)' + layer + ' renderInContext:(void *)UIGraphicsGetCurrentContext()]') frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() result = frame.EvaluateExpression('(UIImage *)UIGraphicsGetImageFromCurrentImageContext()') if result.GetError() is not None and str(result.GetError()) != 'success': print(result.GetError()) else: image = result.GetValue() _showImage(image) lldb.debugger.HandleCommand('eobjc (void)UIGraphicsEndImageContext()')
def run(self, arguments, options): commandForObject, ivarName = arguments objectAddress = int(fb.evaluateObjectExpression(commandForObject), 0) ivarOffsetCommand = '(ptrdiff_t)ivar_getOffset((void*)object_getInstanceVariable((id){}, "{}", 0))'.format(objectAddress, ivarName) ivarOffset = int(fb.evaluateExpression(ivarOffsetCommand), 0) # A multi-statement command allows for variables scoped to the command, not permanent in the session like $variables. ivarSizeCommand = ('unsigned int size = 0;' 'char *typeEncoding = (char *)ivar_getTypeEncoding((void*)class_getInstanceVariable((Class)object_getClass((id){}), "{}"));' '(char *)NSGetSizeAndAlignment(typeEncoding, &size, 0);' 'size').format(objectAddress, ivarName) ivarSize = int(fb.evaluateExpression(ivarSizeCommand), 0) error = lldb.SBError() 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()) else: print 'Could not create the watchpoint: {}'.format(error.GetCString())
def _copyFromData(data, defaultFilename, preferredFilename, noOpen): directory = '/tmp/chisel_copy/' path = directory + (preferredFilename or defaultFilename) try: os.makedirs(directory) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(directory): pass else: raise startAddress = fb.evaluateExpression('(void *)[(id)' + data + ' bytes]') length = fb.evaluateExpression('(NSUInteger)[(id)' + data + ' length]') address = int(startAddress, 16) length = int(length) if not (address or length): print('Could not get data.') return process = lldb.debugger.GetSelectedTarget().GetProcess() error = lldb.SBError() mem = process.ReadMemory(address, length, error) if error is not None and str(error) != 'success': print(error) else: with open(path, 'wb') as file: file.write(mem) file.close() print(path) if not noOpen: os.system('open ' + path)
def _showImage(commandForImage): imageDirectory = '/tmp/xcode_debug_images/' imageName = time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime()) + ".png" imagePath = imageDirectory + imageName try: os.makedirs(imageDirectory) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(imageDirectory): pass else: raise imageDataAddress = fb.evaluateObjectExpression('UIImagePNGRepresentation((id)' + commandForImage + ')') imageBytesStartAddress = fb.evaluateExpression('(void *)[(id)' + imageDataAddress + ' bytes]') imageBytesLength = fb.evaluateExpression('(NSUInteger)[(id)' + imageDataAddress + ' length]') address = int(imageBytesStartAddress, 16) length = int(imageBytesLength) if not (address or length): print('Could not get image data.') return process = lldb.debugger.GetSelectedTarget().GetProcess() error = lldb.SBError() mem = process.ReadMemory(address, length, error) if error is not None and str(error) != 'success': print(error) else: imgFile = open(imagePath, 'wb') imgFile.write(mem) imgFile.close() os.system('open ' + imagePath)
def run(self, arguments, options): commandForObject, ivarName = arguments object = fb.evaluateObjectExpression(commandForObject) valueVariableName = '$fblldb_{}_value'.format(ivarName) fb.evaluateExpressionValue('void *{} = NULL'.format(valueVariableName), False) ivarTypeCommand = '((char *)ivar_getTypeEncoding((void *)object_getInstanceVariable((id){}, \"{}\", &{})))[0]'.format(object, ivarName, valueVariableName) ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand) printCommand = 'po' if ('@' in ivarTypeEncodingFirstChar) else 'p' lldb.debugger.HandleCommand('{} {}'.format(printCommand, valueVariableName)) fb.evaluateExpressionValue('{} = NULL'.format(valueVariableName))
def printAccessibilityIdentifiersHierarchy(view, indent = 0): a11yIdentifier = accessibilityIdentifier(view) classDesc = objHelpers.className(view) indentString = ' | ' * indent #if we don't have any accessibility identifier - we should have some children if int(a11yIdentifier.GetValue(), 16) == 0: 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()))
def printAccessibilityHierarchy(view, indent = 0): a11yLabel = accessibilityLabel(view) classDesc = objHelpers.className(view) indentString = ' | ' * indent #if we don't have any accessibility string - we should have some children if int(a11yLabel.GetValue(), 16) == 0: print indentString + ('{} {}'.format(classDesc, view)) #We call private method that gives back all visible accessibility children for view accessibilityElements = fb.evaluateObjectExpression('[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]' % view) accessibilityElementsCount = int(fb.evaluateExpression('(int)[%s count]' % accessibilityElements)) for index in range(0, accessibilityElementsCount): subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (accessibilityElements, index)) printAccessibilityHierarchy(subview, indent + 1) else: print indentString + ('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription()))
def run(self, arguments, options): request = arguments[0] HTTPHeaderSring = '' HTTPMethod = fb.evaluateExpressionValue('(id)[{} HTTPMethod]'.format(request)).GetObjectDescription() URL = fb.evaluateExpressionValue('(id)[{} URL]'.format(request)).GetObjectDescription() timeout = fb.evaluateExpression('(NSTimeInterval)[{} timeoutInterval]'.format(request)) HTTPHeaders = fb.evaluateObjectExpression('(id)[{} allHTTPHeaderFields]'.format(request)) HTTPHeadersCount = fb.evaluateIntegerExpression('[{} count]'.format(HTTPHeaders)) allHTTPKeys = fb.evaluateObjectExpression('[{} allKeys]'.format(HTTPHeaders)) for index in range(0, HTTPHeadersCount): key = fb.evaluateObjectExpression('[{} objectAtIndex:{}]'.format(allHTTPKeys, index)) keyDescription = fb.evaluateExpressionValue('(id){}'.format(key)).GetObjectDescription() value = fb.evaluateExpressionValue('(id)[(id){} objectForKey:{}]'.format(HTTPHeaders, key)).GetObjectDescription() if len(HTTPHeaderSring) > 0: HTTPHeaderSring += ' ' HTTPHeaderSring += '-H "{}: {}"'.format(keyDescription, value) HTTPData = fb.evaluateObjectExpression('[{} HTTPBody]'.format(request)) dataFile = None dataAsString = None if fb.evaluateIntegerExpression('[{} length]'.format(HTTPData)) > 0: if options.embed: if fb.evaluateIntegerExpression('[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]'.format(HTTPData)): dataAsString = fb.evaluateExpressionValue('(id)[(id){} base64EncodedStringWithOptions:0]'.format(HTTPData)).GetObjectDescription() else : print('This version of OS doesn\'t supports base64 data encoding') return False elif not runtimeHelpers.isIOSDevice(): dataFile = self.generateTmpFilePath() if not fb.evaluateBooleanExpression('(BOOL)[{} writeToFile:@"{}" atomically:NO]'.format(HTTPData, dataFile)): print('Can\'t write data to file {}'.format(dataFile)) return False else: print('HTTPBody data for iOS Device is supported only with "--embed-data" flag') return False commandString = '' if dataAsString is not None and len(dataAsString) > 0: dataFile = self.generateTmpFilePath() commandString += 'echo "{}" | base64 -D -o "{}" && '.format(dataAsString, dataFile) commandString += 'curl -X {} --connect-timeout {}'.format(HTTPMethod, timeout) if len(HTTPHeaderSring) > 0: commandString += ' ' + HTTPHeaderSring if dataFile is not None: commandString += ' --data-binary @"{}"'.format(dataFile) commandString += ' "{}"'.format(URL) print(commandString)
def _responderChain(startResponder): responderAddress = fb.evaluateExpression(startResponder) while int(responderAddress, 16): yield fb.evaluateExpressionValue(responderAddress).GetObjectDescription() responderAddress = fb.evaluateExpression("(id)[(id)" + responderAddress + " nextResponder]")
def _inheritanceHierarchy(instanceOfAClass): instanceAddress = fb.evaluateExpression(instanceOfAClass) instanceClass = fb.evaluateExpression("(id)[(id)" + instanceAddress + " class]") while int(instanceClass, 16): yield fb.evaluateExpressionValue(instanceClass).GetObjectDescription() instanceClass = fb.evaluateExpression("(id)[(id)" + instanceClass + " superclass]")
def findArgAtIndexFromStackFrame(frame, index): return fb.evaluateExpression('*(int *)' + str(findArgAdressAtIndexFromStackFrame(frame, index)))
def class_getInstanceMethod(klass, selector): command = '(void*)class_getInstanceMethod((Class){}, @selector({}))'.format(klass, selector) value = fb.evaluateExpression(command) return value
def class_getSuperclass(klass): command = '(void*)class_getSuperclass((Class){})'.format(klass) value = fb.evaluateExpression(command) return value