risc-V学习日记(3):编译与链接

早上好啊,大伙。这个专栏的内容基本就是做笔记,只是给我自己和大伙再学习之后如果忘记哪些内容可以很快的来查看,还是建议大伙去看汪辰老师的视频,老师讲的还是很好的。

文章目录

GCC

GCC简介

由 GNU开发的,遵循 GPL许可证发行的编译器套件。

GCC(GNU Compiler Collection)是Linux系统中最著名的开源编译器套件,支持C、C++、Objective-C、Fortran、Ada等多种编程语言。这个始于1987年的编译器项目,如今已成为开发者构建项目的核心工具链。

为什么说GCC是程序员的必备工具?

跨平台支持:可在Windows/Mac/Linux等系统使用

高度优化:支持-O1到-O3多级代码优化

灵活扩展:可搭配Makefile实现自动化构建

调试友好:生成带调试信息的可执行文件

GCC命令格式

c 复制代码
gcc [ options ] [ filenames ]  
常用选项 含义
-E 只做预处理
-c 只编译不链接,生成目标文件".o"
-S 生成汇编代码
-o file 把输出生成到由 file 指定文件名的文件中
-g 在输出的文件中加入支持调试的信息
-v 显示输出详细的命令执行过程信息

GCC的主要执行步骤

  1. 编译

    编译器完成"预处理"和"编译"'预处理"指处理源文件中以"#"开头的预处理指令,譬如 #include、#define 等"编译" 则针对预处理的结果进行一系列的词法分析、请语法分析、语义分析,优化后生成汇编指令,存放在 .o 为后缀的目标文件中。

  2. 汇编(as)

    汇编器将汇编语言代码转换为机器(CPU)可以执行的指令。

  3. 链接(ld)

    链接器将汇编器生成的目标文件和一些标准库(譬如 libc)文件组合,形成最终可执行的应用程序。

我们这里写一个 .c 文件,然后让它编译一下,给大伙看看它的运行经历了哪些事情。

就写一个梦的开始来做样例吧~

在前面说过gcc 加上选项 -v 就能返回执行过程。

bash 复制代码
gcc hello.c -v

如果大家是第一次使用gcc这个指令,它会说没有这个指令,大家按照它的提示安装一下就行了。

解析一下它的执行流程

预处理和编译,这里就是生成的一个.s的临时文件。

然后再把这个.s的临时文件,执行as指令,生成一个包含机器码的.o文件。

最后,它会调用collect2,它会引用很多文件,才能生成最后的可执行文件。

GCC涉及的文件类型

后缀 文件类型
.c:C 源文件
.cc/.cxx/.cpp C++ 源文件
.i 经过预处理的C 源文件
.s/.S 汇编语言源文件
.h 头(header)文件
.o 目标(object)文件
.a/.so 编译后的静态库(archive)文件和共享(shared object)文件
a.out 可执行文件

ELF

ELF简介

ELF(Executable and Linkable Format)是Linux系统的标准二进制文件格式,堪称可执行文件的"DNA"。无论是我们编译生成的a.out,还是系统级的glibc.so,甚至是内核模块.ko文件,都采用这种统一的文件结构。

ELF的三重身份:

可执行文件:可以直接运行的独立程序

共享目标文件:.so动态链接库

可重定位文件:.o中间目标文件

ELF 文件类型 说明 实例
可重定位文件(Relocatable File) 内容包含了代码和数据,可以被链接成可执行文件或共享目标文件。 Linux 上的 .o文件
可执行文件(Executable File) 可以直接执行的程序 Linux 上的a.out
共享目标文件(Shared Object File) 内容包含了代码和数据,可以作为链接器的输入,在链接阶段和其他的 Relocatable File或者 Shared Object File一起链接成新的 Obiect File;或者在运行阶段,作为动态链接器的输入,和 Executable File 结合,作为进程的一部分来运行 Linux 上的 .so
核心转储文件(Core Dump File) 进程意外终止时,系统可以将该进程的部分内容和终止时的其他状态信息保存到该文件中以供调试分析 Linux上的core 文件

文件格式

文件头(ELF Header)

使用readelf -h查看文件头信息,包含以下关键字段:

字段 说明 典型值示例
Magic Number 文件标识(7F 45 4C 46) 7F 45 4C 46
Class 32/64位架构 ELF64
Type 文件类型(EXEC/DYN/REL) DYN (Position-Independent Executable)
Entry point address 程序入口地址 0x400520
Start of program headers 程序头表偏移 64
Start of section headers 节头表偏移 13912

核心数据段

程序头表(Program Header Table)
  1. 描述段(Segment)信息,用于程序执行
  2. 查看命令:readelf -l
段类型 作用说明
LOAD 需要加载到内存的段
DYNAMIC 动态链接信息
INTERP 指定动态链接器路径
节头表(Section Header Table)
  1. 描述节(Section)信息,用于链接和调试
  2. 查看命令:readelf -S
关键节 功能说明
.text 代码段(机器指令)
.data 已初始化的全局变量
.bss 未初始化的全局变量
.rodata 只读数据(字符串常量等)
.symtab 符号表
.strtab 字符串表

动态链接相关结构

  1. .dynamic段:记录依赖的共享库
  2. .got(全局偏移表):支持位置无关代码
  3. .plt(过程链接表):实现延迟绑定
bash 复制代码
# 查看动态段信息
readelf -d /usr/bin/ls

# 输出示例:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

文件处理相关工具:Binutils

网址:Binutils

ar:归档文件,将多个文件打包成一个大文件。

as:被 gcc 调用,输入汇编文件,输出目标文件供链接器 ld 连接。

ld:GNU 链接器。被 gcc 调用,它把目标文件和各种库文件结合在一起,重定位数据,并链接符号引用。

objcopy:执行文件格式转换。

objdump:显示 ELF 文件的信息

readelf:显示更多 ELF 格式文件的信息(包DWARF 调试信息)

例如说下面用 readelf 命令查看头 ------

感谢大伙观看,别忘了三连支持一下

大家也可以关注一下我的其它专栏,同样精彩喔~

下期见咯~

相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习
im_AMBER3 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J3 天前
从“Hello World“ 开始 C++
c语言·c++·学习