### So文件抽取及加载器实现 #### 一、前言 在深入了解So文件(共享对象文件)及其加载机制的过程中,Thomas King通过这篇文章分享了他对So文件格式和链接器(linker)的研究成果,并在此基础上实现了So文件的抽取及加载器。这一实践不仅有助于深入理解So文件的工作原理,而且为开发自定义加载器提供了实用的参考。 #### 二、So文件抽取 ##### 1. 文件格式定义 为了实现So文件的抽取,作者首先定义了一个简化的文件格式。这种简化主要体现在保留与指令集相关的结构,同时避免涉及与特定平台相关的指令集重定位等问题。下面详细介绍这一文件格式的主要组成部分: - **魔术数**:文件头部分的魔法数字用于标识文件类型,这里使用`"MELF"`作为标志。 - **文件大小与内存大小**:`e_filesz`表示文件实际大小,而`e_memsz`则表示包含bss段在内的文件在内存中的总大小。 - **动态段信息**:`e_DYNvaddr`和`e_DYNnum`分别表示动态段的虚拟地址和大小,这有助于在加载时正确解析动态段。 - **EXIDX信息**:对于ARM平台,`e_EDXvaddr`和`e_EDXnum`分别表示EXIDX(Exported Index)段的虚拟地址和大小,这有助于实现跨平台兼容性。 - **符号表与字符串表**:`strtab`和`symtab`保持原样,但只保留依赖的So文件名和导出的符号名称,以减少文件大小。 - **重定位表**:将原来的`rel`表中的导入符号整合到`plt.rel`表中,后者记录了需要重定位的地址和依赖库的索引。 ##### 2. So文件抽取 抽取过程中,作者特别关注了符号表(symtab)的处理,其中包含了大量以`_`和`__`开头的系统自动生成的导出符号。这些符号并非用户定义,因此在抽取时会被过滤掉。这一做法不仅可以减小最终文件的大小,还有助于提高加载效率。 - **符号过滤**:在提取过程中,通过对symtab进行筛选,去除不必要的系统符号,只保留用户定义的导出符号。 - **字符串表更新**:同时,对strtab进行相应更新,以确保符号名称的完整性和正确性。 - **预重定位**:在抽取时就进行了预重定位处理,这样在加载时只需将依赖库的基地址加到已知的偏移量上即可完成重定位,简化了加载过程。 #### 三、加载器实现 在完成了So文件的抽取之后,下一步是实现一个简易的加载器。该加载器的主要功能是将抽取后的So文件加载到内存中,并确保所有必要的重定位工作正确完成。 - **加载流程**: - 加载So文件到内存。 - 解析动态段信息,确定各个段的虚拟地址。 - 使用`dlsym`等函数解析符号表,确保正确的符号引用。 - 对所有需要重定位的地方进行处理,包括使用预重定位的方法简化这一过程。 - **加载器特点**: - 简化了So文件的结构,只保留了必要的信息。 - 实现了高效的符号解析和重定位。 - 支持跨平台兼容性,尤其是通过保留EXIDX段的信息。 #### 四、结论 通过本文的学习,我们可以了解到So文件抽取及加载器实现的具体步骤和技术细节。这一实践不仅有助于理解So文件的工作原理,也为开发自定义加载器提供了宝贵的经验。此外,对于希望深入研究操作系统或编程语言实现的开发者来说,这是一次非常有价值的学习经历。需要注意的是,虽然文中提到的方法具有一定的局限性(例如预重定位方法依赖于目标设备),但它们为探索更高级的技术和解决方案提供了一个良好的起点。
- 粉丝: 32
- 资源: 93
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助