# linker_script **Repository Path**: ottobryant_admin/linker_script ## Basic Information - **Project Name**: linker_script - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-01 - **Last Updated**: 2025-08-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 以下是 GNU `ld` 链接脚本(linker script)的 **所有命令与结构化语法关键字(commands/statements)** ,并附上 **官方文档地址** 方便查阅原始资料与细节。 --- ## 🧭 官方文档地址(Linker Script) * **GNU Linker (ld) 官方手册(完整版)** 📘 [https://sourceware.org/binutils/docs/ld/Scripts.html](https://sourceware.org/binutils/docs/ld/Scripts.html) --- ## 📚 GNU ld Linker Script 全部命令分类总表 ### 一、控制脚本结构的命令(Top-level keywords) | 命令 | 说明 | | --------------------- | ------------------------------------------------------ | | `ENTRY(symbol)` | 设置 ELF 文件的入口点,通常是 `_start`或 `main`。 | | `OUTPUT(filename)` | 指定输出文件名(很少直接用,通常通过命令行 -o 指定)。 | | `SEARCH_DIR(path)` | 添加库搜索目录,相当于 `-L`选项。 | | `GROUP()` | 指定多个库以分组方式链接,解决循环依赖问题。 | | `INPUT()` | 指定输入文件。 | | `OUTPUT_FORMAT()` | 设置输出文件格式(如 elf64-x86-64)。 | | `TARGET()` | 设置目标平台,如 `i386-elf`。 | | `INCLUDE "file.ld"` | 引用其他 linker 脚本文件。 | | `ASSERT(expr, msg)` | 如果 expr 为 false,链接时报错并输出 msg。 | | `EXTERN(symbol...)` | 显式声明符号为外部可见(即使未使用)。 | --- ### 二、内存分配命令(Memory & Region) | 命令 | 说明 | | ------------------------------- | ------------------------------------------ | | `MEMORY { ... }` | 定义内存段,使用 `ORIGIN`和 `LENGTH`。 | | `REGION_ALIAS(alias, region)` | 给某个 MEMORY 区域创建别名。 | --- ### 三、节区定义命令(Sections & Layout) | 命令 | 说明 | | ------------------------------------------ | ------------------------------------------------------ | | `SECTIONS { ... }` | 主体结构,控制输出节的顺序与分配。 | | `PHDRS { ... }` | 定义 ELF 程序头(Program Header),控制 segment 分布。 | | `.section-name` | 定义某个节,例如 `.text : { *(.text) } > TEXT`。 | | `KEEP(section)` | 强制保留某节的内容,避免被优化器移除。 | | `FILL(expr)` | 使用某个模式填充该节空白区域。 | | `ALIGN(n)` | 对齐地址到 n 字节边界。 | | `SORT_BY_NAME()`/`SORT_BY_ALIGNMENT()` | 排序节内文件顺序。 | | `CONSTRUCTORS` | 展开 `.ctors` `.dtors`区域(用于 C++ 构造析构)。 | --- ### 四、符号相关命令(Symbol & Expression) | 命令 | 说明 | | --------------------------------- | --------------------------------------------- | | `symbol = expression;` | 定义符号为某地址或值,如 `_heap_end = .;`。 | | `PROVIDE(symbol = expr)` | 定义符号,仅当该符号尚未定义时有效。 | | `PROVIDE_HIDDEN(symbol = expr)` | 同上,但符号是局部的。 | | `ABSOLUTE(expr)` | 返回一个绝对地址,避免随节移动而变化。 | | `BLOCK(n)` | 对表达式向上对齐至 n 的倍数。 | | `ALIGN(expr)` | 同 `BLOCK(expr)`,更推荐写法。 | | `SIZEOF(section)` | 获取 section 大小。 | | `LOADADDR(section)` | 获取 section 的加载地址。 | | `ADDR(section)` | 获取 section 的起始地址。 | --- ### 五、特殊结构 | 命令 | 说明 | | ------------------- | ------------------------------------------- | | `OVERLAY { ... }` | 实现多个段映射到同一地址空间(罕见)。 | | `AT (address)` | 指定节的加载地址。 | | `:phdr-name` | 指定该节属于哪个程序头段。 | | `>region` | 指定该节映射到哪个内存区域(MEMORY 定义)。 | | `=fill` | 在节内进行填充。等效于 `FILL()`。 | --- ## ✅ 推荐调试与实验建议 现在已经能手写复杂 `link.ld`,建议进一步做这些实验练习: 1. **实验不同 FILL 模式:** * 用 `FILL(0xDEADBEEF)`,再 `objdump -s` 看段内内容。 2. **使用 ASSERT 检查布局正确性:** ```ld ASSERT(ADDR(.bss) >= 0x600000, "BSS 不在 DATA 区域!") ``` 3. **使用 PROVIDE 导出地址供 C 引用:** ```ld PROVIDE(heap_top = _heap_end); ``` C 中用 `extern char heap_top[];` 4. **加 init/fini 构造函数表,并用 objdump -s 确认其展开。**