Android - 如何加载共享库?

Sam*_*... 9 android shared-libraries android-ndk

我创建了最简单的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!
Run Code Online (Sandbox Code Playgroud)

以下所有代码:

first.h

#ifndef FIRST_H
#define FIRST_H

extern int first(int x, int y);

#endif /* FIRST_H */
Run Code Online (Sandbox Code Playgroud)

first.c

#include "first.h"

int first( int x, int y ) {
    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

你好ç

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

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

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)
Run Code Online (Sandbox Code Playgroud)

readelf - 你好

...
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]
Run Code Online (Sandbox Code Playgroud)

RPATH在这里,但链接器由于某种原因不使用它.

显然动态链接器在Android上运行得很好(使用LD_LIBRARY_PATH,它也没有不同的RPATH)

我做错了什么?

我错过了一些明显的东西吗

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

这个例子中没有Java.它没有被使用,也不需要项目.

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

Yur*_*nko 15

Bionic链接器加载器(AOSP源中的android/bionic/linker/linker.c,如果你想检查)似乎完全忽略了ELF中的RPATH.它只考虑LD_LIBRARY_PATH和"/ vendor/lib"和"/ system/lib"的硬编码数组.

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

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