Есть ли способ указать базовый адрес разделяемой библиотеки с помощью dlopen ()? - PullRequest
0 голосов
/ 28 мая 2020

Кажется, что когда мы dlopen () некоторые библиотеки, они будут загружены по некоторым предпочтительным (но не фиксированным) адресам. Я проверил исходный код dlopen (), и основная функция говорит:

static __always_inline const char *
_dl_map_segments (struct link_map *l, int fd,
                  const ElfW(Ehdr) *header, int type,
                  const struct loadcmd loadcmds[], size_t nloadcmds,
                  const size_t maplength, bool has_holes,
                  struct link_map *loader)
{
  const struct loadcmd *c = loadcmds;
  if (__glibc_likely (type == ET_DYN))
    {
      /* This is a position-independent shared object.  We can let the
         kernel map it anywhere it likes, but we must have space for all
         the segments in their specified positions relative to the first.
         So we map the first segment without MAP_FIXED, but with its
         extent increased to cover all the segments.  Then we remove
         access from excess portion, and there is known sufficient space
         there to remap from the later segments.
         As a refinement, sometimes we have an address that we would
         prefer to map such objects at; but this is only a preference,
         the OS can do whatever it likes. */
      ElfW(Addr) mappref
        = (ELF_PREFERRED_ADDRESS (loader, maplength,
                                  c->mapstart & GLRO(dl_use_load_bias))
           - MAP_BASE_ADDR (l));
      /* Remember which part of the address space this object uses.  */
      l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
                                            c->prot,
                                            MAP_COPY|MAP_FILE,
                                            fd, c->mapoff);
      if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
        return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
...
}

В комментарии говорится, что вы можете указать предпочтительный адрес, но ОС определит, использовать ли его.

Вопрос

  1. Можно ли каким-либо образом указать базовый адрес для каждого открытого модуля?
  2. ELF_PREFERRED_ADDRESSS по умолчанию установлено на 0, но этот макрос, похоже, предполагает, что предпочтительные адреса могут быть изменены, скажем, с помощью переменной среды? Но даже он есть, сомневаюсь, что его можно менять для каждой dlopened библиотеки.
  3. Если я хочу реализовать эту функцию самостоятельно, мне кажется, что мне нужно обернуть новую функцию dlopen и передать предпочтительный адрес указанной выше основной функции (и, возможно, использовать MAP_FIXED). Это правильно?

Спасибо!

1 Ответ

0 голосов
/ 01 июня 2020

Можно ли каким-либо образом указать базовый адрес для каждого открытого модуля?

Нет.

ELF_PREFERRED_ADDRESSS по умолчанию установлен в 0, но этот макрос, кажется, делает вывод, что предпочтительные адреса могут быть изменены, скажем, с помощью переменной среды? Но даже если он есть, я сомневаюсь, что его можно изменить для каждой dlopened библиотеки.

Этот код скомпилирован в динамический c загрузчик ld-linux.so и не может быть измененным после компиляции.

Если я хочу реализовать эту функцию самостоятельно, мне кажется, что мне нужно обернуть новую функцию dlopen и передать предпочтительный адрес указанной выше основной функции (и, возможно, использовать MAP_FIXED ). Это правильно?

Функция от приватная до ld-linux. Вы не сможете его обернуть или вызвать из-за пределов ld-linux.

PS То, что вы вероятно, ищете, это команду prelink .

...