背景介绍
在学习CSAPP第7章后,了解了有关linking的一些原理。仅就该章内容而言,有许多值得思考和注意的地方。作为一名developer,如果不清楚链接器是如何实现symbol resolution和relocation的,那么总有一天他会在这个问题上栽跟头。
举一个很简单的例子,如果在一个project中多个文件中定义了具有相同name的variable或者function, 会发生什么情况呢?
比如:
//file1.c
int x = 1;
int y = 2;
int main()
{
func();
printf("x = %d\ty = %d\n", x, y);
return 0;
}
//file2.c
double x;
void func()
{
x = 0.0;
}
如果编译、执行上述两个文件,一定会有意外的惊喜发生!
本人花了一个周末从头到尾学习了一遍第7章中的所有内容, 编译、运行了该章节中的所有代码,确实有许多收获! 整个过程较为顺利,只是7.7节中的内容曾一度令我困惑。好在第二天再看一遍后,也能够彻底的理解了。
bug登场
值得一提的是,这里有一个例外:
在学习7.13节Library Interpositioning技术时,前两个Interpositioning(Comiple-time && Link-time)的代码都可以成功运行。其结果也确实表明interpotioning成功! 但是在尝试Run-time Interpositioning时,发生了segment fault.
源码如下:
//mymalloc.c
#ifdef RUNTIME
#define _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>
//malloc wrapper function
void *malloc(size_t size)
{
void *(*mallocp)(size_t size);
char *error;
//printf("trying to get address of libc malloc...\n");
mallocp = dlsym(RTLD_NEXT, "malloc"); //Get address of libc malloc
if((error = dlerror()) != NULL)
{
fputs(error, stderr);
exit(1);
}
//printf("Getting address of libc malloc succeeded.\n");
char *ptr = mallocp(size); //call libc malloc
printf("malloc(%d) = %p\n", (int)size, ptr);
return ptr;
}
//free wrapper function
void free(void *ptr)
{
void (*freep)(void *ptr);
char *error;
if(!ptr)
{
return;
}
freep = dlsym(RTLD_NEXT, "free"); //Get address of libc free
if((error = dlerror()) != NULL)
{
fputs(error, stderr);
exit(1);
}
freep(ptr); //call libc free
printf("freep(%p)\n", ptr);
ptr = NULL; //set ptr to NULL, avoiding bugs resulting from free a pointer twice.
}
#endif
//int.c
#include<stdio.h>
#include<malloc.h>
int main()
{
int *p = (int*)malloc(32);
free(p);
return 0;
}
相应的makefile文件内容为:
intr: int.c
gcc -o -g intr int.c
mymalloc.so: mymalloc.c
gcc -DRUNTIME -shared -fpic -g -o mymalloc.so mymalloc.c -ldl
run: mymalloc.so intr
LD_PRELOAD="./mymalloc.so" ./intr
在shell下运行make run, 其结果为:
make: *** [run] Segmentation fault (core dumped)
为什么会这样? 仔细检查了几遍代码之后,发现代码与书中给出的代码确实一致。 于是只能寄希望于调试分