首页
社区
课程
招聘
让glibc函数按自己的逻辑执行,原来这么容易!
发表于: 2020-1-3 18:33 6426

让glibc函数按自己的逻辑执行,原来这么容易!

2020-1-3 18:33
6426
之前一直听说函数是强符号,而且我也理所当然的像下面这样理解,所以也就信了:
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直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 10861
活跃值: (4482)
能力值: ( LV12,RANK:404 )
在线值:
发帖
回帖
粉丝
2

同名函数及链接过程https://www.it610.com/article/5227739.htm


最后你只是调用了自己定义的函数 void*malloc(size_tsize) ,glibc运行库不受影响,其他作用域内仍是隐式使用运行库。
《程序员的自我修养:链接、装载与库》 这本书有介绍很多链接的知识。
2020-1-4 12:46
0
游客
登录 | 注册 方可回帖
返回
//