首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Android安全
发新帖
5
37
[原创]编译和链接、装载过程
发表于: 2025-12-6 15:27
2203
[原创]编译和链接、装载过程
卡卡骨
2025-12-6 15:27
2203
平常开发中,很少会关注到编译和链接过程,因为通常的开发环境都是流行的集成开发环境(`IDE`),比如`pycharm, visual studio`,这些`ide`通常讲编译和链接过程一步完成了,通常将这种编译和链接合并到一起的过程称为**构建**(`Build`) --- # 被隐藏的进程 ```C #include <stdio.h> int main(){ printf("Hello Workd\n"); return 0; } ``` 但我们使用gcc编译这个程序的时候,事实上其中被隐藏了多个过程 ```Bash gcc hello.c ``` 被隐藏的包括这么几个过程 - 预处理(预编译)(`prepressing`) - 编译(`compilation`) - 汇编(`assembly`): 将汇编代码转为机器可执行的指令,只要对照汇编指令和机器指令的对照表一一翻译就可以了 - 链接(`linking`) 9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8X3k6Z5z5h3!0K6h3e0M7&6d9p5&6X3M7r3E0*7z5h3S2j5N6W2k6q4N6@1u0Q4x3V1k6A6L8h3q4Y4k6g2)9J5k6i4m8F1k6#2)9K6c8X3q4#2N6r3S2Q4y4h3k6C8k6i4W2Q4x3@1b7I4y4K6j5#2x3o6l9@1z5e0R3^5i4K6u0V1y4g2q4G2N6s2c8S2h3h3!0G2b7h3c8z5N6K6W2W2c8@1N6f1e0h3u0^5g2g2)9J5k6o6m8Q4x3X3b7%4y4h3k6X3k6U0S2S2y4o6k6U0j5X3q4W2y4$3t1J5z5o6t1&6z5e0q4S2x3o6V1H3y4h3c8T1k6h3c8S2y4#2)9J5z5b7`.`.</mark> ### 预编译 & 编译 预编译过程: 主要就是处理哪些源代码中以“`#`”开始的预编译指令,比如 “`#include`” 编译过程,就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分之一 现在版本的`GCC`将预编译和编译两个步骤合并成了一个步骤 # 编译器做了什么 > 从最直观的角度来看,编译器就是将高级语言翻译成机器语言的一个工具 #### 编译过程: - 扫描 - 语法分析 - 语义分析 - 源代码优化 - 代码生成和目标代码优化 # 模块拼装-静态链接 程序设计的模块化是人们一直在追求的目标,因为当一个系统十分复杂的时候,我们不得不将一个复杂的系统逐步分割成小的系统,以达到各个突破的目的。 一个复杂的软件也如此,人们把每个源代码模块独立地编译,然后按照需要将他们拼装起来,这个组装模块的过程就是链接(`Linking`) 比如说: 我们在程序模块`main.c`中使用了另一个模块`func.c`的`foo()`函数 我们在`main.c`模块中每一处调用`foo`的时候都必须要确切的知道`foo`这个函数的地址 但是由于每个模块都是单独编译的,在编译器编译`main.c`的时候,它并不知道`foo`函数的地址,所以它暂时性把这些调用`foo`的指令的目标地址搁置, 等到最后链接的时候由链接器去将这些指令的目标地址进行修正。 --- # 目标文件(Linux - ELF / window - PE) ELF文件介绍 ## 目标文件长什么样子 目标文件中包括 - 编译后的机器指令代码、数据 - 链接时所需要的符号表,调试信息,字符串等 一般目标文件将这些信息按不同的属性,以“节(`Section`)”的形式存储,有时候也叫做“段(`Segment`)” 节、段 ,这两个 一般情况下都表示一个一定长度的区域,基本上不加以区别,唯一的区别是再`ELF`的链接视图和转载视图的时候 |||| |-|-|-| |`.code` / `.text`|程序源代码编译后的机器指令常被放在**代码段**|| |`.data`|全局变量和局部静态变量数据经常放在**数据段**|| |`.bss`|`.bss`段为 未初始化的全局变量和局部静态变量预留位置,它没有内容 ,不占用空间|| |`.rodata`|`Read Only Data`, 存放只读数据,比如字符串常量,全局`const`变量|| |`.comment`|存放的是编译器版本信息,比如字符串:“`GCC:(GNU)4.2.0`”|| |`.debug`|调试信息|| |`.dynamic`|动态链接信息|| |`.hash`|符号哈希表|| |`.line`|调试时的行号表|| |`.note`|额外的编译器信息|| |`.strtab`|`String Table` 字符串表, 用于存储`ELF`文件中用到的各种字符串|| |`.symtab`|`Symbol Table` 符号表|| |`.shstrtab`|`Section String Table`段名表|| |`.plt` `.got`|动态链接的跳转表和全局入口表|| |`.init` `.fini`|程序初始化与终结代码段|| ## ELF文件结构描述 !<a href="elink@eaaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6k6h3y4#2M7X3f1J5i4K6u0W2N6$3!0K6N6r3q4@1K9h3y4Q4x3X3g2U0L8W2)9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8X3S2V1e0e0f1&6k6e0c8T1z5p5N6Z5f1p5#2@1c8@1@1#2z5i4q4k6K9Y4k6Q4x3V1k6A6L8h3q4Y4k6g2)9J5k6i4m8F1k6#2)9K6c8X3q4#2N6r3S2Q4y4h3k6C8k6i4W2Q4x3@1b7I4y4K6j5#2x3o6l9#2x3U0j5K6i4K6u0V1N6$3y4h3h3s2S2f1c8Y4V1J5k6W2S2W2c8V1S2J5M7V1I4X3z5o6g2K6c8W2)9J5k6o6m8Q4x3X3c8V1j5e0M7^5k6e0W2W2x3$3j5#2k6e0t1#2y4o6S2W2j5U0b7$3y4o6l9H3y4o6x3#2j5e0q4V1z5h3x3J5y4b7`.`.">省去了ELF一些繁琐的结构</a> ### 文件头 9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8X3A6J5z5h3y4o6k6i4m8v1N6h3W2e0k6r3k6U0k6f1c8K9g2X3#2y4k6o6N6Q4x3V1k6A6L8h3q4Y4k6g2)9J5k6i4m8F1k6#2)9J5z5b7`.`.</mark> - `ELF`文件头结构成员含义 9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8W2R3%4y4$3p5&6z5r3t1I4k6W2W2U0b7#2t1#2P5o6W2m8c8%4k6n7d9q4)9J5c8X3W2E0j5h3N6W2i4K6u0W2M7r3&6Y4i4K6t1&6</mark> ### 段表(Section Header Table) 段表描述了`ELF`的各个段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限以及段的其他属性 `ELF`文件的段结构就是由段表决定的,编译器、链接器和装载器都是依赖段表来定位和访问各个段的属性的 9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8U0g2Y4e0X3V1$3K9U0M7K6d9q4l9K6L8g2y4n7N6X3k6Y4P5g2A6s2e0W2S2Q4x3V1k6A6L8h3q4Y4k6g2)9J5k6i4m8F1k6#2)9J5z5b7`.`.</mark> 只有分析`ELF文件头`,就可以得到`段表`和`段表字符串表`的位置,从而解析整个`ELF`文件 --- # 链接的接口 - 符号 在链接中,我们将函数和变量统称为**符号**(`Symbol`),函数名和变量名就是 **符号名**(`Symbol Name`) 链接过程中很关键的一部分就是符号的管理,每一个目标文件都会有一个相应的符号表(`Symbol Table`), 这个表里记录了目标文件中所用到的所有符号。每个定义的符号有一个对应的值,叫做**符号值**(`Symbol Value`),对于变量和函数来说,符号值就是他们的地址。 9J5c8Y4y4@1j5i4c8A6j5#2)9J5c8X3S2V1y4f1f1K6k6V1@1@1d9X3#2p5c8Y4m8J5x3V1E0i4z5i4W2%4N6@1A6Q4x3V1k6A6L8h3q4Y4k6g2)9J5k6i4m8F1k6#2)9K6c8X3q4#2N6r3S2Q4y4h3k6C8k6i4W2Q4x3@1b7I4y4K6j5#2x3o6l9#2x3e0j5%4i4K6u0V1K9s2A6g2g2@1k6W2f1h3N6f1b7$3E0x3y4f1M7K6g2o6g2i4d9r3!0X3f1q4)9J5k6o6m8Q4x3X3b7$3y4h3j5H3k6o6S2U0y4o6x3$3y4$3j5I4y4X3k6U0z5r3p5J5z5h3b7@1x3K6p5K6y4U0j5&6y4o6y4T1k6g2)9J5z5b7`.`.</mark> --- # 可执行文件的装载与进程 可执行文件只有转载到内存以后才能被`CPU`执行。 ## 进程的建立 我们就来看看这种最通常的情形:创建一个进程,然后装载相应的可执行文件并且执行。 那么在有虚拟存储的情况下,上述过程最开始只需要做三件事情: - 创建一个独立的虚拟地址空间。 - 读取可执行文件头,并建立虚拟空间与可执行文件的映射关系。 - 将`CPU`的指令寄存器设置成可执行文件的入口地址,启动运行。 --- # 动态链接 ## 为什么要有动态链接 一个主要的原因就是,静态链接存在浪费内存和磁盘空间、模块更新困难等问题 而动态链接能解决这些问题 ## 动态链接的基本思想 要解决空间浪费和更新困难这两个问题最简单的办法就是把程序的模块相互分割开来,形成独立的文件,而不再将它们静态地链接在一起。 简单来说,就是不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。 也就是说,把链接这个过程推迟到了运行时再进行,这就是**动态链接**的基本思想
回复或点赞可查看完整内容
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
#基础理论
收藏
・
5
点赞
・
37
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
git_51951meggadf3df
非常支持你的观点!
2026-9-11 10:29
mb_sicsragt
你的帖子非常有用,感谢分享!
2026-8-22 14:15
mb_lthgjpwj
为你点赞!
2026-8-20 17:28
Wika
感谢你分享这么好的资源!
2026-8-8 16:09
mb_wsoacceo
为你点赞!
2026-8-8 01:26
afishlong
你的帖子非常有用,感谢分享!
2026-7-14 04:49
哈哥
感谢你的积极参与,期待更多精彩内容!
2026-2-26 11:10
sleep_Zzz
非常支持你的观点!
2026-2-24 11:47
mb_bzlxewmx
谢谢你的细致分析,受益匪浅!
2026-1-20 14:51
wx_清风明月_799
感谢你分享这么好的资源!
2026-1-20 13:53
SX_DomOne
非常支持你的观点!
2026-1-12 17:57
wangguoguo
为你点赞!
2025-12-30 13:56
alienhe
你的帖子非常有用,感谢分享!
2025-12-25 11:43
whohh
这个讨论对我很有帮助,谢谢!
2025-12-12 20:05
苦瓜.
非常支持你的观点!
2025-12-12 16:45
mb_szqldxer
感谢你分享这么好的资源!
2025-12-12 15:56
npc0vo
谢谢你的细致分析,受益匪浅!
2025-12-11 02:14
梦_魇
感谢你的贡献,论坛因你而更加精彩!
2025-12-9 14:36
passself
为你点赞!
2025-12-8 19:56
Hawcett
期待更多优质内容的分享,论坛有你更精彩!
2025-12-8 14:40
寻影星尘
非常支持你的观点!
2025-12-8 12:16
dob_C
你的分享对大家帮助很大,非常感谢!
2025-12-8 11:50
dofla
你的帖子非常有用,感谢分享!
2025-12-8 11:16
WsttXm
你的帖子非常有用,感谢分享!
2025-12-8 10:25
ONewTach
谢谢你的细致分析,受益匪浅!
2025-12-8 09:18
ldljlzw
期待更多优质内容的分享,论坛有你更精彩!
2025-12-8 08:51
陈可牛
你的分享对大家帮助很大,非常感谢!
2025-12-7 23:41
mb_tmbvnlxt
为你点赞!
2025-12-7 19:44
我的小拇指啊
这个讨论对我很有帮助,谢谢!
2025-12-7 17:32
mb_rjdrqvpa
感谢你的积极参与,期待更多精彩内容!
2025-12-7 13:56
doduhuang
你的分享对大家帮助很大,非常感谢!
2025-12-7 09:52
cxbcxb
你的帖子非常有用,感谢分享!
2025-12-7 09:49
mb_bppcorlj
谢谢你的细致分析,受益匪浅!
2025-12-7 01:41
dxzhang
谢谢你的细致分析,受益匪浅!
2025-12-6 21:18
huangyalei
为你点赞!
2025-12-6 20:20
mb_oowzftna
谢谢你的细致分析,受益匪浅!
2025-12-6 17:12
顽劣
你的帖子非常有用,感谢分享!
2025-12-6 15:51
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
12
)
LQ6H
雪 币:
530
活跃值:
(2622)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
80
粉丝
1
关注
私信
LQ6H
2
楼
666
2025-12-6 16:23
0
wx_插曲
雪 币:
411
活跃值:
(861)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
316
粉丝
24
关注
私信
wx_插曲
3
楼
666
2025-12-6 21:59
0
Heiyiren123
雪 币:
223
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
66
粉丝
1
关注
私信
Heiyiren123
4
楼
感谢分享,很有参考价值!
2025-12-8 03:08
0
bbpk
雪 币:
678
活跃值:
(1552)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
55
粉丝
0
关注
私信
bbpk
5
楼
感谢分享
2025-12-8 08:15
0
GEKEZYX
雪 币:
0
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
154
粉丝
0
关注
私信
GEKEZYX
6
楼
666
2025-12-8 09:47
0
option
雪 币:
9397
活跃值:
(4334)
能力值:
( LV2,RANK:10 )
在线值:
发帖
40
回帖
771
粉丝
4
关注
私信
option
7
楼
学习一下,好像编译器都一样
2025-12-8 10:06
0
__Shinn
雪 币:
2706
活跃值:
(1395)
能力值:
( LV7,RANK:100 )
在线值:
发帖
3
回帖
74
粉丝
66
关注
私信
__Shinn
2
8
楼
感谢分享,很有参考价值!
2025-12-8 10:11
0
勒LI
雪 币:
58
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
74
粉丝
0
关注
私信
勒LI
9
楼
666
2025-12-8 17:25
0
mb_jnmxfjku
雪 币:
109
活跃值:
(765)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
145
粉丝
0
关注
私信
mb_jnmxfjku
10
楼
111
2025-12-9 17:53
0
29o
雪 币:
20
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
83
粉丝
0
关注
私信
29o
11
楼
学习一下
2026-1-19 22:42
0
miredo
雪 币:
0
活跃值:
(1355)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
4
粉丝
0
关注
私信
miredo
12
楼
学习一下
2026-1-20 11:59
0
mb_ggnlrzcs
雪 币:
207
活跃值:
(706)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
97
粉丝
1
关注
私信
mb_ggnlrzcs
13
楼
学习了,感谢分享!
2026-8-22 12:35
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
卡卡骨
4
发帖
1
回帖
20
RANK
关注
私信
他的文章
[原创]编译和链接、装载过程
2203
[原创]入门实战-知乎x-zse-96参数分析
22842
[原创]入门实战-Rui幸app白盒aes
20200
[原创]入门实战-某居客nsign参数分析
1766
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部