1

我想运行一个 x86 共享库,它是从非 android linux 机器上的 apk 中获取的。

它与 android libc 相关联,所以我libc.so从 android ndk 中获取了它。在调试了段错误一段时间后,我认为这libc.so是“作弊”,并且只包含许多库函数的 nop 实现:

$ objdump -d libc.so | grep memalign -A 8
0000bf82 <memalign>:
    bf82:       55                      push   %ebp
    bf83:       89 e5                   mov    %esp,%ebp
    bf85:       5d                      pop    %ebp
    bf86:       c3                      ret    

现在 ndk 还包含一个libc.a包含这些函数的实际实现的函数,但是如何让我的进程加载这些函数并覆盖 libc.so 的 nop 函数?还会对有关 android 为何使用此技巧以及覆盖如何在那里工作的更多上下文感兴趣。

4

1 回答 1

3

如您所见libc.so,取自 NDK 仅包含存根,因为它的目的是在创建您自己的共享库或可执行文件期间向链接器提供必要的信息。这里很好地解释了为什么我们需要存根库。

因此,如果您需要真正的libc.so二进制文件 - 有两种选择:

  1. 直接从 Android 设备抓取它:

    $ adb pull /system/lib/libc.so <local_destination>
    
  2. 为您的设备下载出厂 ROM 映像,解压缩,挂载system.img到本地文件系统,然后再次从/system/lib该挂载分区复制它。

但即使你得到了正确的二进制文件,它也是一个非常痛苦的练习——让它在你的桌面 Linux 上工作。至少有两个原因:

  1. Android 和桌面 Linux ELF 需要不同的解释器。您可以通过以下方式进行检查readelf

    $ readelf --all <android_binary> | grep interpreter
    [Requesting program interpreter: /system/bin/linker]
    $ readelf --all <linux_x64_binary> | grep interpreter
    [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
    

    (解释器是一个小程序,执行实际加载二进制文件并由内核加载)显然您的 Linux 系统没有/system/bin/linker,内核将拒绝加载此类二进制文件。因此,您必须以某种方式正确加载部分并自行解决所有依赖项。

  2. Android内核与桌面内核不同,它有一些额外的功能libc.so依赖,所以即使你以某种方式加载ELF,它仍然与你的内核不兼容,你肯定会在某个时候遇到问题。

最重要的是:实际上不可能在桌面 GNU/Linux 上重用 android 二进制文件,即使它们的目标是相同的硬件架构。

于 2016-08-26T08:38:51.553 回答