是AOSP的libc ++。与NDK的libc ++ _ shared.so?

时间:2017-11-12 00:43:20

标签: android android-ndk android-source

我正在Android应用中工作,其中一个共享库(我在Android Studio中构建,让我们称之为libA.so)由供应商动态加载另一个共享库提供程序(我们称之为libB.so)。我知道我不应该在我的应用程序中使用多个C ++运行时库(https://developer.android.com/ndk/guides/cpp-support.html#important_considerations),所以我们决定在两个库中使用c ++ _ shared。

在构建AOSP时,

libB.so(由供应商提供的那个)被编译和链接(供应商坚持以这种方式构建库,不能做很多事情)。 libB.so的makefile将STL标志设置为c ++ _与此共享:

LOCAL_NDK_STL_VARIANT := c++_shared

当我查看libB.so库中的NEEDED标记时,我可以看到对libc++.so

的依赖关系
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++.so] <----
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x000000000000000e (SONAME)             Library soname: [libB.so]

当我运行readelf -d libc++.so检查AOSP的libc ++的内容时,我得到了这个

Dynamic section at offset 0xe4b40 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000003 (PLTGOT)             0xe6310
 0x0000000000000002 (PLTRELSZ)           22128 (bytes)
 0x0000000000000017 (JMPREL)             0x39ff8
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000007 (RELA)               0x2ce58
 0x0000000000000008 (RELASZ)             53664 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          380
 0x0000000000000006 (SYMTAB)             0x238
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0xdeb8
 0x000000000000000a (STRSZ)              102917 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x270c0
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x000000000000000e (SONAME)             Library soname: [libc++.so]
 0x000000000000001a (FINI_ARRAY)         0xe08e0
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x0000000000000019 (INIT_ARRAY)         0xe5b38
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x000000006ffffff0 (VERSYM)             0x2bb7c
 0x000000006ffffffc (VERDEF)             0x2cddc
 0x000000006ffffffd (VERDEFNUM)          1
 0x000000006ffffffe (VERNEED)            0x2cdf8
 0x000000006fffffff (VERNEEDNUM)         2
 0x0000000000000000 (NULL)               0x0

我知道NDK也提供了libc++.so,但是当我在Android NDK中分发的库中运行相同的命令时,我收到错误

readelf: Error: libc++.so: Failed to read file header

如果我没有弄错,那是因为在NDK中,libc++.so实际上是一个链接描述文件。

libA.so(我使用我的应用程序构建并加载libB.so)最终依赖于libc++_shared.so

Dynamic section at offset 0x4bca50 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++_shared.so] <---
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libA.so]

我认为我不能(或应该)在我的应用中捆绑libc++.solibc++_shared.so

那么,AOSP的libc++.so和NDK的libc++_shared.so是一样的吗?

有人知道为什么即使使用libc++.so,AOSP也会向libc++_shared.so而非LOCAL_NDK_STL_VARIANT := c++_shared添加动态依赖关系?我应该要求我的提供商链接libc++_shared.so吗?也许有人有更好的建议来解决这种依赖性不匹配问题。

2 个答案:

答案 0 :(得分:1)

不,他们不等同。 libc ++。所以在AOSP中是针对最新的(技术上是未来的 API级别)API级别而没有libandroid_support构建的。它使用不同的标志集构建,并且可能是不同的ABI。它使用一组体系结构标志构建,允许编译器使用所有Android设备上不可用的指令。它也与NDK中的版本不同,但对于不同的NDK版本也是如此,在决定它们是否兼容时不太重要。

如果供应商向您提供libB.so以包含在您的应用中,则他们正在错误地构建它。正如您所注意到的,它是与平台libc ++的链接。因此,应用程序无法访问它。你身边没有任何解决办法;供应商需要提供适当的NDK库。如果他们想继续使用AOSP构建系统,则需要设置LOCAL_SDK_VERSION,以便LOCAL_NDK_STL_VARIANT不被忽略。

如果供应商提供的设备已将此库安装到系统映像(即/system/lib64/libB.so, not 包含在您的应用程序中),那么@ alex-中的指导科恩的回答适用。这就是建立像libandroid.so这样的官方NDK库的方式。它们链接到系统的libc ++。所以,但只向应用程序公开C ABI。只要供应商遵循这些准则,就可以了。

正如亚历克斯所提到的那样,你所引用的文件比现实情况略有限制。 可以在同一个程序中使用多个STL(否则NDK应用程序根本无法工作,因为平台和应用程序使用不同的STL),但它确实需要非常仔细的管理您的ABI的表面区域以及避免ODR违规的非常谨慎。

答案 1 :(得分:0)

首先,可以在一个应用中混合使用不同的C ++运行时,只要它们不交互即可。这意味着,C ++对象(包括异常)不应跨越其共享库的边界。因此,如果您的 libB.so 提供 extern&#34; C&#34; 公共API,您可以安全地使用为 any <编译的组件中的这些函数/ em> C ++运行时,甚至 stlport_static

如果供应商lib未导出纯C API,则违反了体系结构规定(请参阅https://source.android.com/devices/architecture/images/vndk_design_android_o.pdf,第27页)。在这种情况下,您可能还需要构建依赖 libA.so 作为AOSP的一部分。如果您选择将库更紧密地耦合到 libB.so ,例如,您可以这样做。扩展它的一些类,在libA / libB边界上抛出异常等等。

请注意,自Android N以来,系统链接器protects平台库(/ system / lib和/ vendor / lib中的那些)来自用户代码 dlopen 。您应该考虑将 libB libA 或两者都添加到whitelist