重定位过程
重定位过程如图,可以参考《ELF格式及加载过程简介》。
SGX的ELF文件重定位过程
原理同上。
这里描述SGX初始化末期通过调用relocate_enclave完成对对ELF文件映射的重定位项进行配置。
API如下
/* By default all symbol is linked as global symbol by link editor. When call global symbol,
* we first call .plt entry. It should have problems if the call goloal symbol when relocation
* is not done.
* Declare relocate_enclave as .hidden is to make it local symbol.
* Since this function is called before relocation is done, we must make
* it local symbol, so the code is like "fce3: e8 98 12 00 00 call 10f80 <relocate_enclave>"
* 0x9812=0x10f80-0xfce8
*/
__attribute__ ((visibility ("hidden")))
int relocate_enclave(void* enclave_base)
这个函数本身是全局不可见的,因为我们此时还没有进行重定位,但是全局符号需要通过plt项来寻找,这就会冲突。
这个函数内部遍历所有的动态段(PT_DYNAMIC),然后对动态段内的每个动态节【ElfW(Dyn)】遍历,将其中的符号表偏移、重定位表偏移、重定位表大小、重定位表项大小、PLT重定位偏移、PLT大小进行记录,其中表的大小除以表项的大小就是表项的个数。
然后调用do_relocs,遍历每一个重定位表项,每一个重定位表项指向一个虚拟空间地址(比如.text节中的某个符号),这里要做的就是将符号表项、PLT项的实际位置都记录到重定位表项所指的虚拟空间地址,这样以后当访问那个虚拟空间地址时候(比如.text节中的某个符号),我们可以很方便的找到重定位的符号、PLT项的具体位置。
#ifdef __x86_64__
/* Relocation for x64 (with addend) */
static int do_relocs(const ElfW(Addr) enclave_base,
ElfW(Addr) rela_offset,
ElfW(Addr) sym_offset,
size_t nr_relocs);
#elif defined(__i386__)
/* Relocation for x86 (without addend) */
static int do_relocs(const ElfW(Addr) enclave_base,
ElfW(Addr) rel_offset,
ElfW(Addr) sym_offset,
size_t nr_relocs);