Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
1

проблемы с созданием "правильного" core dump'а

01.01.2012, 13:42. Показов 3395. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Суть проблемы
При попытке создать с помощью gdb дамп памяти программы, которая в этот момент выполняет системный вызов, я получаю весьма бесполезный core, в котором, насколько я понимаю, не содержится информации, относящейся к моей программе, а содержится лишь часть, относящаяся к системному вызову.

Не по теме:

Вообще, я в матчасти не очень силен и, возможно, порю несусветную чушь. Потому ниже привожу подробное описание того, что я делаю, что я получаю и чем я не доволен.


подробное описание под катом

Берем простенькую программку, которая будет засыпать после выполнения system("sleep 1000").
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <cstdlib>
using namespace std;
 
void func1(int a) {
  cout << getpid() << endl;
  system("sleep 1000");
  cout << a << endl;
}
 
void func2(int a) {
  func1(a - 1);
}
 
void func3(int a) {
  func2(a - 1);
}
 
int main() {
  func3(3);
}
компилируем, запускаем, открываем в отладчике, печатаем стек вызовов, сохраняем дамп, выходим:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ g++ test.cc -g -o test
$ ./test &
[2] 11466
$ gdb -q test 11466
Reading symbols from /home/yekka/myspace/test...done.
Attaching to program: /home/yekka/myspace/test, process 11466
Reading symbols from /usr/lib/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...Reading symbols from /usr/lib/debug/lib/libm-2.11.1.so...done.
done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.1.so...done.
done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.1.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ff9b6d20f7e in __libc_waitpid (pid=<value optimized out>, 
    stat_loc=0x7fff315299ac, options=<value optimized out>)
    at ../sysdeps/unix/sysv/linux/waitpid.c:32
32  ../sysdeps/unix/sysv/linux/waitpid.c: Нет такого файла или каталога.
    in ../sysdeps/unix/sysv/linux/waitpid.c
(gdb) where
#0  0x00007ff9b6d20f7e in __libc_waitpid (pid=<value optimized out>, 
    stat_loc=0x7fff315299ac, options=<value optimized out>)
    at ../sysdeps/unix/sysv/linux/waitpid.c:32
#1  0x00007ff9b6cb87e9 in do_system (line=<value optimized out>)
    at ../sysdeps/posix/system.c:149
