Отладить основной файл без символов

У меня есть приложение 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 ?? ()

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

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

Есть ли какой-либо способ получить больше информации из этого основного дампа? Через строки или другой отладчик или что-нибудь еще? Спасибо.

Ответы

Ответ 1

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

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

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

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

Ответ 2

В будущем:

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

В этой ситуации:

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Это просто предложение. Проблем может быть много.

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

Ответ 8

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