Android的 - 如何加载共享库? [英] Android – how to load shared library?

查看:556
本文介绍了Android的 - 如何加载共享库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我简单的可执行文件,并创建SHARED_LIBRARY。
SHARED_LIBRARY不会被加载,而不改变LD_LIBRARY_PATH:

 #./hello
。/你好
link_image [1995]:未链接./hello
不能链接EXECUTABLE#LD_LIBRARY_PATH =:$ LD_LIBRARY_PATH ./hello
你好,世界!

所有code如下:

first.h

 的#ifndef FIRST_H
#定义FIRST_HEXTERN INT第一(INT X,int y)对;#ENDIF / * * FIRST_H /

first.c

 的#includefirst.h首先INT(INT X,int y)对{
    返回X + Y;
}

的hello.c

 的#include<&stdio.h中GT;
#包括first.hINT主(INT ARGC,字符** argv的){
    的printf(你好,世界\\ n!);
    第一(1000,24);
    返回0;
}

Android.mk

 包含$(CLEAR_VARS)
LOCAL_MODULE:=第一
LOCAL_SRC_FILES:= first.c
包括$(BUILD_SHARED_LIBRARY)包括$(CLEAR_VARS)
LOCAL_MODULE:=你好
LOCAL_SRC_FILES:=的hello.c
LOCAL_SHARED_LIBRARIES:=第一
LOCAL_LDFLAGS:= -Wl,-rpath,。 -Wl,-rpath,/数据/数据​​/ TESTLIB / lib目录
包括$(BUILD_EXECUTABLE)

readelf --all你好

  ...
偏移0xef4动态部分包含25个条目:
程序头:
  型胶印VirtAddr PhysAddr FileSiz MemSiz FLG对齐
  INTERP 0x000154 0x00008154 0x00008154 0x00013 0x00013 - [R为0x1
      [请求程序间preTER:/系统/斌/接头]
...
  标记类型名称/值
 00000001(需要)共享库:[libfirst.so]
 00000001(需要)共享库:[++的libstdc如此。]
 00000001(需要)共享库:[libm.so]
 00000001(需要)共享库:[libc.so]
 00000001(需要)共享库:[libdl.so]
 0x0000000f(RPATH)库rpath的:[:/数据/数据​​/ TESTLIB / lib目录]

RPATH是在这里,但链接器不使用它的一些原因。

显然,动态连接器只是罚款在Android(与LD_LIBRARY_PATH和它的没有什么不同RPATH其一)

做我错了吗?

我失去了一些东西明显?

RPATH在我的例子两个目录,(:/数据/数据​​/ TESTLIB / lib中)(。),应该是足够的。

有在这个例子中没有Java。它不使用,不需要的项目。

基本上我正在寻找加载从我的目录不改变LD_LIBRARY_PATH(这是不可能的,有时)或使用包装执行dlopen所有必需的库。

共享库的标准方式
解决方案

仿生链接器加载程序(在AOSP源代码的Andr​​oid /仿生/连接器/ linker.c,如果你想检查),似乎在完全忽略RPATH ELF。它只考虑LD_LIBRARY_PATH和/供应商/ lib目录和硬codeD阵/系统/ lib目录。

这是基于对冰淇淋三明治树中的code我已签出的粗略扫描。

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

I’ve created simplest EXECUTABLE and SHARED_LIBRARY. SHARED_LIBRARY doesn’t get loaded without changing LD_LIBRARY_PATH:

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

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

All code below:

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 is here, but linker doesn’t use it for some reason.

Apparently dynamic linker works just fine on Android (with LD_LIBRARY_PATH and it’s no different RPATH either)

What do I do wrong?

Am I missing something obvious?

RPATH has two directories in my example, (.:/data/data/testlib/lib), one (.) should be sufficient.

There is no Java in this example. It’s not used and not needed for the project.

Basically I’m looking for a standard way to load shared libraries from "my directory" without changing LD_LIBRARY_PATH (it’s not possible sometimes) or using wrapper to dlopen all required libs.

解决方案

The Bionic linker-loader (android/bionic/linker/linker.c in the AOSP source, if you want to check) seems to completely ignore RPATH in the ELF. It only considers LD_LIBRARY_PATH and a hardcoded array of "/vendor/lib" and "/system/lib".

This is based on a cursory scan of the code on the Ice Cream Sandwich tree I have checked out.

This would explain the behavior you are seeing.

这篇关于Android的 - 如何加载共享库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