Как мне сопоставить адрес указателя инструкции segfault из / var / log / messages с адресом / функцией в моем файле .map? - PullRequest
2 голосов
/ 11 сентября 2009

(Моя среда - 64-битная Ubuntu, мое приложение скомпилировано на C ++ и связано с g ++.)

Когда приложение выполняет что-то вроде деления на ноль или запускает asm("int $3"), оставленное в коде, одно из следующих событий регистрируется через syslog на /var/log/kern.log и /var/log/messages:

Sep 10 18:06:47 VM kernel: [117194.123452] a.out[20288] trap divide error ip:45c59d sp:7fff65a91810 error:0 in a.out[400000+144000]
Sep 10 18:07:10 VM kernel: [117217.020833] a.out[20294] trap int3 ip:45c493 sp:7fff5cc559f0 error:0

В обоих случаях адрес указателя инструкций указывает на то, что я легко могу найти в файле .map, созданном во время ссылки (с использованием "-Wl,-Map,output.map").

Но если я вызову ошибку сегмента, в данном случае вызовом memcpy() с источником, установленным в NULL, указатель инструкции находится вне диапазона, я понятия не имею, как он должен отображаться:

Sep 10 18:06:13 VM kernel: [117160.228587] a.out[20282]: segfault at 0 ip 00007f7e79209092 sp 00007fff831faf08 error 4 in libc-2.9.so[7f7e79185000+168000]

В этом примере я ожидал бы, что IP будет в диапазоне 0x445e70-0x445e7f, который является местоположением memcpy () согласно моему файлу .map.

Мой вопрос: в чем заключается хитрость при интерпретации ip в этом случае?

1 Ответ

3 голосов
/ 11 сентября 2009

В соответствии с сообщением, похоже, что он произошел сбой внутри memcpy(), начиная с libc-2.9.so, который отображается в вашем процессе, начиная с 0x7f7e79185000 Это ожидается, поскольку memcpy - это функция, которая пытается разыменовать указатель. Указатель инструкции выглядит допустимым, поскольку он находится в пределах диапазона libc. Если вы намеревались переопределить memcpy и вызвать свою собственную версию, вам может понадобиться скомпилировать с -fno-builtin-memcpy.

Редактировать: Возможно, вы статически связываете libc, но в соответствии с сообщением у вас также есть общая библиотека libc, отображенная в вашей памяти процесса. Вы должны увидеть его в /proc/ pid /maps во время работы вашей программы. Возможно, вы связываетесь с другой общей библиотекой, такой как libstdc ++, и это зависит от общей библиотеки libc. В результате у вас есть две версии memcpy, и в этом случае она вызывает версию разделяемой библиотеки libc, которая отображается по старому адресу. Если вам не нужна разделяемая библиотека libc, убедитесь, что вы статически связываете все библиотеки; используйте опцию -static в начале вашей линии связи.

...