gpt4 book ai didi

rust - 位置无关代码 (PIC) 中的绝对地址

转载 作者:行者123 更新时间:2023-12-03 11:27:11 30 4
gpt4 key购买 nike

我正在尝试构建并链接单个图像以作为操作系统内核(即在 QEMU 中)加载,目标是 aarch64-unknown-none-softfloat。我使用自定义 linker.ld 文件,它设置内核的入口点 ENTRY(_reset) 并定位图像

。 = 0x40080000

程序计数器 (PC) 复位的位置。

它工作正常,直到我将 0x40080000 处的页面映射到内核将驻留的高端内存并启用虚拟内存转换。为了保证切换后的调试信息网格,我将标称图像位置更改为

。 = 0xffffff8200000000

并重建。

我发现访问:

  • 一些(pub extern)静态信息,以及
  • 通过某些核心库函数

是通过从.rodata中某处读取绝对地址。这会在映射之前运行时破坏代码。如果我把它改回来,当我在映射后运行它时,它会破坏代码。

它生成的代码在 O1 中看起来有点像这样(通过 PC 相关页面间接生成):

adrp  x0, 0x10000 // page offset from PC up to rodata
add x0, 0x120 // byte offset from page in rodata
ldr x0, [x0] // use as address

我需要的是真正跨代码和数据的位置独立代码,以便它在内存中的两个位置工作,而不引用任何存储的绝对地址,即使这些地址相对于 PC 可用。

我已经尝试过其他重定位模型,包括 Pic 和 RopiRwpi,但我看不到它生成不同的代码。

谢谢!

编辑:非常感谢临时映射的建议。我看过那个用过。我对启用 -no-dynamic-linker 的编译器选项更感兴趣,避免生成需要 R_AARCH64_ABS64 重定位的代码,以保证代码和数据将分开一定距离。

最佳答案

根据我的经验,大多数想要驻留在高端内存中的操作系统内核只是链接到它们的目标高端内存地址,内核在启动时做的第一件事就是建立页表来映射自己进入高级内存。这样,操作系统内核设计者只需要确保入口点的某些 block 是位置独立的(或者实际上,只需将该启动代码链接到其真正的低内存位置,方法是将它放在一个特殊的部分并更改链接描述文件)。

参见示例 entrypointlinker script (不是 Rust 内核/aarch64)。

一个足够复杂的内核可以控制它的内存分配器然后可以考虑释放包含入口点代码的页面,正如入口点部分的开始和结束所标识的那样(实际上扩展它以处理所有初始化代码的相同方式)。

如果你能负担得起在启动时使用额外的内存,一个不错的 Rust 选项也可以是为加载程序编写一个单独的 crate,将所有内容与链接描述文件绑定(bind)在一起,并在启动后释放它的内存。

关于rust - 位置无关代码 (PIC) 中的绝对地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62254811/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com