Роман Ермолов - Отладка приложений под ios
TRANSCRIPT
![Page 1: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/1.jpg)
![Page 2: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/2.jpg)
Роман Ермолов
Отладка приложений под iOS
![Page 3: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/3.jpg)
План1 Интересные возможности LLDB2 Отладка иерархии UIView3 Отладка без исходников
![Page 4: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/4.jpg)
Интересные возможности
LLDB1 breakpoint 1.1 condition 1.2 command
![Page 5: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/5.jpg)
Интересные возможности
LLDB1 breakpoint 1.1 condition 1.2 command
![Page 6: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/6.jpg)
breakpoint
- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; self.contentManagerVC.view.frame = self.layout.contentFrame; // ... self.voiceSearchController.view.frame = self.layout.voiceSearchFrame; }
6
![Page 7: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/7.jpg)
breakpoint
7
![Page 8: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/8.jpg)
breakpoint
8
![Page 9: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/9.jpg)
Интересные возможности
LLDB1 breakpoint 1.1 condition 1.2 command
![Page 10: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/10.jpg)
condition
10
@implementation YBSplitViewController - (void)loadView { self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; // ... } - (void)viewDidLoad { [super viewDidLoad]; // ... } @end
![Page 11: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/11.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/12.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/13.jpg)
condition
(lldb) po $arg1 <YBSplitViewController: 0xSome_Address>
13
![Page 14: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/14.jpg)
Интересные возможности
LLDB1 breakpoint 1.1 condition 1.2 command
![Page 15: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/15.jpg)
print/po
![Page 16: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/16.jpg)
print/po- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; //... }
16
![Page 17: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/17.jpg)
- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; NSLog(@"%f", self.collapsedHeight); //... }
17
print/po
![Page 18: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/18.jpg)
- (void)configureForScreenType:(YBScreenType)screenType { self.collapsedHeight = [[self class] collapsedHeightForScreenType:screenType]; //... }
18
// Добавляем команду print self.collapsedHeight
(CGFloat) $0 = 15
print/po
![Page 19: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/19.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/20.jpg)
thread return
![Page 21: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/21.jpg)
thread return- (void)showAlertViewIfNeeded { if (![self shouldShowAlertView]) { return; } [self showAlertView]; } - (BOOL)shouldShowAlertView { return ([self application].applicationState == UIApplicationStateActive && [self isSyncInitializing]); }
21
![Page 22: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/22.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/23.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/24.jpg)
Интересные возможности
LLDB1 breakpoint 1.1 condition 1.2 command
![Page 25: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/25.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/26.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/27.jpg)
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/28.jpg)
Отладка иерархии UIView
![Page 29: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/29.jpg)
Отладка иерархии 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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/30.jpg)
Отладка иерархии UIView
30
![Page 31: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/31.jpg)
Отладка иерархии UIView
31
![Page 32: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/32.jpg)
Отладка иерархии UIView
Reveal Spark Inspector
32
![Page 33: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/33.jpg)
Отладка иерархии UIView
(lldb) expression (void)[0x7fd7aaec45b0 setTintColor:[UIColor redColor]]
33
(lldb) expression (void)[CATransaction flush]
![Page 34: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/34.jpg)
Отладка без исходников
![Page 35: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/35.jpg)
Отладка без исходников
35
![Page 36: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/36.jpg)
Отладка без исходников
36
Sample app Safari
![Page 37: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/37.jpg)
Процесс отладки1 Определение точки входа
2 Остановка программы
3 Оценка текущего состояния
4 Анализ поведения
37
![Page 38: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/38.jpg)
Работа с методами
![Page 39: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/39.jpg)
Работа с методами
// 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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/40.jpg)
Работа с методами
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/41.jpg)
Работа с методами. АргументыСпособы передачи аргументов в функцию:
через регистры процессора
через стек
смешанный (часть передается через регистры, часть через стек или другую память)
41
Архитектуры:
armv7* / arm64 / x86_64
![Page 42: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/42.jpg)
Работа с методами. Аргументы
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/43.jpg)
Работа с методами. Аргументы
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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/44.jpg)
Работа с методами. Аргументы (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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/45.jpg)
Работа с методами. Аргументы (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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/46.jpg)
Работа с методами. Аргументы (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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/47.jpg)
Работа с объектами
![Page 48: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/48.jpg)
Работа с объектами/// 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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/49.jpg)
Работа с объектами
49
@interface CustomClass : NSObject { @private NSInteger _counter; } @end
struct CustomClass_object { Class isa; NSInteger _counter; };
![Page 50: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/50.jpg)
Работа с объектами. Значение 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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/51.jpg)
Работа с объектами. 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](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/52.jpg)
ChiselУстановка брейкпоинтов на метод класса/объекта
Установка watchpoint’ов
Иерархия UIViewController
Открытие UIImage, UIView, UIColor в Preview
многое другое!
52
![Page 53: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/53.jpg)
Hopper
![Page 54: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/54.jpg)
Hopper
Дизассемблер
Декомпилятор
Отладчик
54
![Page 55: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/55.jpg)
Hopper
55
![Page 56: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/56.jpg)
Hopper
56
![Page 57: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/57.jpg)
Hopper
57
![Page 58: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/58.jpg)
Hopper
58
![Page 59: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/59.jpg)
Процесс отладки
59
1 Определение точки входа
2 Остановка программы
3 Оценка текущего состояния
4 Анализ поведения
![Page 60: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/60.jpg)
Итоги1 Интересные возможности LLDB2 Отладка иерархии UIView3 Отладка без исходников
![Page 61: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/61.jpg)
МатериалыLLDB Command Map
Mac OS X Debugging Magic
iOS Debugging Magic
iOS ABI Function Call Guide
Hopper
Chisel
61
![Page 62: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/62.jpg)
Спасибо за внимание!
![Page 63: Роман Ермолов - Отладка приложений под iOS](https://reader036.vdocuments.pub/reader036/viewer/2022081801/58786edf1a28ab497b8b59dd/html5/thumbnails/63.jpg)
Вопросы? (: