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

可以通过阅读代码来帮助分析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@[email protected])和Boot Oat文件(system@[email protected])拿出来。首先,用二进制编辑工具打开.art文件,一探究竟:

Android ART运行环境下Image文件格式简析_第1张图片

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

Android ART运行环境下Image文件格式简析_第2张图片

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


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


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

Android ART运行环境下Image文件格式简析_第3张图片

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

你可能感兴趣的:(android,二进制,image,Art)