从零学习开发一个RISC-V操作系统(二)丨GCC编译器和ELF格式
本篇文章的内容
- 一、GCC(GUN Compiler Collection)
- 1.1 GCC的命令格式
- 1.2 GCC的主要执行步骤
- 1.3 GCC涉及的文件类型
- 二、ELF简介
- 2.1 ELF文件格式图
- 2.2 ELF文件处理的相关工具
- 2.3 练习
本系列是博主参考B站课程学习开发一个RISC-V的操作系统的学习笔记,计划从RISC-V的底层汇编指令学起,结合C语言,在Ubuntu 20.04上开发一个简易的操作系统。一个目的是通过实践操作学习和了解什么是操作系统,第二个目的是为之后学习RISC-V的集成电路设计打下一定基础。本系列持续不定期更新,分享出来和大家一同交流进步。
博主是微电子科学与工程专业的学生,对软件和操作系统难免有理解不到位的地方。如有谬误敬请不吝告知,不胜感激。
参考课程及文章:
【Bilibili】[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春
一、GCC(GUN Compiler Collection)
GCC是一个由GNU(一个自由软件基金会组织)开发的,遵循GPL许可证发行的编译器套件,是一个编译器的集合。支持 C、C++、Objective-C、Fortran、Ada 和 Go 语言等多种语言前端,已被移植到多种计算机体系架构上,如 x86、ARM、RISC-V 等。在之后的课程中使用的也是GCC作为编译工具。GCC 的初衷是为 GNU 操作系统专门编写一款编译器,现已被大多数 “Unix-like”操作系统(如 Linux、BSD、MacOS 等)采纳为标准的编译器。
1.1 GCC的命令格式
- GCC
操作选项
文件名
常用操作选项 | 含义 |
---|---|
-E | 只做预处理(将包含的宏语言头文件转化为C语言文件) |
-c | 只编译(生成机器指令)不链接(与库文件相连),生成目标文件.o |
-S | 生成汇编代码 |
-o file | 将输出的文件生成到由file 指定文件名的文件中 |
-g | 在输出的文件中加入支持调试的信息 |
-v | 显示输出详细的命令执行过程信息 |
1.2 GCC的主要执行步骤
- 编译
编译(使用cc1程序,这里针对 C 语言,不同的语言有自己的编译器):编译器完成 “预处理” 和 “编译”,“预处理” 指处理源文件中以 “#” 开头的预处理指令,譬如 #include、#define 等;“编译” 则针对预处理的结果进行一系列的词法分析、语法分析、语义分析,优化后生成汇编指令,存放在 .o 为后缀的目标文件中。
- 汇编
汇编(使用as程序):汇编器将汇编语言代码转换为机器(CPU)可以执行的指令。
- 链接
链接(使用ld程序):链接器将汇编器生成的目标文件和一些标准库(譬如 libc)的.o
文件组合,形成最终可执行的应用程序。
1.3 GCC涉及的文件类型
.c
:C 源文件.cc/.cxx/.cpp
:C++ 源文件.i
:经过预处理的 C 源文件.s/.S:汇编语言源文件(
.S文件中还包含宏指令,
.s`文件中是纯汇编指令).h
:头(header)文件.o
:目标(object)文件.a/.so
:编译后的静态库(archive)文件和共享库(shared object)文件a.out
:可执行文件,常见于Unix系统
二、ELF简介
ELF(Executable Linkable Format)是一种 Unix-like系统上的二进制文件格式标准。ELF文件格式对于底层的操作系统开发非常重要,当程序需要在底层进行优化,调试,排错等操作时,ELF文件可以更好地帮助程序员完成任务。ELF 标准中定义的采用 ELF 格式的文件分为以下4类:
2.1 ELF文件格式图
ELF格式是在程序编译链接过程中生成的文件采用的通用格式。如果直接用文本编辑器或二进制编辑器打开该文件,无法直接看出文件中包含的信息,因为该文件是用二进制书写的。但是其中每一个字节都有其特定的含义,这些字节的排布遵从ELF文件格式。ELF文件中最主要的部分包括ELF文件头(ELF Header)、程序头表(Program Header Table)和节头表(Section Header Table)。
ELF文件头(ELF Header)中包含了该文件的一些基本信息,例如该文件运行在哪种体系架构上,运行的版本号等。
ELF文件的主体部分是多个程序节(Section)。如上图所示,.text
中一般存放指令(程序的具体操作),.init
中一般存放一些初始化操作,.data
中存放程序要操作的数据,例如在程序中定义的全局变量等。
在程序加载到内存前,一般都要对各个节进行对齐操作。例如,当程序按4KB进行分节时,如果.test
节中的内容本身很少,且不加任何操作,它就会按4KB的大小独占一部分区域。为了节省内存空间,我们对各个节的内容按属性进行归并,例如.text
和.init
都存放了一些程序运行的指令,所以我们可以对齐进行归并,形成了程序段(Segment)。一个程序段可以由多个程序节构成。
ELF程序头表(Program Header Table)从运行角度描述了程序的内容,它是程序运行视图的体现。程序头表中包含了该文件中哪几个节要归并成一个段,每一个段占用的大小,入口地址等信息。其中包含的信息只有在运行时才会用到。
ELF节头表(Section Header Table)中存放的该文件中包含的节的信息,包括节的名称,节的入口地址,节的大小等。节头表从链接的角度描述了程序的内容,它是程序链接视图的体现。其中的信息只有链接时才会用到。
2.2 ELF文件处理的相关工具
对程序员而言,手动查看和调试ELF文件的过程是十分繁琐的,GNU为程序员提供了相关的处理工具软件,存放在Binutils工具包中。该工具包中的小程序如下:
- ar:归档文件,将多个文件打包成一个大文件。
- as:被 gcc 调用,输入汇编文件,输出目标文件供链接器 ld 连接。
- ld:GNU 链接器。被 gcc 调用,它把目标文件和各种库文件结合在一起,重定位数据,并链接符号引用。
- objcopy:执行文件格式转换。
- objdump:显示 ELF 文件的信息。
- readelf:显示更多 ELF 格式文件的信息(包括DWARF 调试信息)。
- …
2.3 练习
使用gcc编译代码并使用Binutlis工具对生成的目标文件和可执行文件(ELF格式)进行分析,具体要求如下:
- 编写一个简单的打印“Hello world!”的程序源文件
hello.c
- 对源文件进行本地编译,生成针对支持x86_64指令集架构处理器的目标文件
hello.o
- 查看
hello.o
的文件的ELF文件头信息- 查看
hello.o
的节头表- 对
hello.o
进行反汇编,并查看hello.c
的程序源码和机器指令的对应关系
首先,在Vim编辑器中编写一个简单的hello.c
程序:
如果我们需要hello.o
文件,说明只需要编译,不需要链接,所以在终端中输入如下代码:
$ gcc -c hello.c -o hello.o
查看hello.o
文件中ELF文件头信息(-h
就表示查看文件头header):
$ readelf -h hello.o
查看hello.o
的节头表(-SW
表示显示节头表,并展宽表示):
$ readelf -SW hello.o
要对文件进行反汇编,首先要重新编译程序,并使用gdb使其携带调试信息,之后使用objdump
对程序hello.o
进行反汇编。可以看到每一条C语句对应的汇编指令,可以利用该工具对程序进行调试和优化。
$ rm hello.o
$ gcc -g -c hello.c
$ objdump -S hello.o
原创笔记,码字不易,欢迎点赞,收藏~ 如有谬误敬请在评论区不吝告知,感激不尽!博主将持续更新有关嵌入式开发、机器学习方面的学习笔记。
相关文章:

从零学习开发一个RISC-V操作系统(二)丨GCC编译器和ELF格式
本篇文章的内容 一、GCC(GUN Compiler Collection)1.1 GCC的命令格式1.2 GCC的主要执行步骤1.3 GCC涉及的文件类型 二、ELF简介2.1 ELF文件格式图2.2 ELF文件处理的相关工具2.3 练习 本系列是博主参考B站课程学习开发一个RISC-V的操作系统的学习笔记&…...

论文阅读_大语言模型_Llama2
英文名称: Llama 2: Open Foundation and Fine-Tuned Chat Models 中文名称: Llama 2:开源的基础模型和微调的聊天模型 文章: http://arxiv.org/abs/2307.09288 代码: https://github.com/facebookresearch/llama 作者: Hugo Touvron 日期: 2023-07-19 引用次数: 11…...

当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析
生态系统服务是人类从自然界中获得的直接或间接惠益,可分为供给服务、文化服务、调节服务和支持服务4类,对提升人类福祉具有重大意义,且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目(Millennium Ecosystem Asse…...
k8s Limits 限制内存
Limits 限制内存 在 Kubernetes (K8s) 中,可以使用 Limits(资源限制)来限制 Pod(容器)使用的内存数量。此处的 Limits 表示 Pod 在 K8s 集群中可用的最大内存量。一旦 Pod 内存使用超过这个限制,可能会触发…...

单片机第三季-第三课:STM32开发板原理图、配置、浮点运算单元
目录 1,开发板原理图 2,浮点运算单元(FPU) 1,开发板原理图 课程视频比较早,介绍了三款开发板。观看视频时用的开发板说和51单片机共板的STM32核心板,将51单片机从底座拆下来后,安…...
观察者模式 发布-订阅模式(设计模式与开发实践 P8)
文章目录 观察者模式运用实现 观察者模式 定义:他用来定义对象之间一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖他的对象都会得到通知 运用 如果我们使用过 DOM 上的事件函数,那就接触过观察者模式 document.body…...

【日常业务开发】Java实现异步编程
【日常业务开发】Java实现异步编程 Java实现异步编程什么是异步异步的八种实现方式异步编程线程异步Future异步CompletableFuture实现异步Spring的Async异步Spring ApplicationEvent事件实现异步消息队列ThreadUtil异步工具类Guava异步 CompletableFuture异步编排工具类创建异步…...

学习笔记|模数转换器|ADC原理|STC32G单片机视频开发教程(冲哥)|第十七集:ADC采集
文章目录 1.模数转换器(ADC)是什么?手册说明: 2.STC32G单片机ADC使用原理19.1.1 ADC控制寄存器(ADC_CONTR)19.1.2 ADC配置寄存器(ADCCFG)19.1.4ADC时序控制寄存器(ADCTIM)19.3 ADC相…...

OpenCV实现“蓝线挑战“特效
原理 算法原理可以分为三个流程: 1、将视频(图像)从(顶->底)或(左->右)逐行(列)扫描图像。 2、将扫描完成的行(列)像素重新生成定格图像…...

容器管理工具 Docker生态架构及部署
目录 一、Docker生态架构 1.1 Docker Containers Are Everywhere 1.2 生态架构 1.2.1 Docker Host 1.2.2 Docker daemon 1.2.3 Registry 1.2.4 Docker client 1.2.5 Image 1.2.6 Container 1.2.7 Docker Dashboard 1.3 Docker版本 二、Docker部署 2.1 使用YUM源部署…...
js判断数据类型的方法
简单数据类型用:typeof, // 可以直接typeof空格接数据的方式,也可以typeof(数据)的方式使用 console.log(typeof ""); //string(检验字符串没问题) console.log(typeof 1); //number(检验数字没问题) console.log(typ…...
达梦数据库随系统开机自动启动脚本
写一个脚本,实现在服务器开机后自动启动达梦数据库的功能。 1. 在/etc/init.d/目录下,编写脚本,并将脚本命名为startdm.sh。脚本内容实现如下: #!/bin/bash #chkconfig:2345 80 90 #decription:启动达梦# 切换到 dmdba 用户 su …...

Python开发利器之VS Code
Python官方提供了一个Python集成开发环境(IDE): IDLE (Integrated Development and Learning Environment)。 它提供了一个图形用户界面,可以让开发者编写、调试和执行Python程序。IDLE包含Python解释器、代码编辑器、调试器和文件…...
【Axure视频教程】输入框控制滑动评分条
今天教大家在Axure里如何制作输入框控制滑动评分条的原型模板,可以通过鼠标左右拖动滑块,也可以点击条形让滑块移动到指定位置,标签和输入框里会返回具体的分值,分值由滑块所在的位置动态计算而成;也可以在输入框里输入…...
【学习笔记】[AGC064C] Erase and Divide Game
有点难😅,看到比自己低一级的选手场切这道题就更绷不住了😇 考虑 从低到高位 建立 trie \text{trie} trie 树,但是因为是对反串建立的,所以编号连续的点在 trie \text{trie} trie 树上的位置是分散的😅 …...
算法通关村-----数组中元素出现次数问题
数组中出现次数超过一半的数字 问题描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。详见剑指offer39 问题分析 最直接的方式就是使用hashMap,遍历给定数组,…...
Qt-键盘消息的传递-键盘消息的获取-C++
文章目录 1.概述2.焦点3.强制获取键盘消息4.键盘常用组合方法5.总结 1.概述 QKeyEvent 类用来描述一个键盘事件。当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键盘输人焦点的部件。 QKeyEvent 的 key() 函数可以获取具体的按键,对于 Qt 中给…...

数据结构与算法(五)--链表概念以及向链表添加元素
一、前言 今天我们学习另一种非常重要的线性数据结构–链表,之前我们已经学习了三种线性数据结构,分别是动态数组,栈和队列。其中队列我们额外学习了队列的另一种实现方式–循环队列。其实我们自己实现过前三个数据结构就知道,它…...

计算机视觉与深度学习-图像分割-视觉识别任务02-目标检测-【北邮鲁鹏】
目录标题 参考目标检测定义深度学习对目标检测的作用单目标检测多任务框架多任务损失预训练模型姿态估计 多目标检测问题滑动窗口(Sliding Window)滑动窗口缺点 AdaBoost(Adaptive Boosting)参考 区域建议 selective search 思想慢…...

Flink——Flink检查点(checkpoint)、保存点(savepoint)的区别与联系
Flink checkpoint Checkpoint是Flink实现容错机制最核心的功能,能够根据配置周期性地基于Stream中各个Operator的状态来生成Snapshot,从而将这些状态数据定期持久化存储下来,从而将这些状态数据定期持久化存储下来,当Flink程序一…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...