问题标签 [position-independent-code]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
95 浏览

assembly - 什么决定了内存重映射操作后的位置无关性?

我已经开始阅读 Miro Samek 的“使用 GNU 构建裸机 ARM 系统”,发现自己陷入了困境。在 PDF 第 10 页上的注释之一中可以找到导致我困惑的原因:

注意:函数 low_level_init() 可以用 C/C++ 编码,但有以下限制。该函数必须在 ARM 状态下执行,并且不能依赖于 .data 部分的初始化或 .bss 部分的清除。此外,如果完全执行内存重新映射,它必须发生在 low_level_init() 函数内部,因为该函数返回后代码不再与位置无关

代码“不再与位置无关”究竟如何?似乎引用的代码(可在 PDF 中的第 7-9 页查看)在从标签返回low_level_init/ 之后仍然与位置无关。_cstartup标签后的指令似乎唯一不同的_cstartup是它们引用了链接描述文件中定义的标签(指南的第 3 节)。

那么重映射究竟如何影响它后面的指令是否与位置无关?

0 投票
2 回答
331 浏览

gcc - 为什么 MIPS GCC 在函数调用(一个 GOT 指针)之后从 16($fp) 重新加载 28 美元,而没有先存储到 16($fp) ?

我想我需要粘贴完整的代码,虽然它看起来很长。

我写了一个简单的代码进行测试。

组装后:

我意识到在每个函数调用之后,都有一条lw $28,16($fp)指令。但是我没有看到任何代码会首先在调用者或被调用者中存储一个值。

我可以阅读 MIPS 程序集。我知道这lw是加载字,以及 $fp 和 $sp 如何是帧指针和堆栈指针。

我只是无法理解从16($fp);加载任何内容的意义。似乎有一个未初始化的空间。

我知道$28$gp,并且可以看到它被用作 GOT 指针,以在调用之前加载函数地址,但似乎没有在函数中使用该寄存器之前初始化该寄存器。

MIPS 调用约定是否需要$28在函数入口处已经指向 GOT?

0 投票
1 回答
574 浏览

linux - 我想知道如果系统上关闭了 aslr,pie 是否会做任何事情?还是pie依赖aslr?

我也想知道 pie 和 aslr 在内存中的作用是什么,据我所知,aslr 随机化了 libc 基址、堆栈和堆的地址。并且 pie 随机化精灵基础并使用 .text、.data、.bss、.rodata ......

这是正确的还是我弄错了?

0 投票
0 回答
392 浏览

windows - 在 MASM 中获取段寄存器的实际值

我正在尝试了解有关阅读 PEB / TEB (以及一般的段寄存器)的更多信息。我的主要来源是:https ://en.wikipedia.org/wiki/Win32_Thread_Information_Block 我试图弄清楚 gs 中任何地址的实际地址是什么。例如,我看到 x64 中的 PEB 在 gs:[60h] 所以

应该给我PEB的地址。我试图弄清楚它的存储位置/gs 的值是多少。

我的主要问题是:

1) 43 和 48 分别代表什么值?

2) 有没有办法在没有 gs:[30h] 的情况下找到并访问 gs 的内存位置?因为 lea 和 gs:0 不起作用

3)我试过假设没有在我的环境中编译的东西。

环境:Windows 7、Visual Studio 2015

我看过很多参考资料说

0 投票
2 回答
301 浏览

gcc - __i686.get_pc_thunk 和 __x86.get_pc_thunk 有什么区别?

GCC 和 Clang 在 32 位 x86 位置无关代码中使用这些辅助函数将当前执行地址放入寄存器,例如:

似乎实现是等效的:

除了更名之外还有什么区别(似乎i686更旧)?有 i686 前缀而不是 i386 的原因吗?

0 投票
2 回答
531 浏览

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

我正在尝试构建和链接单个图像以加载为针对 aarch64-unknown-none-softfloat 的 OS 内核(即在 QEMU 中)。我使用一个自定义的 linker.ld 文件来设置内核的入口点ENTRY(_reset)并定位图像

. = 0x40080000

其中程序计数器 (PC) 处于复位状态。

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

. = 0xffffff8200000000

并重建。

我发现了访问:

  • 到一些(酒吧外部)静态,和
  • 通过某些核心库函数

是通过从.rodata. 这在映射之前运行时会破坏代码。如果我把它改回来,它会在我映射后运行它时破坏代码。

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

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

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

谢谢!

编辑:非常感谢临时映射的建议。我见过用的。我更感兴趣的编译器选项将使 -no-dynamic-linker 能够工作,避免生成需要 R_AARCH64_ABS64 重定位的代码,以保证代码和数据将相隔一定距离。

