когда падает с segfault и указатель на инструкцию (IP) равен нулю — возможно ли вообще как-то раскрутить стэк в обработчике или дампе, или это в принципе невозможно?
или извлечь хоть какую-то полезную инфу?
по идее это невозможно, но другой стороны gdb это както делает когда ловит segfault
хотя наверно он какойто флажок на процессоре ставит во время дебага
TP>когда падает с segfault и указатель на инструкцию (IP) равен нулю — возможно ли вообще как-то раскрутить стэк в обработчике или дампе, или это в принципе невозможно?
IP к раскрутке стека не имеет отношения. Тут важно наличие стэк-фреймов и неиспорченный указатель стэка. Для раскрутки есть разные либы. Например Boost.Stacktrace. Но в доке к либе сказано, что это плохая идея раскручивать стэк в сигналах. Лучше сохранить дамп, а потом его анализировать.
Здравствуйте, ArtDenis, Вы писали:
AD> ... Но в доке к либе сказано, что это плохая идея раскручивать стэк в сигналах. Лучше сохранить дамп, а потом его анализировать.
Точнее даже не так. Вот дословно:
The only way to deal with the problem — dump raw stacktrace into file/socket and parse it on program restart.
тут как раз раскручивать нечего — IP (он же указатель на текущую инструкцию ) нулевой
в принципе об этом даже доки говорят ... но я думал — вдруг есть какие грязные хаки
дамп тоже мало чего дает ... точнее вообще ничего
полгигабайта и никаких стеков вообще
воспризвожу так:
int (*p)(); // NOLINT
p = 0x0; // NOLINT
(*p)();// NOLINT
Здравствуйте, reversecode, Вы писали:
R>вообще в процессорах уже давно есть возможности сохранят адрес(а) последних перехода(ов) R>mtrr last branch from ip
это покурим, спасибо
R>хз как там в гдб с этим R>мне всегда хватало bt и printf
под дебаком все ловится и стек дает а вот в дампе или обработчике ничего не вынуть
Здравствуйте, The Passenger, Вы писали:
TP>Здравствуйте, ArtDenis, Вы писали:
TP>тут как раз раскручивать нечего — IP (он же указатель на текущую инструкцию ) нулевой TP>в принципе об этом даже доки говорят ... но я думал — вдруг есть какие грязные хаки
TP>дамп тоже мало чего дает ... точнее вообще ничего TP>полгигабайта и никаких стеков вообще
TP>воспризвожу так:
TP> int (*p)(); // NOLINT TP> p = 0x0; // NOLINT TP> (*p)();// NOLINT
int main()
{
int (*p)(void);
p = 0x0;
(*p)();
}
gcc -ggdb test.c && ./a.out
coredumpctl gdb 697138
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000055699740612f in main () at test.c:5
backtrace явно есть несмотря на прыжок по нулевому адресу.
Здравствуйте, Zhendos, Вы писали:
Z>backtrace явно есть несмотря на прыжок по нулевому адресу.
Подозреваю что сдампить начало потока и последний вызов по нудевому адресу оно могет, а вот восстановить стек неа
причем все это еще не совсем стабильно
например, я сделал несколько вложенных функций с багом в конечной, и если я например сделаю банальный access violation :
int e = (int)*(int*)0;
то стек у меня такойЖ
(gdb) bt
#0 0x0000000000407392 in ?? ()
#1 0x00007fcbe1112e60 in ?? ()
#2 0x00000000004086ed in ?? ()
#3 0x00007fcbe1112e60 in ?? ()
#4 0x00000000004073b7 in ?? ()
#5 0x00007fcbe1112e70 in ?? ()
#6 0x00000000004073c2 in ?? ()
#7 0x00007fcbe1112e80 in ?? ()
#8 0x00000000004073cd in ?? ()
#9 0x00007fcbe1112ea0 in ?? ()
#10 0x000000000040872f in ?? ()
#11 0x0000000000000000 in ?? ()
а если с segfault ip 0 то такойЖ
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000000000040739b in ?? ()
#2 0x00007fb4336c2e60 in ?? ()
#3 0x0000000000000000 in ?? ()
(gdb)
хз чего символов нету вроде -g3 но не суть, — смысл понятен
вообще яработал давным давно с отладчиками и как помню стек раскручивается от текущего адреса т.е. IP
так что остаются только трюки с процессором, но мне не дадут
Здравствуйте, The Passenger, Вы писали:
TP>Здравствуйте, Zhendos, Вы писали:
Z>>backtrace явно есть несмотря на прыжок по нулевому адресу.
TP>Подозреваю что сдампить начало потока и последний вызов по нудевому адресу оно могет, а вот восстановить стек неа TP>причем все это еще не совсем стабильно
TP>например, я сделал несколько вложенных функций с багом в конечной, и если я например сделаю банальный access violation :
TP>а если с segfault ip 0 то такойЖ
И то и то segfault, один и тот же доступ к странице паямти начинающейся с нуля.
"access violation" это же вообще про Wwindows OS.
А компилировали без оптимизации? Современные компиляторы
используя знание о том что нулевые указатели для чтения и выполнения кода
использоваться не могут, вполне способны увидев такой код пометить его
как "unreachable" и переколбасить все так, что мать родная не узнает прочитав ассебмлер,
что это был ваш код.
Здравствуйте, Zhendos, Вы писали:
Z>И то и то segfault, один и тот же доступ к странице паямти начинающейся с нуля. Z>"access violation" это же вообще про Wwindows OS.
дада не спорю
Z>А компилировали без оптимизации? Современные компиляторы
без ... только флаг -g3
Z>используя знание о том что нулевые указатели для чтения и выполнения кода Z>использоваться не могут, вполне способны увидев такой код пометить его Z>как "unreachable" и переколбасить все так, что мать родная не узнает прочитав ассебмлер, Z>что это был ваш код.
это я в курсе
gdb ловит вот так ( я там еще поток добавил, но сути не меняет ):
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000000000040739b in func1 () at /home/320089804/Desktop/work/testPE/test.cpp:80
#2 0x00000000004073a6 in func2 () at /home/320089804/Desktop/work/testPE/test.cpp:85
#3 0x00000000004073b1 in func3 () at /home/320089804/Desktop/work/testPE/test.cpp:90
#4 0x00000000004073bc in func4 () at /home/320089804/Desktop/work/testPE/test.cpp:95
#5 0x000000000040871d in std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x60c040) at /usr/include/c++/4.8.2/functional:1732
#6 0x0000000000408677 in std::_Bind_simple<void (*())()>::operator()() (this=0x60c040) at /usr/include/c++/4.8.2/functional:1720
#7 0x0000000000408610 in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (this=0x60c028) at /usr/include/c++/4.8.2/thread:115
#8 0x00007ffff7b89070 in ?? () from /lib64/libstdc++.so.6
#9 0x00007ffff73a7ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007ffff70d08cd in clone () from /lib64/libc.so.6
TP>когда падает с segfault и указатель на инструкцию (IP) равен нулю — возможно ли вообще как-то раскрутить стэк в обработчике или дампе, или это в принципе невозможно?
Если instruction pointer левый то дебаггер не может получить FPO information из дебаг инфы и соответственно не сможеть раскрутить фреймы функций которые собраны с frame pointer omission. Но, возможно, попытается, используя каки нить хевристики.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
TP>>когда падает с segfault и указатель на инструкцию (IP) равен нулю — возможно ли вообще как-то раскрутить стэк в обработчике или дампе, или это в принципе невозможно? O>Если instruction pointer левый то дебаггер не может получить FPO information из дебаг инфы и соответственно не сможеть раскрутить фреймы функций которые собраны с frame pointer omission. Но, возможно, попытается, используя каки нить хевристики.
есть вариант попробовать: сдампить стек и по нему искать адреса возврата, наука конечно не точная, но вдруг попадется что-то
O>>Если instruction pointer левый то дебаггер не может получить FPO information из дебаг инфы и соответственно не сможеть раскрутить фреймы функций которые собраны с frame pointer omission. Но, возможно, попытается, используя каки нить хевристики. TP>есть вариант попробовать: сдампить стек и по нему искать адреса возврата, наука конечно не точная, но вдруг попадется что-то
да, я так часто делаю
Ищешь на стеке совпадения в image range каких нить модулей, смотришь в асм — есть ли там коллы. В принципе это несложно даже автоматизировать на стороне дампяшегося процесса.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, The Passenger, Вы писали:
TP>когда падает с segfault и указатель на инструкцию (IP) равен нулю — возможно ли вообще как-то раскрутить стэк в обработчике или дампе, или это в принципе невозможно? TP>или извлечь хоть какую-то полезную инфу?
void (*foo)(void);
int main (void)
{
foo();
return 0;
}
$ gcc -g ./test.c
$ ./a.out
Segmentation fault (core dumped)
$ gdb a.out core.1337599
Copyright (C) 2020 Free Software Foundation, Inc.
. . .
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000000000 in ?? ()
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.32-4.fc33.x86_64
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x0000000000401113 in main () at ./test.c:5
(gdb)
TP>по идее это невозможно, но другой стороны gdb это както делает когда ловит segfault
Ну адрес возврата-то в стеке есть на момент прихода SIGSEGV.
TP>хотя наверно он какойто флажок на процессоре ставит во время дебага