Этот расчет:
dynamic = start + phdr->p_vaddr;
верно только для образов ELF, связанных по адресу 0, что типично для разделяемых библиотек и независимых от позиции исполняемых файлов, но не требуется.
Я предполагаю, что у вас есть общие библиотеки, которые были предварительно связаны с адресом, отличным от 0.
Эта библиотека не была предварительно связана:
readelf -Wl foo.so | egrep 'LOAD|DYNAMIC'
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000684 0x000684 R E 0x200000
LOAD 0x000e40 0x0000000000200e40 0x0000000000200e40 0x0001e0 0x0001e8 RW 0x200000
DYNAMIC 0x000e50 0x0000000000200e50 0x0000000000200e50 0x000190 0x000190 RW 0x8
Та же библиотека после prelink -r 0x120000 foo.so
:
readelf -Wl foo.so | egrep 'LOAD|DYNAMIC'
LOAD 0x000000 0x0000000012000000 0x0000000012000000 0x000684 0x000684 R E 0x200000
LOAD 0x000e40 0x0000000012200e40 0x0000000012200e40 0x0001e0 0x0001e8 RW 0x200000
DYNAMIC 0x000e50 0x0000000012200e50 0x0000000012200e50 0x000190 0x000190 RW 0x8
Если предварительно связанная библиотека загружается в ваше приложение по адресу, указанному по адресу (start==0x12200000
), вы получите dynamic == 0x12200e50+0x12200000
, что, очевидно, является поддельным.
Чтобы учесть это, вам необходимо:
dynamic = start + phdr->p_vaddr - first_pt_load->p_vaddr;
, где first_pt_load
- самый низкий сегмент PT_LOAD
(который будет иметь .p_vaddr == 0
для библиотеки без предварительной ссылки и 0x12000000
для библиотеки с предварительной ссылкой).