赞
踩
可执行与可链接格式 (英语:Executable and Linkable Format,缩写为ELF),常被称为ELF格式,在计算机科学中,是一种用于可执行文件、目标文件、共享库和核心转储的标准文件格式。1999年,被86open项目选为x86架构上的类Unix操作系统的二进制文件格式标准,用来取代COFF。因其可扩展性与灵活性,也可应用在其它处理器、计算机系统架构的操作系统上。格式
对象文件(Object files)有三个种类:
- 可重定位的对象文件(Relocatable file)
这是由汇编器汇编生成的 .o 文件。后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file)。我们可以使用 ar 工具将众多的 .o Relocatable object files 归档(archive)成 .a 静态库文件。如何产生 Relocatable file,你应该很熟悉了,请参见我们相关的基本概念文章和JulWiki。另外,可以预先告诉大家的是我们的内核可加载模块 .ko 文件也是 Relocatable object file。- 可执行的对象文件(Executable file)
这我们见的多了。文本编辑器vi、调式用的工具gdb、播放mp3歌曲的软件mplayer等等都是Executable object file。你应该已经知道,在我们的 Linux 系统里面,存在两种可执行的东西。除了这里说的 Executable object file,另外一种就是可执行的脚本(如shell脚本)。注意这些脚本不是 Executable object file,它们只是文本文件,但是执行这些脚本所用的解释器就是 Executable object file,比如 bash shell 程序。- 可被共享的对象文件(Shared object file)
这些就是所谓的动态库文件,也即 .so 文件。如果拿前面的静态库来生成可执行程序,那每个生成的可执行程序中都会有一份库代码的拷贝。如果在磁盘中存储这些可执行程序,那就会占用额外的磁盘空 间;另外如果拿它们放到Linux系统上一起运行,也会浪费掉宝贵的物理内存。如果将静态库换成动态库,那么这些问题都不会出现。动态库在发挥作用的过程 中,必须经过两个步骤:
a)链接编辑器(link editor)拿它和其他Relocatable object file以及其他shared object file作为输入,经链接处理后,生存另外的 shared object file 或者 executable file。
b)在运行时,动态链接器(dynamic linker)拿它和一个Executable file以及另外一些 Shared object file 来一起处理,在Linux系统里面创建一个进程映像。
ELF文件格式提供了两种视图,分别是链接视图和执行视图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZSsdsTlX-1635732326658)(en-resource://database/982:1)]
链接视图是以节(section)为单位,执行视图是以段(segment)为单位。
链接视图就是在链接时用到的视图,而执行视图则是在执行时用到的视图。
上图左侧的视角是从链接来看的,右侧的视角是执行来看的。
总个文件可以分为四个部分:
实际上,一个文件中不一定包含全部内容,而且它们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定。 [1]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zevR60Fm-1635732326660)(en-resource://database/983:1)]
ELF文件有两种索引:程序标头中记载了运行时所需的段,而段首地址表记载了二进制文件中段的首地址
前面我们知道了SO是ELF在动态链接库,也就是ELF在Android平台的扩展名。
.so文件是一个C/C++的函数库,Android中调用.so文件都是通过jni的方式。Android系统中每一个CPU架构对应一个ABI,
目前有以下几种:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64,所以我们可以生成对应ABI的.so文件。
defaultConfig { ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' }}
AS已经为我们添加了几个核心文件和代码块
main.java
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
native-lib.cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_huruwo_elf_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C--";
return env->NewStringUTF(hello.c_str());
}
3.cmake跨平台动态编译配置
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
SHARED
native-lib.cpp)
find_library( # Sets the name of the path variable.
log-lib
target_link_libraries( # Specifies the target library.
native-lib
${log-lib})
具体的JNI编写不在此篇讨论之内
了解ELF文件和SO文件的实质以及SO文件的编写。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。