【问题标题】:Android – how to load shared library?Android – 如何加载共享库?
【发布时间】:2012-09-19 21:51:34
【问题描述】:

我创建了最简单的 EXECUTABLE 和 SHARED_LIBRARY。 不更改 LD_LIBRARY_PATH 就不会加载 SHARED_LIBRARY:

# ./hello
./hello
link_image[1995]: failed to link ./hello
CANNOT LINK EXECUTABLE

# LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./hello
Hello, world!

以下所有代码:

first.h

#ifndef FIRST_H
#define FIRST_H

extern int first(int x, int y);

#endif /* FIRST_H */

first.c

#include "first.h"

int first( int x, int y ) {
    return x + y;
}

hello.c

#include <stdio.h>
#include "first.h"

int main( int argc, char **argv ) {
    printf( "Hello, world!\n" );
    first( 1000, 24 );
    return 0;
}

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE    := first
LOCAL_SRC_FILES := first.c
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
LOCAL_SHARED_LIBRARIES := first
LOCAL_LDFLAGS := -Wl,-rpath,. -Wl,-rpath,/data/data/testlib/lib
include $(BUILD_EXECUTABLE)

readelf --all hello

...
Dynamic section at offset 0xef4 contains 25 entries:
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  INTERP         0x000154 0x00008154 0x00008154 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /system/bin/linker]
...
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libfirst.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x0000000f (RPATH)                      Library rpath: [.:/data/data/testlib/lib]

RPATH 在这里,但链接器由于某种原因没有使用它。

显然动态链接器在 Android 上工作得很好(使用 LD_LIBRARY_PATH 并且它也没有不同的 RPATH)

我做错了什么?

我是否遗漏了一些明显的东西?

在我的示例中,RPATH 有两个目录,(.:/data/data/testlib/lib),一个 (.) 就足够了。

此示例中没有 Java。项目没有使用它,也不需要它。

基本上,我正在寻找一种从“我的目录”加载共享库的标准方法,而无需更改 LD_LIBRARY_PATH(有时这是不可能的)或使用包装器来 dlopen 所有必需的库。

【问题讨论】:

  • 为了测试我的理智,我在 CentOS 上使用相同的源文件运行以下命令:gcc -olibfirst.so first.c -fPIC -sharedgcc -ohello hello.c -lfirst -L../hello./hello:加载共享库时出错:libfirst.so:无法打开共享目标文件:没有这样的文件或目录gcc -ohello hello.c -lfirst -L. -Wl,-rpath,../hello你好,世界!抱歉,不知道如何正确格式化评论。
  • readelf --all hello ... Program Headers: Type Offset VirtAddr PhysAddr ... INTERP 0x0000000000000200 0x0000000000400200 0x0000000000400200 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] ... Dynamic section at offset 0x808 contains 22 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libfirst.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000f (RPATH) Library rpath: [.]
  • 你试过省略LOCAL_LDFLAGS吗?
  • 删除 LOCAL_LDFLAGS 将从 .SO 中删除 RPATH 设置 0x0000000f (RPATH) Library rpath: [.:/data/data/testlib/lib] 即动态链接器将仅使用 LD_LIBRARY_PATH 来查找所需的 .SO 或者您的意思是别的什么?
  • 不,因为我不知道,所以我只是在闲逛。

标签: android android-ndk shared-libraries


【解决方案1】:

仿生链接器加载程序(AOSP 源代码中的 android/bionic/linker/linker.c,如果您想检查的话)似乎完全忽略了 ELF 中的 RPATH。它只考虑 LD_LIBRARY_PATH 和“/vendor/lib”和“/system/lib”的硬编码数组。

这是基于我对冰淇淋三明治树上代码的粗略扫描。

这将解释您所看到的行为。

【讨论】:

  • 这与WARNING: linker: ./program: unused DT entry: type 0x1d arg 0x78 相关的消息是0x0000001d (RUNPATH) Library runpath: [.] 属性吗?
  • 是否可以在android LD_LIBRARY_PATH 中添加一个库?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-10
  • 2012-11-18
  • 2019-04-17
  • 2021-05-23
  • 1970-01-01
相关资源
最近更新 更多