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 命令查看头 ------

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

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

下期见咯~

相关推荐
viperrrrrrrrrr73 小时前
大数据学习(96)-Hive面试题
大数据·hive·学习
charlie1145141914 小时前
STM32F103C8T6单片机的起始点:使用GPIO输出点亮我们的第一个小灯(HAL库版本)
stm32·单片机·嵌入式硬件·学习·教程·hal库·gpio
每次的天空5 小时前
Android学习总结之算法篇五(字符串)
android·学习·算法
奕天者6 小时前
C++学习笔记(三十三)——forward_list
c++·笔记·学习
武昌库里写JAVA7 小时前
Golang的消息中间件选型
java·开发语言·spring boot·学习·课程设计
breakloop7 小时前
量化交易从0到1(理论篇)
笔记·学习·量化交易
大白的编程日记.8 小时前
【Linux学习笔记】初识进程概念和进程PCB
linux·笔记·学习
每次的天空8 小时前
Flutter学习总结之Android渲染对比
android·学习·flutter
跳跳的向阳花9 小时前
08、Docker学习,常用安装:ClickHouse
学习·clickhouse·docker
2301_813506139 小时前
STP学习
网络·学习