在操作系统上实现 ELF Loader

加载器 (loader) 的职责

  • 解析数据结构
  • 创建进程初始状态
  • 跳转执行

代码示例

  • 能正确处理参数/环境变量 env.c

Boot Block Loader

加载操作系统内核?

  • 也是一个 ELF 文件
  • 解析数据结构 + 复制到内存 + 跳转

之前给大家看过一眼

  • 做得事情与静态加载器完全一样
  • 没有 mmap 怎么办?
    • 用 I/O 指令把数据从磁盘搬到内存

ELF 文件是如何生成的?

一个字节一个字节 “写出来” 的

  • printf("\x7f");

绝大部分指令都是编译时就完全确定好的

  • 但有少部分不能
  • 例如 printf 的地址
    • call 会编译成 e8 00 00 00
      • 复习题:offset 0 是跳转到哪条指令,为什么?
    • 连接时需要 relocate
      • 这也是 ELF “数据结构” 的一部分
      • 你可以理解成 “ADDR_OF(puts) + 4” 这种运算规则

为什么 ICS 课的 “链接和加载” 如此僵硬?

因为 ELF 不是一个好的 “描述状态机数据结构” 的格式

  • 彻底违背了信息的局部性原则
    • 含义隐晦的 R_X86_64_32, R_X86_64_PLT32
    • 不靠解析根本不可能看懂
    • 大量的 “指针” (人类无法阅读的偏移量)
    • 等于直接让你去读一个内存数据结构的 core dump

给我一个机会重新设计?

  • 可以做个 JSON-based,可读的格式
    • FLE: A Fast, Legible, and Expedient Binary Format
      • (这个名字也是 GPT 给我起的)