未命名
空指针调用函数 堆->后插入调整次数
不考虑ASLR的情况
可执行文件装载地址构成 1. 所有可执行文件都是从从固定的虚拟地址开始装载的,因为一般都是第一个装载的文件 2. 程序初始化的工作,负责全局变量的初始化,全局对象的构造函数之类的东西 3. main函数:所有用户代码写的东西都在main函数里执行 4. 程序收尾工作:关闭文件描述符、释放堆内存,执行全局对象的析构函数等。并直接回收整个地址空间(包括代码、数据、堆栈),
静态链接 - 重定位前,未知变量和函数地址会有占位符 - 代码段,数据段会和可执行文件的代码段、数据段合并。形成固定的绝对虚拟地址 - 数据都可以通过绝对地址进行调用(小型数据可以用PC相对寻址) - 函数一般都是PC相对寻址 - PC相对寻址:当前地址+指令大小+到下一个指令的距离。 - (优势:位移量小节省空间,支持程序浮动加载,局部性原理有优化--离得近)
动态链接 分为FPIC和非FPIC(地址无关代码)的:
无FPIC地址无关代码: - 装载时类似于静态链接,但代码段和数据段都不确定,无法做到共享。 - 所有数据和代码都需要重定位绝对地址重定位 - 为什么不能共享?因代码段包含绝对地址引用,无法在进程间共享,且要求代码段可写(运行时重定位)(存在安全风险)
FPIC地址无关代码动态库: - 装载时代码段需要通过PLT/GOT间接重定位到基地址,可以做到代码段共享。 - 动态库内部数据(静态全局变量)和代码可采用PC相对地址去访问 - 代码是PC相对寻址到对应的PLT条目 - 动态库访问外部数据和代码需要用到GOT表进行PC相对寻址 - 为什么能访问数据?其实PC相对寻址找的是GOT表,GOT表与代码段的相对位置是固定的,所以可以PC相对寻址+GOT固定偏移找到,再进行跳转。 - 对于难以区分内外的全局变量,动态库内部维护GOT表去访问。 - 外部调用动态库的代码段也是PC 相对寻址到 PLT 条目,再考虑GOT获取代码段位置。
其他: 常量可以用基址寻址+PC相对寻址获得