本文学习的源码参考AndroidXRef,版本为Lollipop 5.1.0_r1。
这一节,我们详细讲so的加载过程,也即ElfReader这个类的Load函数:
bool ElfReader::Load(const android_dlextinfo* extinfo) {
return ReadElfHeader() &&
VerifyElfHeader() &&
ReadProgramHeader() &&
ReserveAddressSpace(extinfo) &&
LoadSegments() &&
FindPhdr();
}
很清晰,依次调了这6个函数,我们一个个来看。
ReadElfHeader()
bool ElfReader::ReadElfHeader() {
ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
if (rc < 0) {
DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
return false;
}
if (rc != sizeof(header_)) {
DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
static_cast<size_t>(rc));
return false;
}
return true;
}
ReadElfHeader使用pread64直接从so文件中将ELF的头表读取header_中。
header_ 为ElfReader的成员变量,是Elf32_Ehdr的类型,因此,我们就可以通过header_来获取头表中的任意字段。
VerifyElfHeader()
bool ElfReader::VerifyElfHeader() {
if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
DL_ERR("\"%s\" has bad ELF magic", name_);
return false;
}
// Try to give a clear diagnostic for ELF class mismatches, since they're
// an easy mistake to make during the 32-bit/64-bit transition period.
int elf_class = header_.e_ident[EI_CLASS];
#if defined(__LP64__)
if (elf_class != ELFCLASS64) {
if (elf_class == ELFCLASS32) {
DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
} else {
DL_ERR("\"%s\" has unknown ELF class: %d&#