【发布时间】: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