-
-
[分享]linker详解
-
发表于: 2天前 598
-
加载
以安卓4.4为例,从system.loadlibrary入手

进入doLoad方法



LoadNativeLibrary只截取关键部分

在LoadNativeLibrary中执行了JNI_OnLoad函数

继续往下分析dlopen



find_library_internal是去找已经加载过的so文件,第一次加载走load_library



先看ReadElfHeader

看看header_是什么

就是ElfHeader结构体

然后看VerifyElfHeader,就是在验证ElfHeader

然后看ReadProgramHeader

下面是Elf32_Phdr的定义

先看一下PAGE_START PAGE_END PAGE_OFFSET的实现


PAGE_SIZE: (1<<12)-1=4095=0x00000fff
PAGE_MASK :PAGE_SIZE取反,那就是0xfffff000(32位)
PAGE_START是获取当前地址所在页的起始地址,比如x=0x12345678,那么PAGE_START就是0x12345000
PAGE_END是获取当前地址所在页的下一页的起始地址,而非页内最后一个字节,比如x=0x12345678,那么PAGE_END就是0x12346000
然后看ReserveAddressSpace,主要看phdr_table_get_load_size,还有load_bias

先解释load_bias,他是实际地址(start)与期望地址(addr)的差值。比如说,addr=0x1000, start=0x5000, 然后我们现在需要找到elf文件中某个地址0x1050(他是绝对地址),那么0x1050相对于addr的偏移就是0x50,在真实内存中的地址就是0x1050+(0x5000-0x1000)
写了注释的phdr_table_get_load_size



然后看LoadSegments


然后看FindPhdr


CheckPhdr函数如下

然后回到load_library

elf_reader.load_start以及下面几个函数

phdr_num_

load_start_

load_size_

load_bias_

然后再往前回到find_library_internal

往下就进入到了soinfo_link_image
链接
先分析phdr_table_get_dynamic_section


经过phdr_table_get_dynamic_section函数后,si->dynamic就指向了elf文件的程序头表中p_type=PT_DYNAMIC的元素

再分析soinfo_link_image,主要看第五步,和soinfo_relocate函数









第五步的话就是si->strtab+d->d_un.d_val;


假设si->strtab=0x2d4c4, d->d_un.d_val=0x5c620, 那么si->strtab+d->d_un.d_val=0x89ae4。去elf中可以找到

再看soinfo_relocate