#2  0x00000000004008b9 in func1 (a=1) at test.cc:6
#3  0x00000000004008ef in func2 (a=2) at test.cc:11
#4  0x0000000000400909 in func3 (a=3) at test.cc:15
#5  0x0000000000400919 in main () at test.cc:19
(gdb) gcore core.test
Saved corefile core.test
(gdb) detach
Detaching from program: /home/yekka/myspace/test, process 11466
(gdb) quit
Что мы видим? Мы видим красноречивый стек, к которому у меня нет никаких претензий.
Теперь откроем сохраненный дамп и поглядим еще раз.
Bash
1
2
3
4
5
6
7
8
9
10
11
$ gdb -q test core.test
Reading symbols from /home/yekka/myspace/test...done.
[New Thread 11466]
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.1.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `/home/yekka/myspace/test'.
#0  0x00007ff9b6d20f7e in ?? ()
(gdb) where
#0  0x00007ff9b6d20f7e in ?? ()
#1  0x0000000000000000 in ?? ()
От былой красноречивости не осталось и следа. Стек сократился до двух безымянных функций, одну из которых, сравнивая адреса с предыдущим бектрейсом, можно идентифицировать как __libc_waitpid at ../sysdeps/unix/sysv/linux/waitpid.c:32, а второй адрес вообще NULL.
Толку от такого дампа я не вижу и меня это огорчает.


Вопросы
  1. Почему, когда я в описанном выше случае создаю дамп, а потом снова открываю его в отладчике, то теряется информация о функциях и переменных, относящихся к моей программе?
  2. Как можно в описанном выше случае сохранить дамп памяти, с которым после этого можно будет работать?

PostScriptum
Если в приведенной выше программе модифицировать func1 (убрать системный вызов):
C++
1
2
3
4
5
void func1(int a) {
  cout << getpid() << endl;
  while(1);
  cout << a << endl;
}
то тогда, выполняя аналогичную последовательность действий, я получаю дамп, который при повторной загрузке в отладчик дает полную информацию о состоянии программы, стеке вызовов и переменных
1
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.01.2012, 13:42
Ответы с готовыми решениями:

Проблемы с созданием объектов
Описан класс TPlanet: TPlanet = class (TObject) public name: string; ...

Проблемы с созданием объекта
Есть два класса public class Tname { public string name_eng; public...

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

Проблемы с созданием RAID-5
Всем привет! У меня есть 5 дисков по терабайту, и я пытаюсь создать из них RAID-5 массив...

8
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.01.2012, 14:32 2
Лучший ответ Сообщение было отмечено как решение

Решение

Для порядку ещё сделай оригинальную (общую) постановку задачи. Что конкретно ты хочешь сделать?

Добавлено через 7 минут
Сделел немного на своём примере, но приниципальной сути не изменилось. После загрузки коры получил почти нормальный стек:

Код
(gdb) bt
#0  0x00db7422 in __kernel_vsyscall ()
#1  0x008e1cc0 in ?? ()
#2  0x008e1b10 in ?? ()
#3  0xbfa9b284 in ?? ()
#4  0x080483f5 in func (x=100) at t.c:5
#5  0x0804840c in main () at t.c:10
Т.е. вопросительные знаки только на месте glibc'шных функций, которые притащились из динамических библиотек. Оригинальный стек был такой:

Код
(gdb) bt
#0  0x00db7422 in __kernel_vsyscall ()
#1  0x008e1cc0 in nanosleep () from /lib/tls/i686/cmov/libc.so.6
#2  0x008e1b10 in sleep () from /lib/tls/i686/cmov/libc.so.6
#3  0x080483f5 in func (x=100) at t.c:5
#4  0x0804840c in main () at t.c:10
Добавлено через 11 минут
Вопросительные знаки на месте функций из динамических библиотек - это нормальное явление и вот почему.

1. Если запустить программу непосредственно из gdb, то gdb умеет перехватывать ситуации загрузки динамической библиотеки в память в момент запуска отлаживаемого приложения. И поэтому при печати стека gdb знает, какие адреса, соответствующие динамическим библиотекам, к какой конкретно библиотеке относятся (и из этого уже может вычислить конкретную функцию динамической библиотеки).

2. Если gdb приаттачивается к запущенному процессу, то я не знаю, откуда он выцепляет информацию о загруженных динамических библиотеках, но технически я в этом проблем не вижу: в каталоге /proc имеется некоторая дополнительная инфа о работающем процессе, из которой в совокупности с данными динамического загрузчика что-то и как-то можно расковырять.

3. Когда gdb поднимает файл core, то информацию взять уже неоткуда. Файл core содержит лишь образ памяти, занимаемый отлаживаемым процессом. А вся (или частично) информация про динамические библиотки берётся извне по отношению к отлаживаемому процессу: в пункте 1 это делается непосредственно через специальный hook (реализованый в ld.so именно для работы отладчика), в пункте 2 это делается на основании информации из /proc плюс какие-то специальные данные в ld.so (тоже сделанные для работы отладчика), но данные в /proc имеются только в том случае, если процесс жив. Когда процесса уже нет в живых, то эти данные уже утеряны. В итоге в core содержится только образ памяти, в котором нет информации о том, где какая динамическая библиотека. Информация же о самом бинарнике берётся из файла бинарника (т.к. core исследуется не самостоятельно, а в контексте бинарника, который параллельно с core'ой подаётся в отладчик)
3
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
01.01.2012, 14:37  [ТС] 3
Цитата Сообщение от Evg Посмотреть сообщение
Для порядку ещё сделай оригинальную (общую) постановку задачи. Что конкретно ты хочешь сделать?
озадачился я этими изысканиями по мотивам твоей темы Встроенная в программу печать стека при помощи внешнего отладчика (спасибо за весьма любопытную статью, кстати).
Идея в том, чтобы помимо распечатки стека бектрейсом еще и автоматически создавать core dump, который дальше можно было бы при необходимости использовать для более детального анализа. (В обсуждении к вышеупомянутой теме я описывал возникшую у меня проблему, но тот пост остался не замечен)
Поскольку там основная программа на время работы внешнего отладчика также приостанавливается системным вызовом wait, я тоже получаю неинформативный дамп.
0
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.01.2012, 14:46 4
Повторил с точностью до буквы твой вариант - увидел такую же засаду как и у тебя. Странно. Надо думать

Добавлено через 3 минуты
Если в твоём коде заменить

C
1
system("sleep 1000");
на

C
1
sleep (1000);
то всё будет нормально. system работает через fork-exec. Теоретически я не понимаю, почему вызов sysytem привёл к таким последствиям, но в данном случае проблема именно в нём

Добавлено через 2 минуты
Цитата Сообщение от yekka Посмотреть сообщение
В обсуждении к вышеупомянутой теме я описывал возникшую у меня проблему, но тот пост остался не замечен
Это такая проблема настройки форумного движка. Твой второй пост просто склеился с первым и такие вещи зачастую оказываются незамеченными в случаях, когда в этот момент другие перечитывают страницу форума
0
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
01.01.2012, 14:52  [ТС] 5
Цитата Сообщение от Evg Посмотреть сообщение
Если в твоём коде заменить
system("sleep 1000");
на
sleep (1000);
то всё будет нормально.
но вот чем заменить fork-wait при автоматическом вызове внешнего отладчика?
0
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.01.2012, 16:44 6
Цитата Сообщение от yekka Посмотреть сообщение
В обсуждении к вышеупомянутой теме я описывал возникшую у меня проблему, но тот пост остался не замечен
У меня стек нарисовался такой:

Код
(gdb) bt
#0  0x005bf422 in __kernel_vsyscall ()
#1  0x006e572d in ?? ()
#2  0x004ac3c0 in ?? () from /lib/ld-linux.so.2
#3  0x08048a61 in gdb_PrintStackGDB () at t.c:67
Backtrace stopped: frame did not save the PC
Из последней строки следует, что как-то некорректно в core лежит состояние стека (т.к. в нём отсутствует связующая информация о вызовах). Идей по этому поводу никаких нет

Добавлено через 8 минут
Этот же пример на sparc-linux отрабатывает корректно:

Код
(gdb) core core.from.gdb
Reading symbols from /usr/lib/libstdc++.so.6...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `/home/<user>/a.out'.
[New process 20095]
#0  0xf7cbcf04 in wait () from /lib/libc.so.6
(gdb) bt
#0  0xf7cbcf04 in wait () from /lib/libc.so.6
#1  0x00010be8 in gdb_PrintStackGDB () at t.c:67
#2  0x00010e0c in func1 (x=0xffb7d8cc) at t.c:95
#3  0x00010e54 in func2 (j=Cannot access memory at address 0x7
) at t.c:102
#4  0x00010eb0 in main (argc=1, argv=0xffb7d9d4) at t.c:117
Понимание того, как это работает на sparc и очень слабое знание i386 (но примерное понимание общего принципа работы в данном месте) в совокупности, к сожалению, НЕ даёт мне понять, какая же засада случилась со связующей информацией

