2014-11-07 2 views
4

Я пытаюсь добавить возможность генерации трассировки стека из дампа ядра на Mac автоматически при выходе из строя одного из наших тестов.Сценарий LLDB для получения трассировки стека после сбоя

я был в состоянии сделать это довольно легко на Linux с

gdb --batch --quiet -ex "thread apply all bt" -ex "quit" <binary> <core file> 2> /dev/null 

Но у меня возникают некоторые проблемы, делая то же самое на Mac (OSX 10.8) с lldb. Для начала версия lldb, которую я использую, - lldb-310.2.37.

Мой первоначальный подход использовать опцию -s и передать в файл сценария следующим образом:

target create -c <core file> <binary> 
thread backtrace all 
quit 

Изначально у меня были некоторые проблемы, которые я думаю, что было вызвано отсутствием новой строки в конце файла сценария который заставлял lldb не выходить, но после этого был исправлен, я получаю следующее: Выполнение команд в 'lldbSource'.

(lldb) target create -c <core file> <binary> 
Core file '<core file>' (x86_64) was loaded. 
(lldb) thread backtrace all 
error: Aborting reading of commands after command #1: 'thread backtrace all' failed with error: invalid thread 
Aborting after_file command execution, command file: 'lldbSource' failed. 

Самое смешное, после того, как это произойдет, мы до сих пор работаем lldb, и выпуск «нить трассировки все» вручную работает просто отлично.

Итак, подход № 2 заключался в создании скрипта python и использовании их API-интерфейса python (я пробовал это, прежде чем выяснять, что начальный блокиратор, который я описал, был связан с отсутствующей новой строкой).

Мой сценарий:

import lldb 
debugger = lldb.SBDebugger.Create() 
target = debugger.CreateTarget('<binary>') 
if target: 
process = target.LoadCore('<core file>') 
if process: 
    print process.exit_description 
    for thread in process: 
    print 'Thread %s:' % str(thread.GetThreadID()) 
    print '\n'.join(str(frame) for frame in thread) 

Проблема у меня с этим подходом является то, что process.exit_description является возвращение None (и поэтому каждый вещь, которую я пробовал, документация Python API LLDB является почти полностью бесполезна) ,

Выход Я ищу из этого вызова нечто похожее на следующее:

Process 0 stopped 
* thread #1: tid = 0x0000, 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16, stop reason = signal SIGSTOP 
    frame #0: 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16 
libsystem_c.dylib`strlen + 16: 
-> 0x7fff8aca4670: pcmpeqb (%rdi), %xmm0 
    0x7fff8aca4674: andl $0xf, %ecx 
    0x7fff8aca4677: shll %cl, %eax 
    0x7fff8aca4679: pmovmskb %xmm0, %ecx 

Это выход автоматически LLDB собственно при загрузке файла дампа. Мне не обязательно нужен дамп сборки, но я хочу, по крайней мере, поток, структуру и причину.

Я думаю, что первый подход, который я использовал, если бы его можно было заставить работать, был бы идеальным, но в любом случае для меня все в порядке. У меня нет контроля над версией LLDB, которая будет использоваться, к сожалению, поэтому я не могу просто обновиться до последней версии и посмотреть, исправлена ​​ли ошибка.

Другие подходы к получению желаемого результата также приветствуются. Для контекста это будет вызываться из скрипта perl.

ответ

1

TOT lldb от lldb.llvm.org имеет новый режим «--batch», который будет работать так же, как и пакетный режим gdb, и исправляет некоторые ошибки, из-за которых команды исходного кода командной строки ведут себя лучше. Если вы можете создать свой собственный lldb, вы можете получить эти исправления сейчас, иначе вам придется подождать следующего обновления Xcode.

Описание exit_description равно None, потому что ваш процесс не вышел из строя, он разбился. Обратите внимание, что по крайней мере на OS X несколько потоков могут иметь одновременные исключения к тому моменту, когда процесс обрушится на сбой, на самом деле не очень полезно сказать, что процесс разбился. Вы должны спросить темы. Состояние остановки, которое lldb выводит, когда поток останавливается, доступен с помощью метода GetStatus.

stream = lldb.SBStream() 
process.threads[0].GetStatus(stream) 
print stream.GetData() 

Это похоже не очень полезная строка справки.

+0

Это сработало, спасибо. – Bwmat

3

Аргумент командной строки --batch поддерживается в версии lldb, которая поставляется с Xcode 7.2 (lldb-340.4.119) и, возможно, раньше.

Это не документировано в the man page, но документировано в lldb --help:

-b 
    --batch 
     Tells the debugger to running the commands from -s, -S, -o & -O, 
     and then quit. However if any run command stopped due to a signal 
     or crash, the debugger will return to the interactive prompt at the 
     place of the crash. 

Этих другие параметры командной строки полезны для автоматизации lldb:

-o 
    --one-line 
     Tells the debugger to execute this one-line lldb command after any 
     file provided on the command line has been loaded. 

    -k 
    --one-line-on-crash 
     When in batch mode, tells the debugger to execute this one-line 
     lldb command if the target crashes. 

Используя эти средства, я кусочки вместе следующая команда:

ulimit -c unlimited && (<binary> || (lldb -c `ls -t /cores/* | head -n1` \ 
    --batch -o 'thread backtrace all' -o 'quit' && exit 1)) 

Эта команда:

  1. Enables core dumps
  2. Запускает исполняемый <binary>
  3. Если это не удается, бежит lldb на самой недавно созданного дампа ядра в /cores (надеюсь, правый один)
  4. печатает Цепочки вызовов всех threads
  5. Выход с ненулевым статусом, чтобы эта команда могла быть встроена в другие рабочие процессы (скрипты CI, Makefile и т. д.)

Я бы предпочел напрямую запустить lldb на <binary>, чтобы команда не полагалась на угадывание в правильном файле ядра. Но lldb по-прежнему не имеет возможности заставить его выйти с ненулевым статусом выхода - эквивалентом опции -return-child-result GDB или quit 1 - так что я не знал бы, успешно ли отлаженная программа или нет. I filed an issue, запрашивающий такую ​​функцию.

+0

lldb-320.4.124.10 пока не поддерживает опцию '--batch'. – WKPlus

Смежные вопросы