Файл ядра отладки без символов - PullRequest
15 голосов
/ 26 июня 2009

У меня есть приложение C, которое мы развернули на сайте клиентов. Он был скомпилирован и работает на HP-UX. Пользователь сообщил о сбое, и мы получили дамп ядра. До сих пор я не смог повторить аварию в доме.

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

(gdb) bt
#0  0xc0199470 in ?? ()

Я могу создать «ядро строк» ​​для файла, но, насколько я понимаю, все, что я получаю, - это все строки в исполняемом файле, поэтому кажется, что там почти невозможно отследить что-либо.

У меня есть отладочная версия (скомпилированная с -g) исполняемого файла, которая, к сожалению, на пару месяцев новее выпущенной версии. Если я пытаюсь запустить GDB с этим концентратором, я вижу это:

warning: exec file is newer than core file.
Core was generated by `program_name'.
Program terminated with signal 11, Segmentation fault.
__dld_list is not valid according to __dld_flags.

#0  0xc0199470 in ?? ()
(gdb) bt
#0  0xc0199470 in ?? ()

Хотя было бы целесообразно скомпилировать отладочную версию и развернуть ее на сайте клиента, а затем дождаться следующего сбоя, это будет относительно сложно и нежелательно по ряду причин.

Я достаточно хорошо знаком с кодом и относительно неплохо представляю, где в коде происходит сбой, основываясь на отчете об ошибке клиента.

Есть ли ЛЮБОЙ способ узнать больше информации из этого дампа памяти? Через строки или другой отладчик или что-нибудь? Спасибо.

Ответы [ 8 ]

9 голосов
/ 26 июня 2009

Этот тип ответа от GDB:

(gdb) bt
#0  0xc0199470 in ?? ()

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

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

6 голосов
/ 26 июня 2009

На будущее:

  1. Убедитесь, что вы всегда строите с внешней базой символов (это не отладочная сборка - это сборка выпуска, но вы храните таблицу символов отдельно)
  2. сохраняйте это для версий, которые вы развернули

Для этой ситуации:

Вы знаете общую область, поэтому, чтобы убедиться, что вы правы, перейдите к трассировке стека и найдите код сборки - посмотрите на него и посмотрите, считаете ли вы, что он соответствует вашему источнику (это проще, если вы знаете, что источник сгенерировал эту сборку). Если все выглядит правильно, то у вас есть некоторая проверка вашей гипотезы. Возможно, вам удастся выяснить значения локальных переменных, посмотрев на стек (поскольку вы знаете, что передали и объявили).

3 голосов
/ 27 июня 2009

В gdb «информационные регистры» должны дать вам достаточно состояния выполнения во время сбоя, чтобы использовать его при разборке исполняемого файла и соответствующих общих библиотек. Я обычно использую objdump для дизассемблирования, перенаправления вывода в файл, а затем поднимаю файл в моем любимом редакторе - это полезно для хранения заметок, когда все выясняется. Также "info target" и "info sharedlib" в gdb могут быть полезны для определения места загрузки разделяемых библиотек.

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

Вы также можете сопоставить разборку новой версии, созданной с -g, с разборкой раздетой версии.

2 голосов
/ 26 июня 2009
  1. Всегда использовать контроль исходного кода (CVS / GIT / Subversion / и т. Д.), Даже для тестовых выпусков
  2. Метка все релизы
  3. Рассмотрите (в будущем) создание сборки с отладкой (-g) и удалите исполняемый файл перед отправкой. ПРИМЕЧАНИЕ: не делайте две сборки с -g и без; они могут не совпадать, так как -g может иногда вызывать генерацию другого кода даже на одном и том же уровне оптимизации. В критически важном для производительности коде вы можете отказаться от -g для критических файлов - в большинстве случаев это ничего не изменит.
  4. Если вы действительно застряли, сбросьте стопку и сбросьте соответствующие части кучи в гекс и посмотрите на нее вручную; возможно, взять инструментальную копию и найти похожие «подписи» в сгенерированном коде и в стеке. Это реальная отладка "старой школы" ...: -)
1 голос
/ 27 июня 2009

Попробуйте запустить pmap для файла ядра (если у hp / ux есть этот инструмент). Это должно сообщить начальные адреса всех модулей в файле ядра. С помощью этой информации вы сможете взять адрес места сбоя и выяснить, какая библиотека потерпела крах. Дальнейшее сравнение адресов между адресом сбоя и адресами известных функций в библиотеке («nm» по отношению к библиотеке должен получить это) может помочь вам определить, какая функция вылетела.

Даже если вам удастся идентифицировать функцию на вершине стека, маловероятно, что эта функция является источником проблемы ... надеюсь, она действительно потерпела крах в вашем коде, а не, скажем, стандартная библиотека строк C Перестройка трассировки стека - следующая лучшая вещь на этом этапе.

1 голос
/ 26 июня 2009

Есть ли у вас источник точный , который вы использовали для компиляции старой версии (например, через тег в дереве исходного кода или что-то в этом роде)? Может быть, вы могли бы восстановить, используя это, и, возможно, получить представление о том, где произошел сбой?

0 голосов
/ 27 июня 2009

Я не думаю, что файл ядра должен содержать символы. Вам нужно иметь возможность создать версию вашей программы, которая будет точно такой же , что и та, что вы отправили своему клиенту, но с -g. Если вы удалите исполняемый файл отладки, он должен быть идентичен поставленной версии. Только тогда GDB может дать вам что-нибудь полезное.

0 голосов
/ 26 июня 2009

Здесь не так много информации. Двоичный файл удален. Но, глядя на ошибку сегментации ... вы должны искать места, где есть вероятность, что вы перезаписываете часть памяти.

Это всего лишь предложение. Там может быть много проблем.

Кстати, если вы не можете воспроизвести на своем локальном компьютере, то объем данных о клиентах может быть проблемой.

...