Buildroot交叉编译共享库通过dlopen()加载

问题描述 投票:0回答:1

我正在尝试通过 buildroot 交叉编译包。该包可以通过

dlopen
调用 .so 共享库的路径来调用自定义代码。但是,自定义代码需要来自调用 dlopen 的父可执行文件的符号。因此,共享库是通过包含
-I
指令到父可执行文件的源代码目录以及
-shared -fPIC
来构建的。

在 Debian 上,父可执行文件打开共享库,并根据

LD_DEBUG=all
通过搜索父可执行文件的路径找到符号并正确加载库。

在 buildroot 上,父可执行文件打开共享库,但在尝试从可执行文件本身动态链接符号时失败。根据

LD_DEBUG=all
,有一个
symbol lookup error: undefined symbol

在我的测试中,我发现 debian 二进制文件可以从 debian 和 buildroot 系统加载共享库,并在 debian 和 buildroot 系统上运行。因此,问题很可能在于两个父可执行文件之间的差异。

我已经比较了 readelf -a 输出(下面的头),并且没有看到 debian 和 buildroot 二进制文件之间有任何真正的区别。最值得注意的是,buildroot 库找不到的符号出现在两个二进制文件中(也在下面)

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x34a00
  Start of program headers:          64 (bytes into file)
  Start of section headers:          1933304 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

失败的符号:

  5964: 0000000000049714   288 FUNC    GLOBAL DEFAULT   13 plugin_hook_register

此外,我已经尝试/检查过:

  • 不剥离 buildroot 二进制文件
  • 使用 buildroot 使用的相同标志构建 debian 二进制文件
  • 更改可执行文件的 rpath
  • 在调用 rpath 挂钩之前使用 buildroot 中的可执行文件
  • 改变
    LD_LIBRARY_PATH
  • 比较ldd的差异(没有)

任何关于如何进一步检查二进制文件以确定为什么无法找到该符号的想法都非常感谢。

编辑:

nm -D
每个二进制的符号输出:

