-
-
让glibc函数按自己的逻辑执行,原来这么容易!
-
发表于:
2020-1-3 18:33
6425
-
之前一直听说函数是强符号,而且我也理所当然的像下面这样理解,所以也就信了:
extern int g1;
int g2;
int g3 = 0x03030303; // 赋初始值了,为强符号
static int g4;
static int g5 = 0x05050505; // 赋初始值了,为强符号
// 有函数体可以理解为有初始值,而没有函数体的就是函数声明,不是定义,所以按理解,函数一定是强符号
extern void f1();
void f2(); // 声明
void f3() {} // 有函数体,强符号
static void f4(); // 声明
static void f5() {} // 有函数体,强符号
但是之前分析elf的重定位时,明明记得在.c文件中,调用该.c文件本身定义的非static函数,调用处与被调用函数的相对地址,显然在编译阶段就能确定,编译器却并不直接在调用处写上相对地址,而是在.o和.so文件中,都还要留一条重定向,也就意味着还要到后面才会确定该函数的地址。既然想不明白原因,我就顺着现有的情况,做了一个猜测,如下的fun.c和main.c,都定义了
voidfun() 函数,但链接不会报"重复定义"错误,并且肯定是main.c中的fun()会被执行,即使显式指定main.c中的fun()为弱符号。结果和猜测的结果一样:
// fun.c
#include <stdio.h>
void fun()
{
printf("weak\n");
}
void test()
{
fun(); // 这里可能会调用别处的fun()
}
// main.c
#include <stdio.h>
extern void test();
// void __attribute__((weak)) fun()
void fun()
{
printf("force\n");
}
int main()
{
test();
return 0;
}
// gcc -c fun.c main.c -g -Wall
// gcc -shared fun.o -o libfun.so
// gcc main.o -L. -lfun -g -Wall
// 将当前路径添加到/etc/ld.so.conf,并且执行ldconfig
// ./a.out
/*
* 结果:"force"
* main()
* |- test() // 执行main.c中的fun(),而不是fun.c本身的fun()
* |- fun() // 打印"force"
*/
然后我就想,自己的.so这样,glibc会不会也一样,结果确实一样:
#include <stdio.h>
#include <stdlib.h>
//void *__attribute__((weak)) malloc(size_t size)
void *malloc(size_t size)
{
printf("%u..\n", size);
return NULL;
}
// gcc test.c -g -Wall
int main()
{
malloc(100); // 不会跟glibc的malloc()冲突,并且调用的是当前代码自己实现的malloc()函数
return 0;
}
// ./a.out
// 结果:100..
那么也就是说,如果想让glibc中的某个函数,按照自己的逻辑执行,还有比LD_PRELOAD更容易的方法。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课