2009-06-26 2 views
13

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

Как вы подозреваете, основной файл/развернутый исполняемый файл полностью лишен каких-либо символов. Когда я загрузить его в БГД и сделать 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 ??() 

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

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

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

ответ

7

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

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

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

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

+0

Этот ответ кажется мне смехотворным. Я обязательно просмотрю код для потенциально переполненных областей. – Morinar

+0

Если отладка с дубликатной копией ничего не показывает, пришло время начать смотреть на регистры и складывать стопки, чтобы попытаться сделать вывод, как вы вышли в середину нигде. Он также может быть выведенным (или неинициализированным) указателем на функцию, перераспределением распределения или, возможно, неправильным размером буфера или «плохим» вводом буфера (используя sprintf()/sscanf с неконтролируемым входом и т. Д.). – jesup

+0

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

1

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

+0

У меня есть точный источник, но этот конкретный фрагмент кода не сильно изменился (если вообще) с этого момента до того, что у меня есть сейчас. – Morinar

0

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

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

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

5

Для будущего:

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

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

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

+0

Как найти код сборки и/или получить трассировку стека? Вся трассировка стека, которую я видел до сих пор, вставил выше ... – Morinar

+0

Команда «разобрать» - см. Это http://www.unknownroad.com/rtfm/gdbtut/gdbadvanced.html –

+0

Я сделал это и получено: (gdb) дизассемблировать Функция не содержит счетчик программ для выбранного кадра. Который мне кажется, что это одобряет разбитый стек, предложенный Суфием ниже. – Morinar

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

Определенно солидный совет. Мы в значительной степени делаем шаги 1-3 здесь, но независимо от того, они обрабатываются совершенно другим набором людей (у нас есть команда, отвечающая за эти вещи здесь), чем я. – Morinar

3

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

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

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

1

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

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

0

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

Смежные вопросы