内核链接脚本解析

原文可在内核链接脚本解析查看到,后续的更新将会更新到个人博客


具体的代码可以见仓库,这里挑选几个说一下。

输出架构

OUTPUT_ARCH 这个命令用于指定输出文件的系统架构,这里采用的是 riscv。

入口点

ENTRY 则定义了程序的入口点,xv6 的默认入口点是 _entry。入口点代码在 entry.S 内。

位置计数器

进入 SECTIONS 后,当前程序的初始地址默认是 0x0。这里跟 Linux 的文件系统一样,采用 “.” 来表示当前地址。这个符号的名字叫位置计数器 (location counter),表示随后的段 / 变量对应的内存地址。这就意味着如果直接给 “.” 赋值,相当于切换了工作目录,后续段的相对位置都会发生改变。

这里可以看一个简单的例子

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}

进入 SECTIONS 后,位置计数器会被设置为 0x10000,所以链接器会将 .text 的地址设置为 0x10000。完成 .text 的设置后,位置计数器会被修改为 0x8000000,.data 的地址会被设置为 0x8000000。轮到 .bss 的时候,它会紧跟着 .data 段,此时位置计数器的值就是 0x8000000 加上 .data 段的大小。

xv6 初始地址设置

一进入 SECTIONS 脚本就会将当前的初始路径设置为 0x80000000。老师课上说这个地址是 qemu 认可的地址,第一条指令必须放置是它。书本2.6节的说法是 0x0 到 0x80000000 这段地址用于放置 IO 设备,所以第一条指令所在的地址就必须是 0x80000000。

段内容解析

  .text : {
    *(.text .text.*)
    . = ALIGN(0x1000);
    _trampoline = .;
    *(trampsec)
    . = ALIGN(0x1000);
    ASSERT(. - _trampoline == 0x1000, "error: trampoline larger than one page");
    PROVIDE(etext = .);
  }

内核的段设置都大同小异,所以看一个 .text 就可以了。

.text 段的第一个表达式 *(.text .text.*),其中的 * 是通配符。其表示所有输入文件的 .text.text.* 段都放置于输出文件的 .text 段中。

接着是命令 ALIGN(exp),这个命令会返回位置计数器对齐到下一个 exp 边界的地址,其并不会修改位置计数器的值。

PROVIDE 这个命令类似于 GCC 中的 attribute((weak))。现在只需要简单的理解为定义了一个符号。

剩余的 _trampolinetrampsec 在页表的章节会涉及到,到时候再去了解即可。

参考

链接脚本

GNU 链接脚本0 - 链接脚本基本介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值