【问题标题】:Is it possible to force a range of virtual addresses?是否可以强制使用一系列虚拟地址?
【发布时间】:2015-04-29 15:48:06
【问题描述】:

我有一个为特定(嵌入式、多处理器、32 位)架构编写的 Ada 程序。我试图在 64 位 RHEL 的模拟中使用相同的代码作为共享对象(因为有多个版本,我需要在运行时选择一个版本)。

我遇到的问题是代码中有几个地方编写它的人(不是我......)使用 Unchecked_Conversions 将 System.Addresses 转换为 32 位整数。不仅如此,还有多个具有硬编码内存地址的例程。我可以对这段代码做一些小的改动,但是完全将它移植到 x86_64 并不是一个真正的选择。有处理中断、CPU任务调度等的例程。

过去,当此代码静态链接到模拟的先前版本(由 Fortran/C/C++ 组成)时,它运行良好。然而,现在主可执行文件启动,然后根据一些输入加载一个共享对象。这个共享对象然后检查其他一些输入并加载适当的 Ada 共享对象。

查看代码,很明显,如果我可以将逻辑内存地址保持在 0 到 2,147,483,647(32 位有符号整数)之间,它应该可以正常工作。有没有办法强制共享对象加载器在 Ada 代码的较低范围内留出空间,或者让 Ada 代码“认为”它的地址在 0 到 2,147,483,647 之间?

【问题讨论】:

  • 您可以尝试使用-m32 选项进行编译。这将产生 32 位 (i386) 可执行文件。
  • 如果您可以从源代码重新编译标准 Ada 库,那么您可以尝试将 System.Address(在 system.ads 中的 prolly)的定义更改为“type Address is mod 2 ** 32;” - 但我不能保证它会工作[在我的 64 位系统上它被定义为 mod 2 ** 64]。

标签: linux memory linker shared-libraries ada


【解决方案1】:

有没有办法强制共享对象加载器在 Ada 代码的较低范围内留出空间

好消息是加载器将保持较低范围不变。

坏消息是它不会在那里加载任何共享对象。没有可用于影响共享对象放置的界面。

也就是说,dlopen from memory(我们在 glibc 的私有分支中实现)将允许您这样做。但这不是公开的。

您的其他可能选择是:

  • 如果您可以将整个过程放入 32 位地址空间,那么您的解决方案就很简单:只需使用 -m32 构建所有内容。

  • 使用prelink 将库重新定位到所需地址。由于该地址应该几乎总是可用的,因此加载器很可能会准确地在那里加载库。

  • 将加载器与自定义的mmap 实现链接,该实现通过某种侧通道检测感兴趣的库,并在设置MAP_32BIT 的情况下执行mmap 系统调用,或者

  • ptrace 沙箱中运行程序。这样的沙盒可以再次拦截mmap 系统调用,并在需要时或插入MAP_32BIT

或者也许让 Ada 代码“认为”它的地址在 0 到 2,147,483,647 之间?

我不明白这怎么可能。如果库将函数地址或全局地址存储在 32 位内存位置,然后加载该地址并取消引用它……它将获得 32 位截断地址和取消引用时的 SIGSEGV

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    相关资源
    最近更新 更多