iOS: Многоредовите команди за точка на прекъсване на LLDB не работят според очакванията

Опитвам се да направя нещо малко фантастично тук, но документите предполагат, че трябва да е възможно. Може би 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 да мига бързо, докато спира и възобновява изпълнението. Обикновено съжалявам за това, защото става не реагира и се срива малко след това.)

И така: Някакви идеи? Дали технологията все още не е готова или просто ми липсва някакво умно парче от пъзела, което ще поправи всичко? Или трябва да се откажа напълно и просто да живея с факта, че има някои части от вътрешността на обекта, които никога няма да разбера?...


person Archaeopterasa    schedule 27.03.2012    source източник
comment
Имаше други въпроси относно проблеми с докладването на SO при отстраняване на грешки с LLDB. Един въпрос, за който знам (но не мога да намеря препратката), съобщава, че проблемите изчезват при превключване обратно към GDB. Предполагам, че все още не е gasp зрял продукт.   -  person Peter M    schedule 28.03.2012
comment
@PeterM: Да, никога не съм имал (много) проблеми с това, че gdb е бъг, но функциите му са много по-ограничени за по-фантастични неща като това. Може би все пак трябва да се върна и да опитам отново в няколко версии...   -  person Archaeopterasa    schedule 28.03.2012


Отговори (1)


Командите за точка на прекъсване не могат да възобновят изпълнението и след това да си върнат контрола, поне днес. Има много неразрешени въпроси за това какво ще се случи, ако точка на прекъсване 1 изпълнява процеса и след това точка на прекъсване 2 бъде ударена. Освен целия въпрос дали кодовата база наистина може да обработва правилно вложените точки на прекъсване (тя е проектирана да...), какво означава, ако точка на прекъсване 2 реши, че изпълнението трябва да спре? Изхвърля ли се състоянието на точка на прекъсване 1?

Изглежда малко езотерично да се притеснявате, че точка на прекъсване ще удари друга точка на прекъсване, докато стъпвате на по-ниския процес, но освен ако не са уточнени всички подробности, за потребителя е лесно да се простреля в крака. Така че за днес командите за точка на прекъсване могат или да спрат, когато точката на прекъсване бъде достигната, или да продължат да се изпълняват - но няма никаква възможност да се изпълнява малко и да се извършва повече обработка. Знам, че това би било наистина полезна възможност за определени задачи, но има много проблеми, които трябва да бъдат обмислени, преди да може да се направи.

В някои случаи е възможно да се справите по обратния начин ... ако искате да спрете във функция parser() само когато е била извикана от функция lexer(), лесно е да поставите точка на прекъсване на lexer() с няколко команди на Python за да преминете един стеков кадър нагоре в стека и да видите каква е извикващата функция. Ако не е lexer(), продължете. Не мисля обаче, че това ще се отнася за това, което се опитвате да направите.

person Jason Molenda    schedule 17.10.2012