64

Роман Ермолов - Отладка приложений под iOS

Embed Size (px)

Citation preview

Page 1: Роман Ермолов - Отладка приложений под iOS
Page 2: Роман Ермолов - Отладка приложений под iOS

Роман Ермолов

Отладка приложений под iOS

Page 3: Роман Ермолов - Отладка приложений под iOS

План1 Интересные возможности LLDB2 Отладка иерархии UIView3 Отладка без исходников

Page 4: Роман Ермолов - Отладка приложений под iOS

Интересные возможности

LLDB1 breakpoint 1.1 condition 1.2 command

Page 5: Роман Ермолов - Отладка приложений под iOS

Интересные возможности

LLDB1 breakpoint 1.1 condition 1.2 command

Page 6: Роман Ермолов - Отладка приложений под iOS

breakpoint

- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; self.contentManagerVC.view.frame = self.layout.contentFrame; // ... self.voiceSearchController.view.frame = self.layout.voiceSearchFrame; }

6

Page 7: Роман Ермолов - Отладка приложений под iOS

breakpoint

7

Page 8: Роман Ермолов - Отладка приложений под iOS

breakpoint

8

Page 9: Роман Ермолов - Отладка приложений под iOS

Интересные возможности

LLDB1 breakpoint 1.1 condition 1.2 command

Page 10: Роман Ермолов - Отладка приложений под iOS

condition

10

