- 概述
MIPS平台中动态库的装载与解析原理,网上资料并不多,而且很多讲解都是错误的,甚至MIPS宝书《see mips run》中也没有提供详细的方案。因此本人只好通过代码走读和运行验证的方法来详细了解其原理。之所以要了解mips动态符号的解析调用,是因为之前在实现mips backtrace时,对一些调整gp的指令存在疑惑,顾而深入研究一下。
先上结论:MIPS动态库中的外部符号调用,是依赖.got段和.MIPS.stubs段来共同实现的。
.got中保存着外部符号的地址,但由于采用了延迟绑定技术,某外部符号在第一次被调用前,其地址是未知的,ld.so在装载动态库阶段并没有立刻将外部函数解析并填充到.got中,目的是为了加快启动速度,也是为了不必要的时间浪费,因为在进程运行期间,某些外部符号可能永远都不会被调用到,所以装载阶段解析所有符号是一个浪费时间的行为。
因此,.got中的未决议符号项内,先指向了.MIPS.stubs中的一段指令(每个符号都对应一段单独的指令),这段指令的作用是跳转至符号解析函数_dl_runtime_resolve。
.got段的第一项比较特殊,它保存的符号正是函数"_dl_runtime_resolve",用objdump查看时此项为0,但运行起来之后,会被ld.so填充进_dl_runtime_resolve的地址。
下面简单举例说明。
hello.c:
#include <stdio.h>
#include "hello.h"
int hello(int i)
{
printf("hello %d \n",i);
return 0;
}
main.c:
#include <stdio.h>
#include "hello.h"
int main(int argc, char** argv)
{
int i = 0;
hello(i);
i++;
hello(i);
return 0;
}
mipsel-linux-gcc hello.c -g -fPIC -rdynamic -fasynchronous-unwind-tables -shared -o libhello.so
mipsel-linux-gcc main.c -g -fPIC -rdynamic -fasynchronous-unwind-tables -L./ -lhello -o main.elf
- 流程图
- main首次调用hello

最低0.47元/天 解锁文章
1622

被折叠的 条评论
为什么被折叠?



