Slide 1

Slide 1 text

LLDB Расширения Как проапгрейдить отладчик при помощи Python Сергей Лем · Avito.iOS · Москва · 02 Дек '17

Slide 2

Slide 2 text

Сергей Лем iOS Engineer @Badoo @turbulem @iamlem

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Сложности отладки Заточка lldb для преодоления этих сложностей Выводы О чем поговорим

Slide 5

Slide 5 text

Чего не хватает? Сложности отладки

Slide 6

Slide 6 text

Исследовать NSSearchPathForDirectoriesInDomains(...) UIImage -> assetName Исследовать Private API

Slide 7

Slide 7 text

(NS)Dictionary (NS)Data (NS)URLRequest JSON .png curl Увидеть

Slide 8

Slide 8 text

Выполнить без перекомпиляции DispatchQueue.asyncAfter(...) Timer.scheduledTimer(...) Singleton.shared.doSomethingGlobal()

Slide 9

Slide 9 text

Типичный процесс Компиляция Исследование Внесение изменений Много времени проходит здесь Цель здесь

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Заточка lldb Как сделать отладку проще и приятнее?

Slide 12

Slide 12 text

Расширения LLDB • Алиасы • Брейкпоинт хуки • Кастомные команды

Slide 13

Slide 13 text

Расширения LLDB Алиасы Делам длинную команду короче command alias

Slide 14

Slide 14 text

Расширения LLDB Алиасы command alias simulateMemoryWarning po [[UIApplication sharedApplication] _receivedMemoryNotification] Симулируем нехватку памяти

Slide 15

Slide 15 text

Расширения LLDB Алиасы command alias printDocumentsPath po NSSearchPathForDirectoriesInDomains(9,1,YES)[0] Печатаем путь к папке Documents

Slide 16

Slide 16 text

Расширения LLDB RegEx команды Команды на основе регулярок command regex 's///'

Slide 17

Slide 17 text

Расширения LLDB RegEx команды command regex assetName 's/(.+)/po [[%1 imageAsset] assetName]/' Находим имя ресурса в UIImage

Slide 18

Slide 18 text

Расширения LLDB RegEx команды command regex asyncMainAfter 's/(\d+) (.+)/expression -- (lldb) asyncMainAfter 3 self.update() Выполняем выражение без перезапуска DispatchQueue.main.async { DispatchQueue.main.asyncAfter(deadline: .now() + %1) { %2 } }/'

Slide 19

Slide 19 text

Расширения LLDB RegEx команды • Множество задач можно решить подстановкой в шаблон выражения • Зависят от контекста • Длинные выражения тяжело писать и поддерживать • Нельзя выполнить несколько команд

Slide 20

Slide 20 text

Расширения LLDB RegEx команды command regex assetName 's/(.+)/expression -l objc -O -- [(UIImageAsset*)[(UIImage*)%1 imageAsset] assetName]/' Пример без привязки к контексту (lldb) assetName 0x600deafbeaf0 Придется использовать адрес

Slide 21

Slide 21 text

Расширения на основе Python скриптов

Slide 22

Slide 22 text

Расширения LLDB Python extensions lldb содержит интерпретатор

Slide 23

Slide 23 text

Расширения LLDB Python extensions • Интерфейс к отладчику • SB-объекты - Scripting Bridge Модуль lldb • Биндинги к C++ объектной модели

Slide 24

Slide 24 text

Расширения LLDB Python extensions Лучше использовать внешние модули

Slide 25

Slide 25 text

Расширения LLDB Python extensions Импортировать модули на старте lldb ~/.lldbinit

Slide 26

Slide 26 text

Расширения LLDB Python extensions Как использовать скрипты на Python?

Slide 27

Slide 27 text

Расширения LLDB Python extensions Хуки для брейкпоинтов frame: SBFrame - текущий фрейм bp_location: SBBreakpointLocation - место срабатывания

Slide 28

Slide 28 text

Расширения LLDB Python extensions breakpoint command add -F module.breakpoint_hook без указания breakpoint_number добавляет команду к последнему созданному

Slide 29

Slide 29 text

Расширения LLDB Python extensions • SBBreakpointLocation и SBBreakpoint содержат API, который использует Xcode • return False --> "Automatically continue..."

Slide 30

Slide 30 text

Расширения LLDB Python extensions UIViewAlertForUnsatisfiableConstraints

Slide 31

Slide 31 text

Расширения LLDB Python extensions Команды на Python class CommandClass: def __init__(self, dbg, session_dict): print 'Command "AwesomeCommand" is ready for use!' def __call__(self, dbg, args, exec_context, output): doSomeMagic(args) def Command(dbg, args, exec_context, output, session_dict): doSomeMagic(args)

Slide 32

Slide 32 text

Расширения LLDB Создание команды на Python Конфигурация command script -c . command script -f .

Slide 33

Slide 33 text

Расширения LLDB Создание команды на Python def __lldb_init_module(debugger, internal_dict): module = __name__ cmd = 'command script add -c %s.Command Command' % module debugger.HandleCommand(cmd) Удобный способ конфигурации

Slide 34

Slide 34 text

Расширения LLDB Создание команды на Python ~/.lldbinit command alias reloadCommands command script import /Path/To/commands.py reloadCommands Удобный способ импорта

Slide 35

Slide 35 text

Демо https://github.com/turbulem/lldb_extensions_talk

Slide 36

Slide 36 text

Расширения LLDB Выводы Зачем использовать? • Обойти ограничения lldb • Упростить анализ • Новые инструменты исследования

Slide 37

Slide 37 text

Расширения LLDB Выводы Как использовать? • Определять команды в отдельных модулях • Не привязываться к контексту • Явно указывать модули (import / @import) • Добавить help и usage

Slide 38

Slide 38 text

Расширения LLDB Выводы Ограничения и проблемы Множество примеров в сети Скромная документация Выражения работают неочевидно Со временем к этому привыкаешь :)

Slide 39

Slide 39 text

С чего начать?

Slide 40

Slide 40 text

Расширения LLDB Что делать дальше? • Что занимает много времени? • Что заставляет пересобирать приложение? Проанализируйте свой опыт Новые команды

Slide 41

Slide 41 text

Расширения LLDB Что делать дальше? 1. Документация LLDB https://lldb.llvm.org/python-reference.html 2. Набор полезных команд от Facebook https://github.com/facebook/chisel 3. Еще немного команд https://github.com/DerekSelander/LLDB 4. Сессия о приемах работы с lldb https://developer.apple.com/videos/play/wwdc2016/417/ @turbulem @iamlem

Slide 42

Slide 42 text

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