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. Я предполагаю, что это еще не вздох зрелый продукт.   -  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