【问题标题】:Cannot open shared library (so) on Raspberry Pi无法在 Raspberry Pi 上打开共享库(so)
【发布时间】:2014-11-01 20:45:45
【问题描述】:

我正在尝试在 Raspberry PI ARM 机器上运行为 Android 编译的 ARM 共享对象二进制文件(在 .apk 中)。

不幸的是,二进制文件是封闭源代码,我无法为在树莓派上运行的操作系统重新编译它(raspian,debian derivation)

快速问题:是否可以在树莓派上运行这样一个为 android 编译的 .so 文件?我在这里上传了二进制文件:http://www.speedyshare.com/MSXq9/libfoo.so(下载不便,请见谅)。

我在这里Running ARM binaries for Android on Linux ARM 发现了这个类似的问题,它表明二进制文件不会在其他 unix 发行版上运行(我在我的树莓上使用 debian 的衍生版本,raspian),因为 android 的 c 库是 Bionic。

可以在 debian 上安装仿生吗?我怎样才能设法运行这个库?

如果我想运行/加载 libfoo.so,则在 rasbperry 机器上生成以下所有输出。

当我尝试在 python 中加载 .so 文件时(之前,我相应地设置了 LD_PRELOAD)

import ctypes 
import os

path = os.path.dirname(os.path.realpath(__file__))
print ctypes.cdll.LoadLibrary('libfoo.so')

我得到一个 OSError: libfoo.so: cannot open shared object file: No such file or directory.

但是在查看 strace 输出后,加载程序似乎无法加载 libfoo.so 并因此失败并显示略微误导的错误消息 No such file or directory(在找到所有 .so 之后并且加载器尝试加载它,但在加载时失败)。

当发出 readelf -h libfoo.so 我得到

root@raspberrypi:/home/pi# readelf -h libfoo.so 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x10b60
  Start of program headers:          52 (bytes into file)
  Start of section headers:          341440 (bytes into file)
  Flags:                             0x5000002, has entry point, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         21
  Section header string table index: 20

此外,libfoo.so 的 attribute section aeabi(通过 readelf --all 获得)

No version information found in this file.
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "5TE"
  Tag_CPU_arch: v5TE
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int

相比之下,在我尝试运行 libfoo.so 的树莓平台上,本地编译的 .so 的输出与上述相同:

  Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "6"
  Tag_CPU_arch: v6
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_FP_arch: VFPv2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: SP and DP
  Tag_ABI_VFP_args: VFP registers
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_DIV_use: Not allowed

编译共享库的 CPU 存在一些差异,但我认为这无关紧要,因为 ARM 架构向下兼容。

这里是用于尝试加载 libfoo.so 的 strace 输出

  root@raspberrypi:/home/pi# strace ./test -s libfoo.so
