从头开发一个RISC-V的操作系统(三)编译与链接

文章目录

目标:通过这一个系列课程的学习,开发出一个简易的在RISC-V指令集架构上运行的操作系统。

前提

这个系列的大部分文章和知识来自于:[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春,以及相关的github地址

在这个过程中,这个系列相当于是我的学习笔记,做个记录。

GCC

GCC简介

我们在Linux下经常使用的GCC是由GNU开发的编译器套件。GCC的初衷是为GNU操作系统专门编写一款编译器,现在已经被大多数"Unix-like"操作系统采纳为标准的编译器。

现在来说,另一个常见的编译器套件还有LLVM,它是由苹果公司开发的。

GCC的主要执行步骤

一个.c程序到一个可执行文件主要包括这么几步:源程序->预处理->编译->汇编->链接。预处理有一些宏替换,注释取消等操作;编译则针对预处理的结果进行词法分析,语法分析,语义分析,优化后生成汇编指令;编译则是编译器将汇编语言代码转为CPU可执行的指令;链接是将汇编器生成的目标文件和一些标准库文件组合,生成最终的可执行程序。

GCC涉及的文件类型

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

ELF

ELF简介

ELF(Executable Linkable Format)是一种Unix-like系统上的二进制文件格式标准。

ELF标准中定义的采用ELF格式的文件分为4类:

这里可以看下第四个是核心转储文件,如果你程序崩溃过,那你估计可能对这个文件有所了解。默认情况下程序崩溃时的dump文件是不会存储的,挺有意思。

ELF文件格式

ELF文件格式分为两种:运行视图(Execution View)和链接视图(Linking View)。

  • ELF Header: 描述文件的主要特性:类型,CPU架构,入口地址,现有部分的大小和偏移等等。
  • Program Header Table: 列举了所有有效的段(segments)和他们的属性。 程序头表需要加载器将文件中的节加载到虚拟内存段中(Execution View);
  • Section: 按照类型划分不同的节(Linking View)。
  • Section Header Table: 包含对每个节(sections)的具体描述。

ELF文件处理工具:Binutils

关于Binutils工具的具体知识自行百度即可。

这里阐述几个可能会使用的命令。

  • as:被gcc调用,输入汇编文件,输出目标文件。因此我们使用gcc来编译c程序生成可执行文件过程中汇编那一个步骤其实是调用了这个工具。
  • ld:GNU链接器,被gcc调用。
  • objcopy:执行文件格式转换。
  • objdump:显示ELF文件的信息。
  • readelf:显示更多ELF格式文件的信息

练习

  1. 编写一个简单的打印 "hello world!" 的程序源文件:hello.c

    c 复制代码
    #include<stdio.h>
    
    void main()
    {
        printf("hello world!");
    }
  2. 对源文件进行本地编译,生成针对支持 x86_64 指令集架构处理器的目标文件 hello.o。

    生成目标文件.o我们要使用-c参数

    bash 复制代码
    $gcc - c hello.c -o hello.o
  3. 查看 hello.o 的文件的文件头信息。

    使用readelf查看hello.o文件,加上-h参数查看头信息。

    bash 复制代码
    $readelf -h hello.o
    ELF Header:
      Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
      Class:                             ELF64
      Data:                              2's complement, little endian
      Version:                           1 (current)
      OS/ABI:                            UNIX - System V
      ABI Version:                       0
      Type:                              REL (Relocatable file)
      Machine:                           Advanced Micro Devices X86-64
      Version:                           0x1
      Entry point address:               0x0
      Start of program headers:          0 (bytes into file)
      Start of section headers:          712 (bytes into file)
      Flags:                             0x0
      Size of this header:               64 (bytes)
      Size of program headers:           0 (bytes)
      Number of program headers:         0
      Size of section headers:           64 (bytes)
      Number of section headers:         13
      Section header string table index: 12
  4. 查看 hello.o 的 Section header table。

    bash 复制代码
    $readelf -S hell.o
    There are 13 section headers, starting at offset 0x2c8:
    
    Section Headers:
      [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
      [ 1] .text             PROGBITS        0000000000000000 000040 000018 00  AX  0   0  1
      [ 2] .rela.text        RELA            0000000000000000 000218 000030 18   I 10   1  8
      [ 3] .data             PROGBITS        0000000000000000 000058 000000 00  WA  0   0  1
      [ 4] .bss              NOBITS          0000000000000000 000058 000000 00  WA  0   0  1
      [ 5] .rodata           PROGBITS        0000000000000000 000058 00000d 00   A  0   0  1
      [ 6] .comment          PROGBITS        0000000000000000 000065 00002a 01  MS  0   0  1
      [ 7] .note.GNU-stack   PROGBITS        0000000000000000 00008f 000000 00      0   0  1
      [ 8] .eh_frame         PROGBITS        0000000000000000 000090 000038 00   A  0   0  8
      [ 9] .rela.eh_frame    RELA            0000000000000000 000248 000018 18   I 10   8  8
      [10] .symtab           SYMTAB          0000000000000000 0000c8 000120 18     11   9  8
      [11] .strtab           STRTAB          0000000000000000 0001e8 00002b 00      0   0  1
      [12] .shstrtab         STRTAB          0000000000000000 000260 000061 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
      L (link order), O (extra OS processing required), G (group), T (TLS),
      C (compressed), x (unknown), o (OS specific), E (exclude),
      l (large), p (processor specific)
  5. 对 hello.o 反汇编,并查看 hello.c 的 C 程序源码和机器指令的对应关系。

bash 复制代码
$gcc -c -g hello.c -o hello.o
$objdump -S hello.c

hello.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
#include<stdio.h>

void main()
{
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
    printf("hello world!");
   4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <main+0xb>
   b:   b8 00 00 00 00          mov    $0x0,%eax
  10:   e8 00 00 00 00          callq  15 <main+0x15>
}
  15:   90                      nop
  16:   5d                      pop    %rbp
  17:   c3                      retq   

-g是为了添加调试信息,-S是为了反汇编的同时显示源码。

参考链接

  1. https://xinqiu.gitbooks.io/linux-inside-zh/content/Theory/linux-theory-2.html
相关推荐
嵌入式小企鹅7 小时前
RISC-V车规专委会成立、AI模型集中开源、半导体产能加速爬坡
人工智能·学习·ai·程序员·算力·risc-v·半导体
国科安芯8 小时前
空间激光通信系统中抗辐射 MCU 芯片应用研究
单片机·嵌入式硬件·架构·risc-v·安全性测试
极创信息1 天前
信创领域五种主流CPU架构(X86 / ARM / RISC-V / MIPS / LoongArch)
java·arm开发·数据库·spring boot·mysql·软件工程·risc-v
嵌入式小企鹅2 天前
CPU需求变化、RISC-V安全方案、DeepSeek V4适配、太空算力动态
人工智能·驱动开发·华为·开源·算力·risc-v
国科安芯4 天前
商业航天与航空安全场景下抗辐射 MCU 选型、应用实践及发展趋势
单片机·嵌入式硬件·无人机·cocos2d·risc-v
国科安芯4 天前
空间辐射环境下抗辐射 MCU 可靠性机理及航空安全应用研究综述
单片机·嵌入式硬件·macos·无人机·cocos2d·risc-v
国科安芯4 天前
航空安全关键系统抗辐射 MCU 加固技术、工程实现与典型应用
单片机·嵌入式硬件·无人机·cocos2d·risc-v
Captain_Data5 天前
AI 12小时设计CPU完整解析:从219字到RISC-V内核的技术突破
人工智能·python·ai·大模型·芯片设计·risc-v
圆山猫6 天前
[RISCV] 用 Rust 写一个 RISC-V BootROM:从 QEMU 到真实硬件(2)
rust·risc-v
嵌入式小企鹅6 天前
算力价值重估、AI编程模型齐开源、RISC-V融资15亿
人工智能·学习·ai·程序员·risc-v·前沿科技·太空算力