0 投票
0 回答
22 浏览

linux - 关于使用 GDB 的代码 x86 的错误内存地址

你好!在 Linux 上使用 GDB,每次我尝试为这些地址之一设置断点时,它都会向我打印一个错误,说这是不可能的或危险的。我怎样才能解决这个问题?谢谢!

0 投票
0 回答
780 浏览

linux - 共享对象如何包含静态线程本地存储?

背景

我遇到了一个问题,它违反了我的位置无关代码和线程本地存储的概念模型。提示此问题的问题可以在此 StackOverflow 帖子中找到;我有一个二进制文件,它又dlopen是一个共享对象。打开共享对象会触发错误声明dlopen: cannot load any more object with static TLS

我对此的理解是,该initial-exec模型被称为“静态 TLS”,并且在不创建与位置无关的代码时,这通常是默认设置。当创建与位置无关的代码时,默认值通常是其他东西,例如global-dynamicGCC 使用的模型。我认为这是因为initial-exec无法在共享对象中工作。对另一个 StackOverflow 帖子的回答支持了这一信念,并指出:

将非 fPIC 代码链接到共享库在 x86_64 上是不可能的,但在 ix86 上是允许的(并且会导致许多微妙的问题,比如这个)。

鉴于我在 x86_64 机器上,这导致了一些混乱。然后我遇到了另一个 StackOverflow 问题,答案似乎是使用静态 TLS 模型创建共享对象。

看到这一点,我决定返回我有问题的二进制文件并递归扫描依赖项以使用静态 TLS 模型,方法readelf -d是根据这个问题的答案查看输出。令我惊讶的是,我发现了一些图书馆。令我沮丧的是,它们不是应用程序构建的库。

这是readelf -d其中之一的输出:

在这里我们可以看到STATIC_TLS,这使我相信该initial-exec模型已被使用。

的输出readelf -l

我对这里缺少 TLS 部分感到惊讶,但即便如此,我们也有明确的迹象表明共享对象正在使用静态initial-execTLS 模型。

最后,我看到有类似问题的人重新排序依赖项以摆脱早期的dlopen错误。我不是为什么这会有所作为。

问题)

  • initial-exec可重定位代码(尤其是 x86_64 上的共享对象)中的函数如何?
  • 为什么重新排序依赖项有时会解决dlopen问题;使用的插槽数量肯定保持不变吗?

dlopen也欢迎对原始问题提出任何其他建议。

更新 1

在进一步研究这个问题的同时,我发现了另一个来源,指出静态 TLS 模型不能在共享库中使用:

0 投票
2 回答
1218 浏览

assembly - 重定位应该如何在静态 PIE 二进制文件中工作?

考虑这个适用于 AMD64 Linux 的 GNU 汇编程序:

当我使用它构建gcc -nostdlib -static-pie并运行它时,它失败了,并且 strace 告诉我发生了这种情况:

不过,如果我将它构建为静态非 PIE 二进制文件或动态 PIE 二进制文件,它工作正常。看起来问题是重定位没有得到处理。

在动态 PIE 二进制文件中,动态链接器会执行此操作,而在非 PIE 静态二进制文件中,您不需要运行时重定位;静态地址是链接时间常数。

但是静态 PIE 二进制文件应该如何工作?他们只是根本不应该有任何搬迁,还是应该有其他东西来处理它们?

0 投票
0 回答
153 浏览

gcc - 可以将 gcc 配置为编译代码的位置无关代码但数据的位置相关代码吗?

我正在尝试为基于 ARM M7 的嵌入式系统构建可引导代码,该代码能够在 QSPI 中的两个不同位置就地执行,因此如果一个版本损坏,则可以在其中执行映像的备份版本不同的地方。

使用 -fpic 编译似乎会生成一个可重定位的代码映像,该映像(几乎)能够在两个地方都可以正常执行。但是,问题在于代码所引用的数据/bss偏移了相同的量 - 也就是说,编译器假设 .data 和 .bss 段紧随 .text 段之后,这不是适用于 XIP 嵌入式系统(RAM 是独立的)。

结果,如果原始二进制文件链接到在 0x60000000 处运行(并在 0x20000000 处使用固定 ram 区域),但随后在 0x60100000 处执行,则 ram 地址也将移动 0x100000(即到 0x20100000),这根本不是我想要的。

显然,我想做的是修改 gcc 的行为,以便对代码的引用(在 QSPI 中的两个不同位置执行)与位置无关,而对 .data/bss 段的引用(在固定的RAM 中的位置)是位置相关的(按照正常情况)。

这是否可以通过调整 gcc 来实现(例如,通过一些晦涩的链接器属性标志)?或者这只是遥不可及?谢谢!