Есть ли инструмент для изменения записей общей библиотеки в динамическом разделе двоичного файла ELF? Я хотел бы явно изменить зависимости общей библиотеки в моем двоичном файле (т.е. заменить путь к существующей библиотеке на собственный путь)
Инструмент для изменения динамической части бинарного файла ELF
Ответы (4)
заменить путь к существующей библиотеке на собственный путь
Если это ваша собственная библиотека, то вы, вероятно, связываете ее так:
$ cc -o prog1 -l/full/path/to/libABC.so prog1.o
вместо правильного:
$ cc -o prog1 -L/full/path/to/ -lABC prog1.o
Первый подход говорит компоновщику Linux, что приложению нужна именно эта библиотека, только эта библиотека и никакое переопределение не должно быть возможным. Второй подход говорит о том, что приложению нужна библиотека, которая будет установлена где-то в системе, либо по пути к библиотеке по умолчанию, либо по пути, указанному $LD_LIBRARY_PATH (будет искаться во время выполнения). -L используется только во время компоновки.
В противном случае вместо того, чтобы патчить ELF, сначала проверьте, можно ли подставить библиотеку с помощью симлинка. Это обычный трюк: потом трудно изменить исполняемый файл, но очень легко изменить, куда указывает символическая ссылка.
patchelf
это то, что вы хотите
$ patchelf --replace-needed LIB_ORIGIN LIB_NEW ELF_FILE
Чтобы увидеть эффект
$ readelf -d ELF_FILE
Установить инструменты легко:
$ sudo apt-get install patchelf readelf
Вы можете проверить переменную окружения LD_LIBRARY_PATH
.
Если вы посмотрите на раздел .dynsym в Linux через readelf
, вы увидите что-то вроде:
1: 0000000000000000 163 FUNC GLOBAL DEFAULT UND fseek@GLIBC_2.2.5 (2)
который просто содержит символическое имя библиотеки. Однако, если вы включите информацию о динамическом загрузчике, вы получите:
libc.so.6 => /lib/libc.so.6 (0x00002ba11da4a000)
/lib64/ld-linux-x86-64.so.2 (0x00002ba11d82a000)
Итак, как уже упоминалось, проще всего (при условии, что вы делаете это для отладки, а не навсегда) было бы просто создать новый сеанс, экспортировать свой собственный путь перед существующим LD_LIBRARY_PATH
и перейти оттуда.