Добавлено через 3 минуты
Есть некое предположение того, что gdb в случае i386 скинул образ памяти не основного процесса, а того, что получился после fork'а (т.е. ошибка gdb). Но как экспериментально подтвердить или опровергнуть - не знаю

Добавлено через 13 минут
В случае с i386 пока нашёл лекарство-затычку. Если линковать статически, то после поднятия core стек рисуется нормальный
1
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
22.01.2012, 18:56  [ТС] 7
проблема чудесным образом разрешилась при апгрейде компилятора (gcc) с версии 4.4.3 до версии 4.6.2
0
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.01.2012, 19:05 8
Странно...
0
Evg
Эксперт CАвтор FAQ
21280 / 8302 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
02.10.2012, 15:14 9
Для истории: https://www.cyberforum.ru/faq/... ost3506089
Т.е. проблема скорее всего была в том, что динамическая glibc собрана с дополнительной опцией -fomit-frame-pointer (или что-то типа того), а потому становится невозможна полноценная работа размотки стека. А статическая библиотека собрана без этой опции
0
02.10.2012, 15:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.10.2012, 15:14
Помогаю со студенческими работами здесь

Проблемы с созданием вектора
#include &lt;iostream&gt; #include &lt;vector&gt; using namespace std; int main(){ vector &lt;int&gt; a =...

Проблемы с созданием словаря на C++
Ребята-программисты, нужна срочная помощь, выдаёт такие ошибки: E0291 для класса &quot;Term&quot; не...

Проблемы с созданием сервиса
Добрый день Создаю сервисную службу вот так http://habrahabr.ru/post/102826/. Но потом не вижу...

Проблемы с созданием процедуры
Есть условие:Создать хранимую процедуру, которая выводит количество сделанных деталей заданного...

Проблемы с созданием процедуры
Здравствуйте, имеется такой скрипт хранимой процедуры для MSSQL(упрощенный пример, на самом деле,...

Проблемы с созданием формы
Здравствуйте, вот попытался создать свою первую форму, все получилось, но в WNDCLASSEX есть еще 1...

Проблемы с созданием класса
class Source { Source(String login,String password,String other) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru