LINUX.ORG.RU

Приложение падает до входа в main

 ,


2

2

Пытаюсь отладить приложение, которое падает до входа в main.

Приложение линкуется с кучей библиотек, которые были написаны разными людьми в разное время. Некоторые библиотеки слинкованы между собой.

Есть подозрение, что все это дело падает на инициализации какой-то static переменной класса, т.к. подобную ошибку когда-то в этих библиотеках уже находили.

В общем жду советов, как все это безобразие можно отладить или хотя бы детектировать ошибку. Желательно, чтобы способ ограничивался использованием gdb и утилит из стандартного набора GNU.

Update: Библиотеку в которой происходит падение вычислили. Теперь необходимо понять, где именно в этой библиотеке происходит падение.
Все (приложение и библиотеки) собрано с отладочной информацией.

★★★★★

Последнее исправление: trex6 (всего исправлений: 2)

падает до входа в main
когда-то в этих библиотеках уже находили.

Раньше всё работало? Типа она сама появилась?

vahtu
()

Плюсую вопрос про сообщения и просьбу собрать с отладочной информацией (ключ -g в gcc).

Если сообщения есть и фигурируют слова а-ля Segmentation fault, то вопрос такой: а Core dump есть?

Может быть, не генерится, т.к. размер дампа превышает текущий установленный. Попробуйте перед запуском приложения выполнить ulimit -c unlimited, потом запустить, и посмотреть наличие файла с именем core.* в рабочем каталоге программы.

Потом уже пробовать gdb с командой bt. А вообще, имхо, проще запустить сразу под отладчиком:

gdb --args ./<your_app_executable>

Затем сказать r

Затем bt (когда упадёт и выдаст приглашение на ввод команды)

GBullfinch
()
Ответ на: комментарий от cdshines

Падает без всяких сообщений?

Segmentation fault

trex6 ★★★★★
() автор топика
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от Bad_ptr

Код есть. Собираем с дебагом.
После падения выдает цифры. Можно по ним как-то определить место падения?

trex6 ★★★★★
() автор топика
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от GBullfinch

Именно так и пробую.
При падении выдает адрес, по которому упал. Как можно посмотреть, что по этому адресу находится?

P.S. Слышал, что gdb можно запустить с возможностью «шагать назад». Возможно, кто-нибудь подскажет, как это сделать.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от unanimous

Библиотеки тоже собраны в debug версии.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от ono

Сам бинарник только инициализирует библиотеки и запускает цикл приложения. Можно ли как-то узнать, где в библиотеке произошло падение?

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Можно ли как-то узнать, где в библиотеке произошло падение?

Ты вообще читаешь то, что тебе отвечают? Да, можно. Запускаешь gdb и смотришь core (команду bt уже советовали). Если core не сгенерировался, делаешь ulimit -c большоечисло и снова запускаешь программу.

tailgunner ★★★★★
()
Ответ на: комментарий от vahtu

Если действительно падает ДО main, то отлаживать нужно не программу, а линкер.

Это линкер виноват, что конструктор глобального объекта фейлит?

tailgunner ★★★★★
()
Ответ на: комментарий от Reset

До входа в main программа не выполняется. Выполняется компоновка и какой-то стартовый код. ТС не указал компилятор, но, надеюсь это не наколенная поделка, а что-то вроде gcc. В этом случае его стартовый код выполнился триллионы раз и выполняется где-то сейчас. Т.е. вероятность, что он глючит исчезающе мала. Хотя...

vahtu
()
Ответ на: комментарий от vahtu
struct WTF
{
  WTF() {
    const char ** a = 0;
    *a = "wtf?";
  }
} wtf;

int main() {}

$ ./a.out
Segmentation fault

(gdb) r
Starting program: /home/xxx/a.out

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400532 in WTF::WTF() ()
(gdb) where
#0  0x0000000000400532 in WTF::WTF() ()
#1  0x0000000000400506 in __static_initialization_and_destruction_0(int, int) ()
#2  0x000000000040051b in _GLOBAL__sub_I_wtf ()
#3  0x000000000040059d in __libc_csu_init (argc=1, argv=0x7fffffffd7c8, envp=0x7fffffffd7d8) at elf-init.c:124
#4  0x00007ffff72dd2c0 in __libc_start_main () from /lib64/libc.so.6
#5  0x0000000000400419 in _start () at ../sysdeps/x86_64/elf/start.S:113
(gdb)

Reset ★★★★★
()
Ответ на: комментарий от vahtu

Компилятор gcc.
Яндекс мне уже подсказал про .init секцию в so-библиотеках.
Теперь вопрос, как узнать ее расположение и поставить туда точку останова.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Так там не нужно ничего ставить. Как только упадёт, gdb сам покажет где именно. Вон Reset вверху привёл пример:

gdb your_executable
r
(упало)
bt

gag ★★★★★
()
Ответ на: комментарий от trex6

Яндекс мне уже подсказал про .init секцию в so-библиотеках.

Теперь вопрос, как узнать ее расположение и поставить туда точку останова.

facepalm.jpg

tailgunner ★★★★★
()
Ответ на: комментарий от gag

Отлично, он показал мне какие-то циферки. Я понимаю, что это ардес в памяти, но не могу понять, что там находится.

Поможете?

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Он наверное имеет в виду, что ты не сможешь поставить точку останова, не зная строки/имени конструктора. С другой стороны, если ты это знаешь, то и точка останова тебе не нужна :).

