Опитвам се да направя нещо малко фантастично тук, но документите предполагат, че трябва да е възможно. Може би LLDB все още е твърде нов, но получавам много сривове/блокировки на дебъгера и дори когато това не се случи, изглежда не работи, както очаквах.
Опитвам се да събера обвивка за отстраняване на грешки около всички извиквания на селектора, за да извлека графиката на извикване на съобщение в определена част от кода. (Бих могъл да обясня защо, ако наистина искате да знаете, но всъщност не е от значение за проблема с дебъгера.)
Започвам с точка на прекъсване на Xcode на реда, където искам да започна да проследявам нещата (за бонус точки това се случва във вторична нишка, но преди да попитате, не, нищо в която и да е друга нишка не извършва достъп до този обект или всичко в неговия подграф на свойства):
[myObject startProcessing];
Точката на прекъсване се задейства и аз стартирам "bt", само за да извлека:
* thread #5: tid = 0x2203, 0x000277d2 .........
След това правя нещо леко зло: поставям точка на прекъсване в objc_msgSend, точно в инструкцията, където тя извиква селектора на реалния обект. objc_msgSend изглежда така:
libobjc.A.dylib`objc_msgSend:
...(instructions)...
0x37babfa4: bx r12
...(more instructions)...
(Всъщност има две bx извиквания, но нека опростим нещата.) Пускам:
breakpoint set -a 0x37babfa4 -t 0x2203
(TID е включен, защото имам достатъчно проблеми с проследяването на тази нишка и не се нуждая от намеса на неподходящи неща.)
Ето къде идва скриптът. Описаната по-горе настройка работи точно както бих искал. Ако възобновя изпълнението, докато точката на прекъсване се задейства, мога да стартирам:
frame select 0
thread step-inst -m this-thread 5
frame info
continue
и ефектът ще бъде, че дебъгерът:
- се премества в рамката objc_msgSend
- стъпки по една инструкция, придвижвайки го напред в рамката за избор на обект, към която сочеше
- показва подходящи подробности (тип обект, извикан селектор)
- възобновява изпълнението
в който момент мога да продължа да поставям тези четири команди отново и отново и да копирам изхода, докато се намразя.
Ако, от друга страна, стартирам:
breakpoint command add -s command
и поставете тези точно същите команди, всичко се разваля. Не се придвижва до рамката за избор на обект. Не показва детайлите на рамката или поне не правилните - в зависимост от различни настройки (вижте по-долу), може или не може да показва "objc_msgSend" като текуща функция. Не възобновява изпълнението.
В този случай, ако мога да накарам този пример да работи, ще бъда най-вече щастлив. Но за още повече бонус точки, аз също опитах това с python, което бих предпочел, защото би позволило много по-сложно регистриране:
breakpoint command add -s python
> thread = frame.GetThread()
> thread.StepInstruction(1)
> newFrame = thread.GetFrameAtIndex(0)
> print " " * thread.GetNumFrames() + newFrame.GetFunctionName()
> process = thread.GetProcess()
> process.Continue()
> DONE
Отново не е добре. Отново в зависимост от малки детайли, това може или не може да отпечата нещо (обикновено objc_msgSend), но никога не отпечатва правилното нещо. Той никога не пристъпва напред към инструкцията. Никога не подновява изпълнението след това.
И отново, версията на Python работи добре, ако го направя на ръка: ако изчакам да се задейства точката на прекъсване, след това изпълня "скрипт" и въведа същите тези редове, работи както се очаква. Някои части дори ще работят изолирано, напр. ако премахна всичко с изключение на частите, които получават процеса и извикам process.Continue() и ги задействам автоматично, това „работи“ (което означава, че виждам подканата за lldb да мига бързо, докато спира и възобновява изпълнението. Обикновено съжалявам за това, защото става не реагира и се срива малко след това.)
И така: Някакви идеи? Дали технологията все още не е готова или просто ми липсва някакво умно парче от пъзела, което ще поправи всичко? Или трябва да се откажа напълно и просто да живея с факта, че има някои части от вътрешността на обекта, които никога няма да разбера?...