首页 > C/C++ > 从二进制代码来看静态链接本质
2017
09-21

从二进制代码来看静态链接本质

    静态链接大家并不陌生,本文将从二进制代码来分析静态链接的本质。

    首先列出将要静态的链接的两个源文件,它们分别是a.c和b.c,最后链接成功的文件为ab。

    a.c代码如下:

extern int shared;
extern void swap(int * ,int *);

int main(){
    int a = 100;
    swap( &a, &shared );
}

    b.c代码如下:

int shared = 1;

void swap( int* a, int* b )
{
    *a ^= *b ^= *a ^= *b;
}

    首先使用命令gcc -c a.c 和gcc -c b.c 生成可重定位文件a.o和b.o。

    接着使用命令objdump -h a.oobjdump -h b.o来查看可重定位文件的各个基本段。

    分别显示如下:

从二进制代码来看静态链接本质 - 第1张  | 刘建广学习笔记 

                                                     图 1

从二进制代码来看静态链接本质 - 第2张  | 刘建广学习笔记

                                                    图 2

    这里主要注意File off和Size。a.o代码段长度为0x22;b.o代码段为0x4a,数据段为0x4。

    然后使用命令ld a.o b.o -e main -o ab来链接两个可重定位文件。

    使用命令objdump -h ab,得到下图:

从二进制代码来看静态链接本质 - 第3张  | 刘建广学习笔记

                                                    图 3

    此时我们不要关心File off,我们只关心VMA和Size。VMA是进程的虚拟空间,代码段从0x4000e8持续到0x400156,Size为0x6e。数据段从0x6001b0持续到0x6001b4,Size为0x4。

    注意观察图1和图2,a.o的代码段长度为0x22,b.o的代码段长度为0x4a,两个加起来为0x6c,再加上位对齐2位,最后长度为0x6e。数据段也类似。

    我们指导在a.c中shared变量和swap方法没有在该文件中定义,那么二进制代码会怎么处理呢?

    使用objdump -d a.o,来查看:

从二进制代码来看静态链接本质 - 第4张  | 刘建广学习笔记

                                                   图 4

    13偏移处,be后面00000000表示的是shared变量的地址,由于此时还没有链接,所以使用默认值00000000,很显然是一个假值。

    18偏移处,e8后面00000000表示的是swap函数的地址,由于此时还没有链接,所以使用默认值00000000,很显然是一个假值。

    同样使用命令objdump -d b.o,来查看:

从二进制代码来看静态链接本质 - 第5张  | 刘建广学习笔记

                                               图 5

    这个函数没有需要重定位的函数和变量。

    我们使用objdump -d ab,来查看链接后的文件ab:

从二进制代码来看静态链接本质 - 第6张  | 刘建广学习笔记

                                                    图 6

    为了代码对齐,在main函数后面多了两条空指令,所以ab的长度是a.o和b.o长度之和再加上2。

    我们观察到0x4000fb处be后面的数据已经不是前面的0x00000000,而是0x6001b0,我们知道这个数据表示shared变量的地址,为什么是这个值呢?请看图3,数据段的起始位置是0x6001b0,shared是唯一个变量,所以0x6001b0就是shared变量的地址。

    在0x400103处e8后面的数据也已经不是前面的0x00000000,而是0x00000004。请看图3或者图6,代码段起始位置为0x4000e8,swap函数的地址为0x40010c。那么e8后面为什么是0x00000004呢?因为call转到的真正地址是call下一条指令地址0x400108+0x4,最后的真正的地址为0x40010c,正好是swap的地址。

    转自:http://blog.csdn.net/jltxgcy/article/details/39177095

最后编辑:
作者:liujg
真实-不弄虚,不做假,做自己,不违心; 踏实-不浮躁,不盲从,不急功,不近利; 实学-不投机,不取巧,勤于学,精于业。