Android ART运行环境下Image文件格式简析

来源:互联网 发布:数据化武道 编辑:程序博客网 时间:2024/05/17 04:32

可以通过阅读代码来帮助分析Image文件的格式。

首先,在art\runtime\Image.h文件中,有相关的定义:

byte magic_[4];byte version_[4];// Required base address for mapping the image.uint32_t image_begin_;// Image size, not page aligned.uint32_t image_size_;// Image bitmap offset in the file.uint32_t image_bitmap_offset_;// Size of the image bitmap.uint32_t image_bitmap_size_;// Checksum of the oat file we link to for load time sanity check.uint32_t oat_checksum_;// Start address for oat file. Will be before oat_data_begin_ for .so files.uint32_t oat_file_begin_;// Required oat address expected by image Method::GetCode() pointers.uint32_t oat_data_begin_;// End of oat data address range for this image file.uint32_t oat_data_end_;// End of oat file address range. will be after oat_data_end_ for// .so files. Used for positioning a following alloc spaces.uint32_t oat_file_end_;// Absolute address of an Object[] of objects needed to reinitialize from an image.uint32_t image_roots_;

下面一一说明:

1)  最先的4个字节是Image文件的magic code,其值在对应的art\runtime\Image.cc文件中有定义:

const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };

2)  接下来的4个字节是Image文件的版本号,同样在Image.cc文件中有指定:

const byte ImageHeader::kImageVersion[] = { '0', '0', '5', '\0' };

3)  再下来的4个字节指定了Image文件映射到内存中的起始地址;

4)  再下来的4个字节说明了Image文件的大小,这是没有根据页4K对齐后的大小;

5)  再下来的8个字节用来指定Image的bitmap,先4个字节说明bitmap相对文件头所在内存地址的偏移,后4个地址说明bitmap的具体大小,至于bitmap的具体作用,以后再说;

6)  再下来的4个字节指定了所要链接的oat文件的checksum,方便以后在运行时检查;

7)  再下来的4个字节是Boot Oat文件在内存中的起始地址,该地址同时也在包含Oat的Elf文件中指定,从而保证在dlopen后加载到这个特定的地址;

8)  再下来的4个字节是Boot Oat文件中数据段的起始地址,该地址和Boot Oat文件中符号oatdata指定的地址一样;

9)  再下来的4个字节是Boot Oat文件中数据段的结束地址,该值等于Boot Oat文件中符号oatlastword+4;

10)             再下来的4个字节是Boot Oat文件在内存中的结束地址,该值可以定位用于动态内存分配的内存段;

11)             最后的4个字节很关键,它是一个地址,指向了一个ObjectArray,里面包含了非常重要的对象。具体来说,一共有7个:

enum ImageRoot {  kResolutionMethod,  kCalleeSaveMethod,  kRefsOnlySaveMethod,  kRefsAndArgsSaveMethod,  kOatLocation,  kDexCaches,  kClassRoots,  kImageRootsMax,};
就先说这么多,具体每个的作用稍后再分析。

目前为止,罗列了那么多概念,估计大家头也晕了,下面举个例子吧。笔者有一台Google Nexus 7二代设备,打开开发者选项,切换到ART运行环境,并且root过后,可以把Image文件(system@framework@boot.art)和Boot Oat文件(system@framework@boot.oat)拿出来。首先,用二进制编辑工具打开.art文件,一探究竟:


从中我们可以看出,magic code是“art\n”,版本号是“005\0”,Image文件映射到内存中的起始地址是0x60000000,Image的大小是0xA9BDB0,Bitmap的偏移是0xA9C000,大小是0x2A6F8。0xA9C000+0x2A6F8=0xAC66F8,这个值正好是.art文件的大小。


所以.art文件实际就是由Image加上其Bitmap组成。好,我们继续,接下来的0xE566C279是要加载的oat文件的checksum,.oat文件的起始地址是0x60A9C000,结束地址是0x64618000,.oat文件的数据段起始地址是0x60A9D000,结束地址是0x646161A8。所有这些绝对地址在.oat文件中也有记录,让我们用readelf打开.oat文件看看,Program Headers如下:


可以看到,映射到的物理地址强制写到0x60A9C000。再看看oatdata和oatlastword:


可以看到,.oat文件中记录的这些值和.art文件中所记录的是一致的。最后的4个字节为0x60A9BCC0,让我们移步到这个地址,看看有些什么东西:


这块应该就是一个ObjectArray,里面记录了7个Object,可以很轻易的看到,其中记录了oat文件的位置(kOatLocation,第5个对象)。

0 0
原创粉丝点击