387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450

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

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

Студворк — интернет-сервис помощи студентам
Суть проблемы
При попытке создать с помощью 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)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.01.2012, 13:42
Ответы с готовыми решениями:

Проблемы с созданием объектов
Описан класс TPlanet: TPlanet = class (TObject) public name: string; x,y,m,r,px,py,vx,vy,ax,ay: real; u,v,up,vp:integer; ...

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

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

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

Решение

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

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

Code
1
2
3
4
5
6
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'шных функций, которые притащились из динамических библиотек. Оригинальный стек был такой:

Code
1
2
3
4
5
6
(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  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Для порядку ещё сделай оригинальную (общую) постановку задачи. Что конкретно ты хочешь сделать?
озадачился я этими изысканиями по мотивам твоей темы Встроенная в программу печать стека при помощи внешнего отладчика (спасибо за весьма любопытную статью, кстати).
Идея в том, чтобы помимо распечатки стека бектрейсом еще и автоматически создавать core dump, который дальше можно было бы при необходимости использовать для более детального анализа. (В обсуждении к вышеупомянутой теме я описывал возникшую у меня проблему, но тот пост остался не замечен)
Поскольку там основная программа на время работы внешнего отладчика также приостанавливается системным вызовом wait, я тоже получаю неинформативный дамп.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.01.2012, 14:46
Повторил с точностью до буквы твой вариант - увидел такую же засаду как и у тебя. Странно. Надо думать

Добавлено через 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  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Если в твоём коде заменить
system("sleep 1000");
на
sleep (1000);
то всё будет нормально.
но вот чем заменить fork-wait при автоматическом вызове внешнего отладчика?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.01.2012, 16:44
Цитата Сообщение от yekka Посмотреть сообщение
В обсуждении к вышеупомянутой теме я описывал возникшую у меня проблему, но тот пост остался не замечен
У меня стек нарисовался такой:

Code
1
2
3
4
5
6
(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 отрабатывает корректно:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(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  [ТС]
проблема чудесным образом разрешилась при апгрейде компилятора (gcc) с версии 4.4.3 до версии 4.6.2
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.01.2012, 19:05
Странно...
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
02.10.2012, 15:14
Для истории: https://www.cyberforum.ru/faq/... ost3506089
Т.е. проблема скорее всего была в том, что динамическая glibc собрана с дополнительной опцией -fomit-frame-pointer (или что-то типа того), а потому становится невозможна полноценная работа размотки стека. А статическая библиотека собрана без этой опции
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.10.2012, 15:14
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

Новые блоги и статьи
Непрерывная интеграция для пакета Python
Mr. Docker 22.06.2025
Было 4 часа утра пятницы, когда я выпустил новую версию нашей внутренней библиотеки для обработки данных. Релиз 0. 5. 2 содержал небольшой фикс для обработки дат в ISO формате, что может пойти не так?. . .
Продвинутый ETL на C# из OLTP БД в хранилище
stackOverflow 22.06.2025
Работая в сфере корпоративной аналитики, я постоянно сталкиваюсь с одним и тем же - нужны чистые, структурированные и, главное, свежие данные. Без них современные аналитические системы, машинное. . .
Мастер-класс по микросервисам на Node.js
Reangularity 21.06.2025
Node. js стал одной из самых популярных платформ для микросервисной архитектуры не случайно. Его неблокирующая однопоточная модель и событийно-ориентированный подход делают его идеальным для. . .
Управление Arduino из WPF приложения
Wired 21.06.2025
Зачем вообще связывать Arduino с WPF-приложением? Казалось бы, у Arduino есть собственная среда разработки, своя экосистема, свои способы управления. Однако при создании серьезных проектов. . .
Звёздная пыль
kumehtar 20.06.2025
Я просто это себе представляю: как создавался этот мир. Как энергия слипалась в маленькие частички. Как они собирались в первые звёзды, как во вселенной впервые появился Свет. Как эти звёзды. . .
Создание нейросети с PyTorch
AI_Generated 19.06.2025
Ключевое преимущество PyTorch — его питоновская натура. В отличие от TensorFlow, который изначально был построен как статический вычислительный граф, PyTorch предлагает динамический подход. Это. . .
JWT аутентификация в ASP.NET Core
UnmanagedCoder 18.06.2025
Разрабатывая веб-приложения, я постоянно сталкиваюсь с дилеммой: как обеспечить надежную аутентификацию пользователей без ущерба для производительности и масштабируемости? Классические подходы на. . .
Краткий курс по С#
aaLeXAA 18.06.2025
Здесь вы найдете все необходимые функции чтоб написать програму на C# Задание 1: КЛАСС FORM 1 public partial class Form1 : Form { Spisok listin = new Spisok(); . . .
50 самых полезных примеров кода Python для частых задач
py-thonny 17.06.2025
Эффективность работы разработчика часто измеряется не количеством написаных строк, а скоростью решения задач. Готовые сниппеты значительно ускоряют разработку, помогают избежать типичных ошибок и. . .
C# и продвинутые приемы работы с БД
stackOverflow 17.06.2025
Каждый . NET разработчик рано или поздно сталкивается с ситуацией, когда привычные методы работы с базами данных превращаются в источник бессонных ночей. Я сам неоднократно попадал в такие ситуации,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru