Подавить символ ld не найдена ошибка для устранения позже во время выполнения - PullRequest
3 голосов
/ 30 сентября 2019

У меня есть следующая библиотека:

shared4.c:

int get_another_int(void){
    return 10;
}

И двоичный файл:

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int get_another_int(void);

int main(void){
    void *handle = dlopen("/home/me/c/build/libshar4.so", RTLD_GLOBAL | RTLD_NOW);
    if(!handle){
        exit(EXIT_FAILURE);
    }
    printf("handle = %p\n", handle);
    printf("another_int = %d\n", get_another_int());
}

Я не связывал двоичный файл с библиотекойи добавлена ​​опция ld, чтобы игнорировать ошибку "символ не найден":

-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all

При таких параметрах двоичный файл скомпилирован и связан с "fine".

Раздел plt выглядит следующим образом:

$ objdump -d -j .plt ./build/bin_shared 

./build/bin_shared:     file format elf64-x86-64


Disassembly of section .plt:

00000000000005e0 <.plt>:
 5e0:   ff 35 22 0a 20 00       pushq  0x200a22(%rip)        # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
 5e6:   ff 25 24 0a 20 00       jmpq   *0x200a24(%rip)        # 201010 <_GLOBAL_OFFSET_TABLE_+0x10>
 5ec:   0f 1f 40 00             nopl   0x0(%rax)
        ...

0000000000000600 <dlopen@plt>:
 600:   ff 25 1a 0a 20 00       jmpq   *0x200a1a(%rip)        # 201020 <dlopen@GLIBC_2.2.5>
 606:   68 00 00 00 00          pushq  $0x0
 60b:   e9 d0 ff ff ff          jmpq   5e0 <.plt>

0000000000000610 <__printf_chk@plt>:
 610:   ff 25 12 0a 20 00       jmpq   *0x200a12(%rip)        # 201028 <__printf_chk@GLIBC_2.3.4>
 616:   68 01 00 00 00          pushq  $0x1
 61b:   e9 c0 ff ff ff          jmpq   5e0 <.plt>

0000000000000620 <exit@plt>:
 620:   ff 25 0a 0a 20 00       jmpq   *0x200a0a(%rip)        # 201030 <exit@GLIBC_2.2.5>
 626:   68 02 00 00 00          pushq  $0x2
 62b:   e9 b0 ff ff ff          jmpq   5e0 <.plt>

Я изучил objdump и заметил следующий фрагмент main:

 66b:   e8 a0 ff ff ff          callq  610 <__printf_chk@plt>
 670:   e8 7b ff ff ff          callq  5f0 <.plt+0x10>

Но приложение не запустилось со следующей ошибкой:

$ ./build/bin_shared 
./build/bin_shared: error while loading shared libraries: unexpected PLT reloc type 0x00

Я посмотрел на все типы перемещения:

$ objdump -R ./build/bin_shared 

./build/bin_shared:     file format elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE 
0000000000200dd8 R_X86_64_RELATIVE  *ABS*+0x00000000000007a0
0000000000200de0 R_X86_64_RELATIVE  *ABS*+0x0000000000000760
0000000000201040 R_X86_64_RELATIVE  *ABS*+0x0000000000201040
0000000000200fd8 R_X86_64_GLOB_DAT  _ITM_deregisterTMCloneTable
0000000000200fe0 R_X86_64_GLOB_DAT  __libc_start_main@GLIBC_2.2.5
0000000000200fe8 R_X86_64_GLOB_DAT  __gmon_start__
0000000000200ff0 R_X86_64_GLOB_DAT  _ITM_registerTMCloneTable
0000000000200ff8 R_X86_64_GLOB_DAT  __cxa_finalize@GLIBC_2.2.5
0000000000201020 R_X86_64_JUMP_SLOT  dlopen@GLIBC_2.2.5
0000000000201028 R_X86_64_JUMP_SLOT  __printf_chk@GLIBC_2.3.4
0000000000201030 R_X86_64_JUMP_SLOT  exit@GLIBC_2.2.5
0000000000000000 R_X86_64_NONE     *ABS*                    //<---- This relocation

Есть ли способ обойти это и сделать символы из библиотеки, загруженной с dlopen, но не связанной с ldв течение времени ссылки, которое будет доступно для динамического компоновщика, поэтому приложение, которое я показал выше, будет работать как ожидалось?

1 Ответ

3 голосов
/ 01 октября 2019

Есть ли способ обойти это

Компоновщик должен знать, что символ будет поступать из какой-то общей библиотеки, и ему нужно знать, что kind символа это для того, чтобы правильно построить динамическую ссылку на символ для этого символа в главном исполняемом файле.

Поскольку вы не хотите (или не можете) предоставить libshar4.soво время соединения другой вариант - сделать вид, что что другая библиотека, с которой вы делаете ссылку, предоставляет этот символ.

Например, поскольку вы используете dlopenВы можете создать dlopen_stub.so, который предоставляет и dlopen , и get_another_int (фактическая реализация любой функции в заглушке может быть пустой), установите SONAME этой библиотеки заглушек наlibdl.so.2 (или что бы то ни было SONAME ваше реальное libdl.so использует), и свяжите ваш двоичный файл с этой заглушкой (вместо связи с -ldl).

Во время выполнения, при условии, что LD_BIND_NOW равно не в действительности, двоичный файл не будет пытаться разрешить get_another_int до тех пор, покаВы загрузили libshar4.so, и к тому времени символ будет доступен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...