Можете ли вы получить какую-либо программу для Linux, чтобы распечатать трассировку стека, если она segfaults?

Если я запускаю программу из оболочки, и она segfaults:

$ buggy_program
Segmentation fault

Это скажет мне, однако, есть ли способ заставить программы печатать обратную трассировку, возможно, запустив что-то вроде этого:

$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)

Я также предпочел бы не использовать strace или ltrace для такой информации, поскольку они будут печататься в любом случае...

6 ответов

Решение

Возможно, есть лучший способ, но этот тип автоматизирует его.

Поместите следующее в ~/backtrace:

backtrace
quit

Поместите это в скрипт seg_wrapper.sh в каталоге на вашем пути:

#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
    gdb -q $1 core -x ~/backtrace
fi

ulimit команда делает так, чтобы ядро ​​было сброшено. "$@" это аргументы, данные скрипту, поэтому это будет ваша программа и ее аргументы. $? содержит состояние выхода, 139, по-видимому, состояние выхода по умолчанию для моей машины для segfault.

За gdb, -q означает тихий (без вступительного сообщения), и -x говорит gdb выполнять команды в данном файле.

использование

Таким образом, чтобы использовать его, вы просто:

seg_wrapper.sh ./mycommand and its arguments 

Обновить

Вы также можете написать обработчик сигнала, который делает это, см. Эту ссылку.

Извините, что приехал сюда через 2 года... наткнулся, когда искал что-то еще. Добавим это для полноты.

1) Хотя я думаю, что принятый ответ отличный, он требует GDB. Метод, с которым я знаком, использует libSegFault.so.

Если вы запустите свое приложение с

LD_PRELOAD=... путь к.../libSegFault.so myapp

Вы получите отчет с трассировкой, загруженными библиотеками и т. Д.

2) скрипт-обёртка catchsegv также доступно, что будет пытаться использовать addr2line перевести адреса в имя файла + номер строки.

Это гораздо более легкие решения, чем файлы core или gdb (например, хорошо для встроенных систем)

catchsegv

Это было упомянуто в другом ответе (но никоим образом не сфокусировано на). Это удобный инструмент в комплекте с проектом glibc. Он обеспечит обратную трассировку (и другую полезную отладочную информацию), только если программа действительно выполняет segfault.

Хорошая статья существует здесь.

Вы можете включить его в свои сценарии по своему усмотрению.

Тебе нужен друг каждого GDB

gdb <program> [core file]

После того, как вы загрузили свой основной файл, команда 'backtrace' (сокращенно bt) выдаст вам текущий стек вызовов. Если вы запускаете свою программу изнутри GDB, вы можете установить произвольные точки останова, проверить содержимое памяти и т. Д.

Ubuntu (как проект) использует Apport для этого. Вы можете посмотреть, как они это сделали.

https://wiki.ubuntu.com/Apport

Вот слегка модифицированный вариант сценария от Кайла Брандта. Это улучшено следующими способами:

  • не требует ручного взаимодействия, если трассировка стека длинная
  • некоторые coredumps сохраняются с именем шаблона ядра., соблюдайте этот параметр
  • не требует явного командного файла для GDB (он создаст временный)
  • ждать фоновых заданий

Автор сценария:

#!/bin/bash
gdbcommandfile=$(tempfile)
usepid=$(cat /proc/sys/kernel/core_uses_pid)
printf "set pagination off\nbacktrace\nquit\n" > $gdbcommandfile
ulimit -c unlimited
"$@"&
pid=$!
wait $!
if [[ $? -eq 139 ]]; then
    if [[ $usepid == 1 ]]; then 
        gdb -q $1 core.$pid -x $gdbcommandfile
    else
        gdb -q $1 core -x $gdbcommandfile
    fi
fi
rm $gdbcommandfile
Другие вопросы по тегам