Bionic和libc的存根实现

时间:2016-08-23 18:57:54

标签: android-ndk shared-libraries ld libc bionic

我想运行一个x86共享库,我从非Android机器上的apk上抓取。

它与android libc相关联,所以我从android ndk中抓取了libc.so。 调试段错误一段时间后,我认为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正在做这个技巧以及覆盖如何在那里工作的一些更多背景也会感兴趣。

1 个答案:

答案 0 :(得分:2)

如您所见,从NDK中获取的libc.so仅包含存根,因为它的目的是在创建您自己的共享库或可执行文件时为链接器提供必要的信息。以下是nice explanation我们需要存根库的原因。

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

  1. 直接从Android设备抓取:

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

  3. 但即使你得到了合适的二进制文件,这也是一个非常痛苦的例子 - 让它在你的桌面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]
      

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

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

    3. 最重要的是:在桌面GNU / Linux上重复使用Android二进制文件几乎是不可能的,即使它们是以相同的硬件架构为目标。