Android - 如何加载共享库?

11

我创建了最简单的可执行程序和共享库。如果不更改LD_LIBRARY_PATH,共享库将无法被加载:

# ./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: error while loading shared libraries: libfirst.so: cannot open shared object file: No such file or directorygcc -ohello hello.c -lfirst -L. -Wl,-rpath,. ./hello Hello, world!抱歉,不知道如何优雅地格式化评论。 - Same old guy...
readelf --all hello `... 程序头: 类型 偏移量 虚拟地址 物理地址 ... INTERP 0x0000000000000200 0x0000000000400200 0x0000000000400200 [请求程序解释器:/lib64/ld-linux-x86-64.so.2] ...偏移量为0x808的动态段包含22个条目: 标签 类型 名称/值 0x0000000000000001 (NEEDED) 共享库: [libfirst.so] 0x0000000000000001 (NEEDED) 共享库: [libc.so.6] 0x000000000000000f (RPATH) 库rpath: [.]` - Same old guy...
你尝试过省略 LOCAL_LDFLAGS 吗? - Olaf Dietsche
删除LOCAL_LDFLAGS将从.SO中删除RPATH设置。0x0000000f (RPATH) Library rpath: [.:/data/data/testlib/lib]也就是说,动态链接器只会使用LD_LIBRARY_PATH来查找所需的.SO文件。或者你指的是其他什么? - Same old guy...
不,因为我毫无头绪,只是胡乱尝试。 - Olaf Dietsche
一个解释是Andriod动态链接器不支持RPATH属性。 但是通过谷歌搜索可以发现它在某种程度上支持,可以这么说。 希望是我做错了什么,而不是动态链接器本身的问题;-) - Same old guy...
1个回答

17
需要翻译的内容:

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

这是基于我检查过的Ice Cream Sandwich树上的代码的粗略扫描。

这可以解释您所看到的行为。


1
这条消息“WARNING: linker: ./program: unused DT entry: type 0x1d arg 0x78”与“0x0000001d (RUNPATH) Library runpath: [.]”属性有关吗? - humanityANDpeace
1
在Android中是否可以将库添加到LD_LIBRARY_PATH? - RonTLV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接