编译和链接【四】链接详解

编译和链接【四】链接详解

前言

在我大一的时候, 我使用VC6.0对C语言程序进行编译链接和运行 , 然后我接触了VS, Qt creator等众多IDE, 这些IDE界面友好, 使用方便, 例如我最喜欢的VS,一键编译运行。对于大一的我,不需要了解编译的整个过程就可以运行,这无疑是非常棒的,并且增加了我对编程的兴趣,同时也简化了我后续的软件开发, 我只需要关心业务和功能代码即可。

但是今天, 我不想“逃课了”,欢迎来到我的频道,本系列 将会介绍编译中的一系列细节。

在正式开始之前,我要推荐两本书,一本是《程序员的自我修养》,另一本是《鲸书》,这两本书对编译的整个过程做了非常详细,非常完备的介绍,但是恰恰如此,我想很多时候,很多知识在工作上是用不到的,也许这句话在很多年多的我会反驳,但是站在工作一年的现在,我将会给你介绍,我所了解的编译和链接。

系列文章入口

关注我~持续更新

编译和链接【一】总述

编译和链接【二】预处理

编译和链接【三】编译过程

符号表和重定位表

在链接过程中,符号表和重定位表是非常重要的两个表。在汇编阶段,汇编器会分析汇编语言中各个section的信息,收集各种符号,生成符号表,将符号在section内的偏移地址也填充到符号表里。

使用 readelf -s main.o 查看目标文件的符号表信息

在这里插入图片描述

在符号表里,可以看到许多符号信息,比如符号的地址,类型和占用空间的大小。

符号表本质上一个结构体数组,在Arm平台下,定义在Linux内核的/arch/arm/include/asm/elf.h里

typedef struct elf32_sym
{
    Elf32_word st_name;
    Elf32_Addr st_value;
    Elf32_word st_size;
    unsigned char st_info;
    unsigned cahr st_other;
    Elf32_Half st_shndx;
}

符号的类型主要有:

  • OBJECT:对象类型,一般用来标识变量
  • FUNC:函数
  • FILE:当前目标文件的名称
  • SECTION:代表一个section,用来重定位
  • COMMON:公用块数据对象,是一个全局弱符号,在当前文件中未分配空间
  • TLS:表示该符号对应的变量存储在线程局部存储

在 C/C++中,编译器是是源文件为翻译单元进行编译的,如果在我们的程序中,我们引用了其他文件的函数或者全局变量,那么编译器会不会报错呢?

其实是不会的,只要你在调用之前进行声明,那么编译器就会认为你的这个函数或者全局变量在其他文件中定义,编译阶段是不会报错的,链接器会尝试在其他文件或者库里查找这个符号的具体定义,但是如果此时还没找到,那么就会报连链接错误。

main.cpp:undefined reference to ‘Addr’

编译器在给每个目标文件生成符号表的过程中,如果没用找到符号的定义,那么也会把这些符号搜集在一起并保存到一个单独的符号表中,这个符号表就是重定位符号表

使用 readelf -s main.o 查看目标文件的符号表信息

在这里插入图片描述

在这个表的Type列,类型为NOTYPE属于未定义状态,需要后续填充,同时在main.o中会使用一个重定位表**.rel.text**来记录这些需要重定位的符号。使用readelf查看重定位表和section header table信息

readelf -S main.o # 查看section header table信息

readelf -r main.o # 查看重定位信息

可以看到:

Relocation section '.rela.text' at offset 0x4c0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000004  000200000002 R_X86_64_PC32     0000000000000000 printf - 4
00000000000c  000300000002 R_X86_64_PC32     0000000000000000 puts - 4

我们看到了需要重定位的符号:prin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值