@implementation YBSplitViewController - (void)loadView { self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; // ... } - (void)viewDidLoad { [super viewDidLoad]; // ... } @end

Page 11: Роман Ермолов - Отладка приложений под iOS

condition

11

@implementation YBSplitViewController - (void)loadView { self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; // ... } - (void)viewDidLoad { [super viewDidLoad]; // ... } - (void)didMoveToParentViewController:(UIViewController*)parent { [super didMoveToParentViewController:parent]; } @end

Page 12: Роман Ермолов - Отладка приложений под iOS

condition// Устанавливаем символьный брейкпоинт -[YBSplitViewController didMoveToParentViewController:]

12

// Устанавливаем символьный брейкпоинт -[UIViewController didMoveToParentViewController:] // Добавляем условие (Class)[$arg1 class] == [YBSplitViewController class]

(lldb) breakpoint set -F "-[YBSplitViewController didMoveToParentViewController:]" Breakpoint 1: no locations (pending). WARNING: Unable to resolve breakpoint to any actual locations.

Page 13: Роман Ермолов - Отладка приложений под iOS

condition

(lldb) po $arg1 <YBSplitViewController: 0xSome_Address>

13

Page 14: Роман Ермолов - Отладка приложений под iOS

Интересные возможности

LLDB1 breakpoint 1.1 condition 1.2 command

Page 15: Роман Ермолов - Отладка приложений под iOS

print/po

Page 16: Роман Ермолов - Отладка приложений под iOS

print/po- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; //... }

16

Page 17: Роман Ермолов - Отладка приложений под iOS

- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; NSLog(@"%f", self.collapsedHeight); //... }

17

print/po

Page 18: Роман Ермолов - Отладка приложений под iOS

- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; //... }

18

// Добавляем команду print self.collapsedHeight

(CGFloat) $0 = 15

print/po

Page 19: Роман Ермолов - Отладка приложений под iOS

print/po

19

// Добавляем команду po self.childViewController

// Добавляем команду expression (void)NSLog(@"Content insets %@", (NSString *)NSStringFromUIEdgeInsets(self.contentInsetsInCarousel))

<ViewController 0xSome_Address lines: 5, text: some_title>

2015-08-16 12:30:25.604 Debugging-Objc[7319:398126] Content insets {10, 20, 30, 40}

Page 20: Роман Ермолов - Отладка приложений под iOS

thread return

Page 21: Роман Ермолов - Отладка приложений под iOS

thread return- (void)showAlertViewIfNeeded { if (![self shouldShowAlertView]) { return; } [self showAlertView]; } - (BOOL)shouldShowAlertView { return ([self application].applicationState == UIApplicationStateActive && [self isSyncInitializing]); }

21

Page 22: Роман Ермолов - Отладка приложений под iOS

thread return- (void)showAlertViewIfNeeded { // if (![self shouldShowAlertView]) { // return; // } [self showAlertView]; } - (BOOL)shouldShowAlertView { return YES; // return ([self application].applicationState == UIApplicationStateActive // && [self isSyncInitializing]); }

22

Page 23: Роман Ермолов - Отладка приложений под iOS

thread return- (BOOL)shouldShowAlertView { return ([self application].applicationState == UIApplicationStateActive && [self isSyncInitializing]); } // Добавляем команду thread return YES

23

thread return 123.45 thread return [NSArray array] thread return @"string"

Page 24: Роман Ермолов - Отладка приложений под iOS

Интересные возможности

LLDB1 breakpoint 1.1 condition 1.2 command

Page 25: Роман Ермолов - Отладка приложений под iOS

watchpoint@implementation YBFieldValidator - (void)validateField:(NSString *)field { if ([self fieldIsEmpty:field]) { _state = YBJSONRequestStateFailed; } else { _state = YBJSONRequestStateSuccess; } } - (void)setInvalidStateWithErrors:(NSArray *)errors { _state = YBJSONRequestStateFailed; } @end

25

Page 26: Роман Ермолов - Отладка приложений под iOS

watchpoint

26

@implementation YBFieldValidator - (void)validateField:(NSString *)field { if ([self fieldIsEmpty:field]) { _state = YBJSONRequestStateFailed; } else { _state = YBJSONRequestStateSuccess; } } - (void)setInvalidStateWithErrors:(NSArray *)errors { _state = YBJSONRequestStateFailed; } @end

Page 27: Роман Ермолов - Отладка приложений под iOS

watchpoint(lldb) watchpoint set variable —-watch read_write _state Watchpoint created: Watchpoint 1: addr = 0xSome_Address size = 8 state = enabled type = rw watchpoint spec = '_state' new value: 0

27

Watchpoint 1 hit: old value: 0 new value: 3

Page 28: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

Page 29: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

29

iOS 7-(lldb) po [[[[UIApplication sharedApplication] delegate] window] recursiveDescription] <UIWindow: 0xSome_Address; frame = (0 0; 375 667); ...> | <UIView: 0xSome_Address; frame = (0 0; 375 667); ...> | | <ViewWithCustomNextResponder: 0xSome_Address; ...>

iOS 8+

Page 30: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

30

Page 31: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

31

Page 32: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

Reveal Spark Inspector

32

Page 33: Роман Ермолов - Отладка приложений под iOS

Отладка иерархии UIView

(lldb) expression (void)[0x7fd7aaec45b0 setTintColor:[UIColor redColor]]

33

(lldb) expression (void)[CATransaction flush]

Page 34: Роман Ермолов - Отладка приложений под iOS

Отладка без исходников

Page 35: Роман Ермолов - Отладка приложений под iOS

Отладка без исходников

35

Page 36: Роман Ермолов - Отладка приложений под iOS

Отладка без исходников

36

Sample app Safari

Page 37: Роман Ермолов - Отладка приложений под iOS

Процесс отладки1 Определение точки входа

2 Остановка программы

3 Оценка текущего состояния

4 Анализ поведения

37

Page 38: Роман Ермолов - Отладка приложений под iOS

Работа с методами

Page 39: Роман Ермолов - Отладка приложений под iOS

Работа с методами

// objc.h typedef id (*IMP)(id self, SEL _cmd, ...);

39

@interface CustomClass : NSObject - (void)methodFoo:(id)foo bar:(id)bar baz:(id)baz; - (void)setQux:(CGFloat)qux; - (void)setCorge:(CGRect)corge; @end

// NSObject.h - (IMP)methodForSelector:(SEL)aSelector; + (IMP)instanceMethodForSelector:(SEL)aSelector;

Page 40: Роман Ермолов - Отладка приложений под iOS

Работа с методами

40

// 1. Получаем адрес функции (lldb) expression IMP $address = (IMP)[[CustomClass class] instanceMethodForSelector:@selector(methodFoo:bar:baz:)]

// 2. Ставим breakpoint на адрес (lldb) breakpoint set —-address $address Breakpoint 1: where = SomeApplication`___lldb_unnamed_function653$$, address = 0xSome_Address

Page 41: Роман Ермолов - Отладка приложений под iOS

Работа с методами. АргументыСпособы передачи аргументов в функцию:

через регистры процессора

через стек

смешанный (часть передается через регистры, часть через стек или другую память)

41

Архитектуры:

armv7* / arm64 / x86_64

Page 42: Роман Ермолов - Отладка приложений под iOS

Работа с методами. Аргументы

42

armv7 arm64 x86_64 алиас

self r0 x0 rdi $arg1

_cmd r1 x1 rsi $arg2

arg1 r2 x2 rdx $arg3

arg2 r3 x3 rcx $arg4

arg3 $(sp) x4 r8 $arg5

Page 43: Роман Ермолов - Отладка приложений под iOS

Работа с методами. Аргументы

43

// Устанавливаем breakpoint - (void)methodFoo:(id)foo bar:(id)bar baz:(id)baz;(lldb) po $arg1 <CustomClass: 0xSome_Address>

(lldb) print (SEL)$arg2 (SEL) $0 = "methodFoo:bar:baz:"(lldb) po $arg3 <FooClass: 0xSome_Address>

(lldb) po $arg4 <BarClass: 0xSome_Address>

(lldb) po $arg5 <BazClass: 0xSome_Address>

Page 44: Роман Ермолов - Отладка приложений под iOS

Работа с методами. Аргументы (x86_64)

44

// Устанавливаем breakpoint - (void)setQux:(CGFloat)qux;

(lldb) po $arg1 <CustomClass: 0xSome_Address>(lldb) print (SEL)$arg2 (SEL) $0 = "setQux:"(lldb) print $arg3 (unsigned long) $1 = 4677571844(lldb) expression (void)NSLog(@"%f", $xmm0) 2015-08-16 12:33:50.316 Debugging-Objc[4470:281979] 0.900000

[customClassObject setQux:0.9];

Page 45: Роман Ермолов - Отладка приложений под iOS

Работа с методами. Аргументы (x86_64)

45

// Устанавливаем breakpoint - (void)setCorge:(CGRect)corge;

(lldb) po $arg1 <CustomClass: 0xSome_Address>(lldb) print (SEL)$arg2 (SEL) $0 = "setCorge:"(lldb) print $arg3 (unsigned long) $1 = 4677571844

[customClassObject setCorge:CGRectMake(10.5, 15.5, 30, 40)];

Page 46: Роман Ермолов - Отладка приложений под iOS

Работа с методами. Аргументы (x86_64)

46

struct CGRect { CGPoint origin; CGSize size; };

(lldb) memory read $rsp+8 --format float64 --count 4 --size 8

struct CGPoint { CGFloat x; CGFloat y; };

struct CGSize { CGFloat width; CGFloat height; };

0xSome_Address : {10.5} // origin.x 0xSome_Address+8 : {15.5} // origin.y 0xSome_Address+16: {30} // size.width 0xSome_Address+24: {40} // size.height

Page 47: Роман Ермолов - Отладка приложений под iOS

Работа с объектами

Page 48: Роман Ермолов - Отладка приложений под iOS

Работа с объектами/// A pointer to an instance of a class. typedef struct objc_object *id;

/// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };

48

Page 49: Роман Ермолов - Отладка приложений под iOS

Работа с объектами

49

@interface CustomClass : NSObject { @private NSInteger _counter; } @end

struct CustomClass_object { Class isa; NSInteger _counter; };

Page 50: Роман Ермолов - Отладка приложений под iOS

Работа с объектами. Значение ivar

(lldb) po [0xSome_Address valueForKey:@"_counter"] 123

50

// 1. Получаем описание переменной (lldb) expression struct objc_ivar* $variable = (struct objc_ivar*) class_getInstanceVariable([CustomClass class], "_counter")// 2. Получаем смещение (lldb) expression ptrdiff_t $offset = (ptrdiff_t)ivar_getOffset($variable)// 3. Получаем значение переменной (lldb) memory read 0xSome_Address+$offset --format int64 --count 1 --size 8 0xSome_Address+$offset: {123}

Page 51: Роман Ермолов - Отладка приложений под iOS

Работа с объектами. Watchpoint

51

// 1. Получаем описание переменной (lldb) expression struct objc_ivar* $variable = (struct objc_ivar*) class_getInstanceVariable([CustomClass class], "_counter")// 2. Получаем смещение (lldb) expression ptrdiff_t $offset = (ptrdiff_t)ivar_getOffset($variable)// 3. Ставим watchpoint на адрес (lldb) watchpoint set expression —-watch read_write —-size 8 -- $arg1+$offset Watchpoint created: Watchpoint 0: addr = 0xSome_Address size = 8 type = rw new value: 0

Page 52: Роман Ермолов - Отладка приложений под iOS

ChiselУстановка брейкпоинтов на метод класса/объекта

Установка watchpoint’ов

Иерархия UIViewController

Открытие UIImage, UIView, UIColor в Preview

многое другое!

52

Page 53: Роман Ермолов - Отладка приложений под iOS

Hopper

Page 54: Роман Ермолов - Отладка приложений под iOS

Hopper

Дизассемблер

Декомпилятор

Отладчик

54

Page 55: Роман Ермолов - Отладка приложений под iOS

Hopper

55

Page 56: Роман Ермолов - Отладка приложений под iOS

Hopper

56

Page 57: Роман Ермолов - Отладка приложений под iOS

Hopper

57

Page 58: Роман Ермолов - Отладка приложений под iOS

Hopper

58

Page 59: Роман Ермолов - Отладка приложений под iOS

Процесс отладки

59

1 Определение точки входа

2 Остановка программы

3 Оценка текущего состояния

4 Анализ поведения

Page 60: Роман Ермолов - Отладка приложений под iOS

Итоги1 Интересные возможности LLDB2 Отладка иерархии UIView3 Отладка без исходников

Page 62: Роман Ермолов - Отладка приложений под iOS

Спасибо за внимание!

Page 63: Роман Ермолов - Отладка приложений под iOS

Вопросы? (:

Page 64: Роман Ермолов - Отладка приложений под iOS

64

Роман Ермолов

iOS-разработчик

Контакты

@roman_ermolov

[email protected]