Почему существует такая разница в способе сопоставления адресов для основного исполняемого файла и общих объектов?
Общие библиотеки обычно связаны по адресу 0 и перемещаются. Непозиционный исполняемый файл обычно связан по адресу 0x400000 по x86_64
Linux и должен не быть перемещен (или не будет работать).
Чтобы узнать, где данный Двоичный файл ELF связан, посмотрите на p_vaddr
адрес первого сегмента PT_LOAD
(readelf -Wl foo
покажет вам это). Кроме того, можно перемещать только двоичные файлы ET_DYN
ELF, в то время как двоичные файлы ET_EXEC
не должны быть.
Обратите внимание, что существуют независимые от позиции исполняемые файлы, и для них необходимо выполнить вычитание.
Обратите внимание, что совместно используемые библиотеки обычно связаны по адресу 0 (и поэтому вычитание работает), но они не должны . Выполнение prelink
в общей библиотеке приведет к тому, что общая библиотека будет связана по адресу, отличному от 0, и тогда вычитаемое вами значение не будет работать либо .
Действительно, что вам нужно do вычитает адрес загрузки во время выполнения из связанного адреса, чтобы получить перемещение (которое будет 0 для не-P IE исполняемых файлов и не 0 для разделяемых библиотек), а затем вычитать это перемещение из счетчика программы, записанного backtrace
для получения значения символа.
Наконец, если вы перебираете все загруженные изображения ELF с dl_iterate_phdr , dlpi_addr
обеспечивает точно перемещение что вам нужно вычесть.