динамическом разделе значения типа d_ptr, которые хранятся как относительные адреса на диске, преобразуются в абсолютные адреса, определяемые загрузчиком.
Глядя на исходный код glibc, ответственный за это код:
Код: Выделить всё
// file: sysdeps/generic/ldsodefs.h
/* Return true if dynamic section in the shared library L should be
relocated. */
static inline bool
dl_relocate_ld (const struct link_map *l)
{
/* Don't relocate dynamic section if it is readonly */
return !(l->l_ld_readonly || DL_RO_DYN_SECTION);
}
Код: Выделить всё
// file: elf/get-dynamic-info.h
/* Don't adjust .dynamic unnecessarily. */
if (l->l_addr != 0 && dl_relocate_ld (l))
{
ElfW(Addr) l_addr = l->l_addr;
# define ADJUST_DYN_INFO(tag) \
do \
{ \
if (info[tag] != NULL) \
info[tag]->d_un.d_ptr += l_addr; \
} \
while (0)
ADJUST_DYN_INFO (DT_HASH);
ADJUST_DYN_INFO (DT_PLTGOT);
ADJUST_DYN_INFO (DT_STRTAB);
ADJUST_DYN_INFO (DT_SYMTAB);
ADJUST_DYN_INFO (DT_RELR);
ADJUST_DYN_INFO (DT_JMPREL);
ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
# undef ADJUST_DYN_INFO
/* DT_RELA/DT_REL are mandatory. But they may have zero value if
there is DT_RELR. Don't relocate them if they are zero. */
# define ADJUST_DYN_INFO(tag) \
do \
if (info[tag] != NULL && info[tag]->d_un.d_ptr != 0) \
info[tag]->d_un.d_ptr += l_addr; \
while (0)
...
}
Мой вопрос: зачем вообще нужны эти перемещения? Для сравнения с другой реализацией: rtld FreeBSD не делает этого, независимо от того, доступен ли динамический раздел для записи или нет.
Для проверки я изменил динамический сегмент моей общей библиотеки на readonly с помощью шестнадцатеричного редактора, и библиотека вела себя нормально. Динамический раздел в памяти был идентичен тому, что был на диске.
Мое предположение: возможно, это сделано для облегчения отладки дампов ядра.
Подробнее здесь: https://stackoverflow.com/questions/791 ... elocations
Мобильная версия