ЕМНИП можно поставить точку останова на адрес. А вообще покажи bt.

vahtu
()
Ответ на: комментарий от vahtu

Действительно, точку останова можно установить на адрес.
Но я не знаю, как узнать адрес .init секции в so-библиотеке.

P.S. Эта секция содержит код инициализации библиотеки, который должен быть выполнен перед ее использованием. Я подозреваю, что всяческие static-члены инициализируются именно там.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

такое бывает когда стек сорвали. сделай git bisect, или что-там у тебя за сорсконтроль, и найди в каком коммите баг появился. потом git show, и внимательно смотри на изменения. обычно этого хватает (если конечно сорсконтроль используется).

если сорсконтроля нет, то можно хардкорно - смотреть в регистры, искать в них адреса, и по адресам пытаться угадать какая функция могла к этим данным обращаться.

waker ★★★★★
()
Ответ на: комментарий от trex6

А более развернутый комментарий?

Пока ты не получил дамп с нормальным стектрейсом, все комментарии бесполезны. Попытки поставить точку останова в .init, о которой ты только что узнал из яндекса, еще и смешны.

tailgunner ★★★★★
()
Ответ на: комментарий от trex6

Отлично, он показал мне какие-то циферки

А это что?

vahtu
()
Ответ на: комментарий от tailgunner

Можете пояснить, почему смешны?
В этих секциях находится код, который, скорее всего, приводит к падению. Я хочу поставить точку останова на этот код. Что в этом смешного?

Стектрейс содержит только от 1 до 3-х вызовов функций, всегда разное количество при одних и тех же данных. Скорее всего это использование неинициализированого указателя.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Стектрейс содержит только от 1 до 3-х вызовов функций, всегда разное количество при одних и тех же данных. Скорее всего это использование неинициализированого указателя.

Ну покажи уже выхлоп. Что за секретность?

vahtu
()
Ответ на: комментарий от vahtu

Да нету у меня его сейчас под рукой. Завтра буду на работе - скину.

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Можете пояснить, почему смешны?

Потому что с тем же успехом можно поставить точку останова на любой из символов из постинга Reset: Приложение падает до входа в main (комментарий)

Что в этом смешного?

То, что ты узнал о секции .init 15 минут назад, но уже лезешь туда, не попробовав штатные средства более высокого уровня.

Скорее всего это использование неинициализированого указателя.

Похоже на то. Один способ поиска тебе уже подсказали: Приложение падает до входа в main (комментарий). Еще один способ - поискать все глобальные объекты и поставить точки останова на их конструкторы.

tailgunner ★★★★★
()
Ответ на: комментарий от trex6

Уверен? gdb пишет откуда он грузит debug инфу. Там точно есть все твои so?

Reset ★★★★★
()
Ответ на: комментарий от vahtu

До входа в main программа не выполняется

???

int foo() __attribute__((init)) {
}

типичный способ инициализации библиотеки. То есть произвести действия после линковки, но _ДО_ вызова main().

з.ы. за синтаксис не ручаюсь - вот вот закрытие олимпиады. Ждёмс

MKuznetsov ★★★★★
()
Ответ на: комментарий от trex6

Отлично, он показал мне какие-то циферки

Даёбтвоюмать, пока уж нам эти циферки.

anonymous
()
Ответ на: комментарий от Reset

В общем случае программа - это приложение+библиотеки. Но здесь в контексте кто и где виноват (приложение - библиотеки) лично у меня программа всё же ассоциируется с тем, что сам пишешь, т.е. с приложением.

gag ★★★★★
()

Ну так стектрейса библиотеки не будет?

cattail
()

man ltrace

Description: Tracks runtime library calls in dynamically linked programs ltrace is a debugging program which runs a specified command until it exits. While the command is executing, ltrace intercepts and records the dynamic library calls which are called by the executed process and the signals received by that process. It can also intercept and print the system calls executed by the program. The program to be traced need not be recompiled for this, so you can use it on binaries for which you don't have the source handy. You should install ltrace if you need a sysadmin tool for tracking the execution of processes.

DELIRIUM ☆☆☆☆☆
()
Последнее исправление: DELIRIUM (всего исправлений: 1)

Библиотеку в которой происходит падение вычислили. Теперь необходимо понять, где именно в этой библиотеке происходит падение.

сделать test-case этой библиотеки и усё..Полупустой проект в который подключается искомая библиотека и который содержит 1-2-3 статических объекта из библиотеки. +внимательно пересмотреть конструкторы.

MKuznetsov ★★★★★
()
Ответ на: комментарий от tailgunner

Теперь интерес к .init у меня уже больше академический.
Как я понял, вы все же не знаете, как поставить туда брейкпоинт?

trex6 ★★★★★
() автор топика
Ответ на: комментарий от trex6

Как я понял, вы все же не знаете, как поставить туда брейкпоинт?

Выяснить адрес и поставить. Следующим вопросом будет «как выяснить адрес»? objdump'ом, если у тебя не PIE. Если PIE - нужно покурить маны.

tailgunner ★★★★★
()

Нашел в gdb.pdf такую вещь:
set stop-on-solib-events
В итоге будем получать останов при любом событии, связанном с динамической библиотекой (любой). Сейчас смотрю, как можно узнать, что за библиотека будет грузиться и пробовать трассировать .init

trex6 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.