Funny Little Executable

Funny Little Executable

2025 南京大学《操作系统原理》
Funny Little Executable

🔥 😭 ✅ ✨ 🫶 😂 😊

代码 (🔢)、符号 (📤)、重定位 (❓)

  • 凑齐这三要素,我们就可以完成链接到加载的全流程了!
🔢: ff ff ff ff ff ff ff
🔢: ff ff ff ff ff ff ff
📤: _start
🔢: 48 c7 c0 3c 00 00 00
🔢: 48 c7 c7 2a 00 00 00
             ^
             |
          This byte is return code (42).
🔢: 0f 05 ff ff ff ff ff
🔢: ff ff ff ff ff ff ff
❓: i32(unresolved_symbol - 0x4 - 📍)
2025 南京大学《操作系统原理》
Funny Little Executable

这是一个 DSL (Domain-specific Language)

我们为什么需要 DSL?

  • 只要领域内的表达能力
    • 做了减法,就可以更专注
    • 更简洁、更 natural

DSL 的例子

  • 正则表达式
  • Markdown, TeX, ...
  • abcjs
2025 南京大学《操作系统原理》
Funny Little Executable

实现 FLE Binutils

实现的工具集

  • objdump/readfle/nm (显示)
  • cc/as (编译)
  • ld (链接)

大部分都复用自 GNU binutils

  • elf_to_fle
2025 南京大学《操作系统原理》
Funny Little Executable

生成可执行文件 (1):预编译 & 编译

源代码 (.c) → 源代码 (.i)

  • Ctrl-C & Ctrl-V (#include)
  • 字符串替换
  • 今天:我们有过程宏

源代码 (.i) → 汇编代码 (.s)

  • “高级状态机” 到 “低级状态机” 的翻译
  • 最终生成带标注的指令序列
2025 南京大学《操作系统原理》
Funny Little Executable

生成可执行文件 (2):汇编

汇编代码 (.s) → 目标文件 (.o)

  • 文件 = sections (.text, .data, .rodata.str.1, ...)
    • 对于 ELF,每个 section 有它的权限、内存对齐等信息
  • section 中的三要素
    • 代码 (字节序列)
    • 符号:标记 “当前” 的位置
    • 重定位:暂时不能确定的数值 (链接时确定)
      • Quick Quiz: ELF 中全局和局部符号有什么区别?还有其他类型的符号吗?
2025 南京大学《操作系统原理》
Funny Little Executable

生成可执行文件 (3):(静态) 链接

多个目标文件 (.o) → 可执行文件 (a.out)

  • 合并所有的 sections
    • 分别合并 .text, .data, .bss 中的代码
    • 把 sections “平铺” 成字节序列
    • 确定所有符号的位置
    • 解析全部重定位
  • 得到一个可执行文件
    • (程序初始内存状态的描述)
2025 南京大学《操作系统原理》
Funny Little Executable

最后一步:加载

把 “字节序列” 搬到内存

  • 没错,就只做这一件事
  • 然后设置正确的 PC,开始运行
mem = mmap.mmap(
    fileno=-1, length=len(bs),
    prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
    flags=mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS,
)
mem.write(bs)
mem.flush()
call_pointer(mem, fle['symbols']['_start'])
2025 南京大学《操作系统原理》