错误的二进制文件(GNU nm 2.40,完整输出)-->

                 U abort@GLIBC_2.17
                 U accept@GLIBC_2.17
                 U access@GLIBC_2.17
                 U arc4random@GLIBC_2.36
                 U atof@GLIBC_2.17
                 U atoi@GLIBC_2.17
                 U atol@GLIBC_2.17
                 U atoll@GLIBC_2.17
                 U backtrace@GLIBC_2.17
                 U backtrace_symbols@GLIBC_2.17
                 U bind@GLIBC_2.17
                 U calloc@GLIBC_2.17
                 U chdir@GLIBC_2.17
                 U chmod@GLIBC_2.17
                 U clearerr@GLIBC_2.17
                 U clock_gettime@GLIBC_2.17
                 U close@GLIBC_2.17
                 U closedir@GLIBC_2.17
                 U closelog@GLIBC_2.17
                 U connect@GLIBC_2.17
                 U __ctype_b_loc@GLIBC_2.17
                 U __ctype_tolower_loc@GLIBC_2.17
                 U __ctype_toupper_loc@GLIBC_2.17
                 w __cxa_finalize@GLIBC_2.17
                 U dlclose@GLIBC_2.34
                 U dlerror@GLIBC_2.34
                 U dlopen@GLIBC_2.34
                 U dlsym@GLIBC_2.34
                 U dup2@GLIBC_2.17
                 U epoll_create1@GLIBC_2.17
                 U epoll_ctl@GLIBC_2.17
                 U epoll_wait@GLIBC_2.17
                 U __errno_location@GLIBC_2.17
                 U eventfd@GLIBC_2.17
                 U exit@GLIBC_2.17
                 U fchmod@GLIBC_2.17
                 U fchown@GLIBC_2.17
                 U fclose@GLIBC_2.17
                 U fcntl64@GLIBC_2.28
                 U feof@GLIBC_2.17
                 U ferror@GLIBC_2.17
                 U fflush@GLIBC_2.17
                 U fgets@GLIBC_2.17
                 U fileno@GLIBC_2.17
                 U fopen64@GLIBC_2.17
                 U fork@GLIBC_2.17
                 U fprintf@GLIBC_2.17
                 U fputc@GLIBC_2.17
                 U fputs@GLIBC_2.17
                 U fread@GLIBC_2.17
                 U free@GLIBC_2.17
                 U freeaddrinfo@GLIBC_2.17
                 U fstat64@GLIBC_2.33
                 U fsync@GLIBC_2.17
                 U ftruncate64@GLIBC_2.17
                 U fwrite@GLIBC_2.17
                 U getaddrinfo@GLIBC_2.17
                 U __getauxval@GLIBC_2.17
                 U getc@GLIBC_2.17
                 U getcwd@GLIBC_2.17
                 U getenv@GLIBC_2.17
                 U geteuid@GLIBC_2.17
                 U getline@GLIBC_2.17
                 U getpagesize@GLIBC_2.17
                 U getpeername@GLIBC_2.17
                 U getpgid@GLIBC_2.17
                 U getpid@GLIBC_2.17
                 U getsockname@GLIBC_2.17
                 U getsockopt@GLIBC_2.17
                 U gettimeofday@GLIBC_2.17
                 w __gmon_start__
                 U isatty@GLIBC_2.17
                 U __isoc23_sscanf@GLIBC_2.38
                 U __isoc23_strtol@GLIBC_2.38
                 U __isoc23_strtoull@GLIBC_2.38
                 U __isoc99_fscanf@GLIBC_2.17
                 U __isoc99_sscanf@GLIBC_2.17
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U kill@GLIBC_2.17
                 U __libc_start_main@GLIBC_2.34
                 U listen@GLIBC_2.17
                 U localtime@GLIBC_2.17
                 U localtime_r@GLIBC_2.17
                 U lockf64@GLIBC_2.17
                 U lseek64@GLIBC_2.17
                 U lstat64@GLIBC_2.33
                 U malloc@GLIBC_2.17
                 U memcmp@GLIBC_2.17
                 U memcpy@GLIBC_2.17
                 U __memcpy_chk@GLIBC_2.17
                 U memmove@GLIBC_2.17
                 U memset@GLIBC_2.17
                 U __memset_chk@GLIBC_2.17
                 U mkdir@GLIBC_2.17
                 U mmap64@GLIBC_2.17
                 U mremap@GLIBC_2.17
                 U MsQuicClose@msquic
                 U MsQuicOpenVersion@msquic
                 U munmap@GLIBC_2.17
                 U nanosleep@GLIBC_2.17
                 U open64@GLIBC_2.17
                 U opendir@GLIBC_2.17
                 U openlog@GLIBC_2.17
                 U perror@GLIBC_2.17
                 U pipe@GLIBC_2.17
                 U printf@GLIBC_2.17
                 U pthread_attr_destroy@GLIBC_2.17
                 U pthread_attr_init@GLIBC_2.17
                 U pthread_condattr_destroy@GLIBC_2.17
                 U pthread_condattr_init@GLIBC_2.17
                 U pthread_condattr_setclock@GLIBC_2.34
                 U pthread_cond_broadcast@GLIBC_2.17
                 U pthread_cond_destroy@GLIBC_2.17
                 U pthread_cond_init@GLIBC_2.17
                 U pthread_cond_signal@GLIBC_2.17
                 U pthread_cond_timedwait@GLIBC_2.17
                 U pthread_cond_wait@GLIBC_2.17
                 U pthread_create@GLIBC_2.34
                 U pthread_join@GLIBC_2.34
                 U pthread_mutexattr_destroy@GLIBC_2.34
                 U pthread_mutexattr_init@GLIBC_2.34
                 U pthread_mutexattr_settype@GLIBC_2.34
                 U pthread_mutex_destroy@GLIBC_2.17
                 U pthread_mutex_init@GLIBC_2.17
                 U pthread_mutex_lock@GLIBC_2.17
                 U pthread_mutex_trylock@GLIBC_2.34
                 U pthread_mutex_unlock@GLIBC_2.17
                 U pthread_rwlock_destroy@GLIBC_2.34
                 U pthread_rwlock_init@GLIBC_2.34
                 U pthread_rwlock_rdlock@GLIBC_2.34
                 U pthread_rwlock_unlock@GLIBC_2.34
                 U pthread_rwlock_wrlock@GLIBC_2.34
                 U pthread_self@GLIBC_2.17
                 U pthread_setname_np@GLIBC_2.34
                 U pthread_sigmask@GLIBC_2.32
                 U putchar@GLIBC_2.17
                 U puts@GLIBC_2.17
                 U read@GLIBC_2.17
                 U readdir64@GLIBC_2.17
                 U readlink@GLIBC_2.17
                 U readv@GLIBC_2.17
                 U realloc@GLIBC_2.17
                 U __register_atfork@GLIBC_2.17
                 U remove@GLIBC_2.17
                 U rename@GLIBC_2.17
                 U rewind@GLIBC_2.17
                 U rmdir@GLIBC_2.17
                 U sendmsg@GLIBC_2.17
                 U setsid@GLIBC_2.17
                 U setsockopt@GLIBC_2.17
                 U shutdown@GLIBC_2.17
                 U sigaction@GLIBC_2.17
                 U sigaddset@GLIBC_2.17
                 U sigemptyset@GLIBC_2.17
                 U sleep@GLIBC_2.17
                 U snprintf@GLIBC_2.17
                 U socket@GLIBC_2.17
                 U socketpair@GLIBC_2.17
                 U sprintf@GLIBC_2.17
                 U __sprintf_chk@GLIBC_2.17
                 U __stack_chk_fail@GLIBC_2.17
                 U __stack_chk_guard@GLIBC_2.17
                 U stat64@GLIBC_2.33
                 U stderr@GLIBC_2.17
                 U stdin@GLIBC_2.17
                 U stdout@GLIBC_2.17
                 U strcasecmp@GLIBC_2.17
                 U strcat@GLIBC_2.17
                 U __strcat_chk@GLIBC_2.17
                 U strchr@GLIBC_2.17
                 U strcmp@GLIBC_2.17
                 U strcpy@GLIBC_2.17
                 U __strcpy_chk@GLIBC_2.17
                 U strcspn@GLIBC_2.17
                 U strdup@GLIBC_2.17
                 U strerror@GLIBC_2.17
                 U strftime@GLIBC_2.17
                 U strlcpy@GLIBC_2.38
                 U strlen@GLIBC_2.17
                 U strncasecmp@GLIBC_2.17
                 U strncmp@GLIBC_2.17
                 U strncpy@GLIBC_2.17
                 U __strncpy_chk@GLIBC_2.17
                 U strnlen@GLIBC_2.17
                 U strrchr@GLIBC_2.17
                 U strstr@GLIBC_2.17
                 U strtod@GLIBC_2.17
                 U strtok@GLIBC_2.17
                 U strtok_r@GLIBC_2.17
                 U syscall@GLIBC_2.17
                 U sysconf@GLIBC_2.17
                 U system@GLIBC_2.17
                 U time@GLIBC_2.17
                 U unlink@GLIBC_2.17
                 U utimes@GLIBC_2.17
                 U vfprintf@GLIBC_2.17
                 U vprintf@GLIBC_2.17
                 U vsnprintf@GLIBC_2.17
                 U __vsyslog_chk@GLIBC_2.17
                 U write@GLIBC_2.17
                 U writev@GLIBC_2.17

良好的二进制(GNU nm 2.40,过滤输出)

0000000000049714 T plugin_hook_register

buildroot 二进制文件缺少这些符号,但仅来自 nm 而不是 readelf。

gcc linker buildroot dlopen
1个回答
0
投票

如何进一步检查二进制文件以确定找不到该符号的原因

该符号存在于“常规”符号表中,但不存在于动态符号表中。只有动态符号表中存在的符号才会参与动态链接。

动态符号表中缺少的已定义符号必须已被有意隐藏(默认情况下,所有符号均已导出)。

这可以通过多种方式发生:

  • 该符号可能标有
    __attribute__((visibility("hidden"))
    "protected"
  • 该符号可能隐藏在链接器版本脚本中
  • 编译命令可能有
    -fvisibility=hidden
    标志

因此请在两个构建环境中寻找上述差异。换句话说,比较链接和编译命令行、比较链接器脚本(如果有)、比较预处理的源。其中至少有一个必须不同。

© www.soinside.com 2019 - 2024. All rights reserved.