execve("./test", ["./test", "-s", "libfoo.so"], [/* 19 vars */]) = 0
brk(0)                                  = 0x36f000
uname({sys="Linux", node="raspberrypi", ...}) = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f6a000
access("/etc/ld.so.preload", R_OK)      = 0
open("/etc/ld.so.preload", O_RDONLY)    = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=44, ...}) = 0
mmap2(NULL, 44, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = 0xb6f69000
close(3)                                = 0
open("/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\270\4\0\0004\0\0\0"..., 512) = 512
lseek(3, 7276, SEEK_SET)                = 7276
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1080) = 1080
lseek(3, 7001, SEEK_SET)                = 7001
read(3, "A.\0\0\0aeabi\0\1$\0\0\0\0056\0\6\6\10\1\t\1\n\2\22\4\24\1\25"..., 47) = 47
fstat64(3, {st_mode=S_IFREG|0755, st_size=10170, ...}) = 0
mmap2(NULL, 39740, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6f3e000
mprotect(0xb6f40000, 28672, PROT_NONE)  = 0
mmap2(0xb6f47000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1) = 0xb6f47000
close(3)                                = 0
munmap(0xb6f69000, 44)                  = 0
open("/usr/lib/tls/v6l/vfp/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v6l/vfp", 0xbea66f20) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v6l/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v6l", 0xbea66f20)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/vfp/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/vfp", 0xbea66f20)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls", 0xbea66f20)      = -1 ENOENT (No such file or directory)
open("/usr/lib/v6l/vfp/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v6l/vfp", 0xbea66f20)  = -1 ENOENT (No such file or directory)
open("/usr/lib/v6l/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v6l", 0xbea66f20)      = -1 ENOENT (No such file or directory)
open("/usr/lib/vfp/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/vfp", 0xbea66f20)      = -1 ENOENT (No such file or directory)
open("/usr/lib/libdl.so.2", O_RDONLY)   = -1 ENOENT (No such file or directory)
stat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=43090, ...}) = 0
mmap2(NULL, 43090, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6f33000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/libdl.so.2", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0(\t\0\0004\0\0\0"..., 512) = 512
lseek(3, 8652, SEEK_SET)                = 8652
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1160) = 1160
lseek(3, 8320, SEEK_SET)                = 8320
read(3, "A0\0\0\0aeabi\0\1&\0\0\0\0056\0\6\6\10\1\t\1\n\2\22\4\24\1\25"..., 49) = 49
fstat64(3, {st_mode=S_IFREG|0644, st_size=9812, ...}) = 0
mmap2(NULL, 41136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6f28000
mprotect(0xb6f2a000, 28672, PROT_NONE)  = 0
mmap2(0xb6f31000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1) = 0xb6f31000
close(3)                                = 0
open("/usr/lib/libc.so.6", O_RDONLY)    = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\214y\1\0004\0\0\0"..., 512) = 512
lseek(3, 1198880, SEEK_SET)             = 1198880
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1360) = 1360
lseek(3, 1198444, SEEK_SET)             = 1198444
read(3, "A.\0\0\0aeabi\0\1$\0\0\0\0056\0\6\6\10\1\t\1\n\2\22\4\24\1\25"..., 47) = 47
fstat64(3, {st_mode=S_IFREG|0755, st_size=1200240, ...}) = 0
mmap2(NULL, 1242408, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6df8000
mprotect(0xb6f1b000, 28672, PROT_NONE)  = 0
mmap2(0xb6f22000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x122) = 0xb6f22000
mmap2(0xb6f25000, 9512, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6f25000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f69000
set_tls(0xb6f694c0, 0xb6f69b98, 0xb6f6e048, 0xb6f694c0, 0xb6f6e048) = 0
mprotect(0xb6f22000, 8192, PROT_READ)   = 0
mprotect(0xb6f31000, 4096, PROT_READ)   = 0
mprotect(0xb6f6d000, 4096, PROT_READ)   = 0
munmap(0xb6f33000, 43090)               = 0
open("/usr/lib/libfoo.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0`\v\1\0004\0\0\0"..., 512) = 512
lseek(3, 341440, SEEK_SET)              = 341440
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 840) = 840
lseek(3, 341224, SEEK_SET)              = 341224
read(3, "A(\0\0\0aeabi\0\1\36\0\0\0\0055TE\0\6\4\10\1\t\1\22\4\24\1\25"..., 41) = 41
close(3)                                = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=43090, ...}) = 0
mmap2(NULL, 43090, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6f33000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/tls/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/tls/v6l/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/tls/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/tls/v6l", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/tls/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/tls/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/tls/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/tls", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/v6l/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/v6l", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/lib/arm-linux-gnueabihf/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/arm-linux-gnueabihf", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
open("/usr/lib/arm-linux-gnueabihf/tls/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/tls/v6l/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/tls/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/tls/v6l", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/tls/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/tls/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/tls/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/tls", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/v6l/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/v6l", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf/vfp", 0xbea66f40) = -1 ENOENT (No such file or directory)
open("/usr/lib/arm-linux-gnueabihf/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/arm-linux-gnueabihf", {st_mode=S_IFDIR|0755, st_size=28672, ...}) = 0
open("/lib/tls/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v6l/vfp", 0xbea66f40)  = -1 ENOENT (No such file or directory)
open("/lib/tls/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v6l", 0xbea66f40)      = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0xbea66f40)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0xbea66f40)          = -1 ENOENT (No such file or directory)
open("/lib/v6l/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v6l/vfp", 0xbea66f40)      = -1 ENOENT (No such file or directory)
open("/lib/v6l/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v6l", 0xbea66f40)          = -1 ENOENT (No such file or directory)
open("/lib/vfp/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0xbea66f40)          = -1 ENOENT (No such file or directory)
open("/lib/libfoo.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/usr/lib/libfoo.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0`\v\1\0004\0\0\0"..., 512) = 512
lseek(3, 341440, SEEK_SET)              = 341440
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 840) = 840
lseek(3, 341224, SEEK_SET)              = 341224
read(3, "A(\0\0\0aeabi\0\1\36\0\0\0\0055TE\0\6\4\10\1\t\1\22\4\24\1\25"..., 41) = 41
close(3)                                = 0
brk(0)                                  = 0x36f000
brk(0x390000)                           = 0x390000
munmap(0xb6f33000, 43090)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f68000
write(1, "Service libfoo.so Not Fo"..., 115Service libfoo.so Not Found:  libfoo.so: cannot open shared object file: No such file or directory
) = 115
write(1, "Problem calling generic_function"..., 91Problem calling generic_function_entry(): ./test: undefined symbol: generic_function_entry
) = 91
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault

【问题讨论】:

  • 你可以让它在 chroot 中工作,诀窍是你应该从一个“普通”的 android 仿生 libc 和工具开始,或者一个 android-on-pi 的。我怀疑通过足够的工作,您可以创建一个自定义构建的仿生(包括其动态链接器),它可以与您的正常 debian pi 设置一起运行(即,没有 chroot)。不过,请确保您的 ABI 完全兼容。怎么没有资源?
  • 感谢您的回复。 @rakib:目前似乎没有在 Raspberry Pi 上运行的 Android。如果是这样,这将是我最喜欢的方法。
  • @Chris Stratton:我会试一试。你有没有什么教程可以让我看看,它解释了如何使用 Bionic 构建一个 chroot?
  • 下载链接给出了 404,但我知道这是一个很老的问题。
  • 有传言称谷歌将 Raspberry Pi 添加为官方支持的 Android 目标。对于运行最简单的可能可执行文件的 chroot,您应该只需要基本库和动态链接器,如上面的 Chris Stratton cmets。最简单的方法是使用安装在 x86/amd64 机器上的正确版本的 Android NDK 来编译和链接您的可执行文件。寻求 NDK 文档以了解 Android 和普通 Linux 系统的差异 - 主要是 Android 内核缺少一些服务,但它也添加了一些东西,特别是 Binder IPC。我不知道这对 Bionic libc 有多大影响,也许影响不大。

标签: android linux arm shared-libraries dynamic-linking


【解决方案1】:

libhybris 可以在 Glibc 系统中使用基于仿生的硬件适配。 从概念上讲,libhybris 是 Bionic 链接器的自定义版本,其中钩子将仿生符号替换为与 Glibc 兼容的符号。 它提供了android_dlopen,android_dlsym 来使用来自 glibc 的 Android 原生库。

【讨论】:

  • 不推荐链接到外部教程和资源,尤其是当它们使用与英语不同的语言时。
猜你喜欢
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2013-06-11
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多