Android ART VM可执行文件格式-ELF(二)

ART虚拟机,通过dex2oat将dex预编译成机器码的oat文件,是基于linux中的可执行文件格式ELF所做的扩展。

ELF(Executable and Linkable Format)的处理流程:

它至少支持三种文件形态:可重定向文件(Relocatable File),可执行文件(Executable File),可共享的对象文件(Shared Object File)。

Relocatable File的一个具体范例是.o 文件,是编译过程中产生的中间文件,通过file 命令查看这类.o文件,可看到他们属于 ELF relocatable文件。

ELF的另一种文件形态是shared object file(动态链接库),通常以.so为后缀:


ELF文件格式的内部构成,可以从Linking,Execution两个视角分析,可以参考:

转自 Android ELF

转载 Android ELF

可以利用readelf命令读取elf的文件头信息,命令行:
readelf -h ***.o
readelf是linux系统分析ELF文件的一个工具。
elf header对应的数据结构:
art/runtime/elf.h

struct Elf32_Ehdr {
  unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes
  Elf32_Half    e_type;      // Type of file (see ET_* below)
  Elf32_Half    e_machine;   // Required architecture for this file (see EM_*)
  Elf32_Word    e_version;   // Must be equal to 1
  Elf32_Addr    e_entry;     // Address to jump to in order to start program
  Elf32_Off     e_phoff;     // Program header table's file offset, in bytes
  Elf32_Off     e_shoff;     // Section header table's file offset, in bytes
  Elf32_Word    e_flags;     // Processor-specific flags
  Elf32_Half    e_ehsize;    // Size of ELF header, in bytes
  Elf32_Half    e_phentsize; // Size of an entry in the program header table
  Elf32_Half    e_phnum;     // Number of entries in the program header table
  Elf32_Half    e_shentsize; // Size of an entry in the section header table
  Elf32_Half    e_shnum;     // Number of entries in the section header table
  Elf32_Half    e_shstrndx;  // Sect hdr table index of sect name string table
  bool checkMagic() const {
    return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0;
  }
  unsigned char getFileClass() const { return e_ident[EI_CLASS]; }
  unsigned char getDataEncoding() const { return e_ident[EI_DATA]; }
};


ELF文件的加载和动态链接过程

示例程序:

#include "stdio.h"
int add(int v1,int v2){

    return v1+v2;

}

int main(){

    add(1,2);

    printf("it is test.");
    return 0;

}

在这个程序中,add函数是定义在当前程序的,它的地址已知,但是printf函数是由C库提供的外部函数,在编译时不会被打包到这个程序中,而是等到这个程序真正运行起来,系统把它需要的动态链接库加载到内存,然后解析出它引用的外部函数的真实地

址,并保证可执行程序可以正确指向这些外部函数。

编译这个小程序,

gcc -c Main.cpp

然后执行链接操作,使其成为真正的可执行程序:

gcc -o Main Main.cpp

使用readelf -S 命令查看section信息:

在Linux平台下,elf格式可执行程序提供了一个名为.interp字段,用于记录程序运行时所使用的动态连接器,这个程序使用的连接器是/lib64/ld-linux-x86-64.so.2,这实际是个可执行程序,类似于Android平台下的system/bin/Linker。

转载:可执行文件的加载函数

Android系统的配置文件,定义了相关的动态连接器

build/core/definitions.mk

###########################################################
## Commands for running gcc to link an executable
###########################################################

define transform-o-to-executable-inner
$(hide) $(PRIVATE_CXX) -pie \
	-nostdlib -Bdynamic \
	-Wl,-dynamic-linker,$(PRIVATE_LINKER) \
	-Wl,--gc-sections \

其中的-dynamic-linker指定了所需的动态链接其,由后面的变量值决定(system/bin/linker64 or linker32).

对应的源码目录:/bionic/linker,这个linker是处理的动态链接库的隐式调用,Android中对动态库的显示调用方法有:

1)Java层,System.loadLibary(String libname)和System.load(String pathname),这两个函数的区别是前者要指出动态链接库的名称,系统在预先设置的路径查找并加载.so库;后者允许将动态库放在程序有权限访问的地方,给出完整的加载路径。

2)native层,dlopen标准接口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值