问题标签 [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 投票
0 回答
362 浏览

c++ - 获取程序内 -pie 二进制文件中 addr2line 的地址

我希望我的程序打印程序完成后 addr2line 可以使用的回溯。在 ubuntu 14.04 上,这是通过以下代码实现的:

现在在 ubuntu 18.04 上使用时,addr2line 提供了很多??:0. 我对backtrace_symbols(3)linux 函数给出的人类可读格式不感兴趣,我想要简洁的格式,可以在必要时使用单独分发的调试符号(剥离到单独的 .dbg 文件)进行解码。

我可以编译-no-pie,但我不想。这似乎是我们在生产中不想要的东西。

我了解到,如果对于每个指针(array[i]上面),我从中删除值/proc/<pid>/maps并转换回十六进制,我得到的地址对于 addr2line 是可以理解的。所以问题是:

如何在不查看 /proc 中的文本文件的情况下获取代码中的偏移量?或者有没有更好的方法来实现简洁的回溯?

0 投票
2 回答
764 浏览

c - 如何找到 PIE 二进制文件的负载重定位?

我需要在我的运行进程中获取堆栈的基地址。这将使我能够打印 addr2line 可以理解的原始堆栈跟踪(运行的二进制文件被剥离,但 addr2line 可以访问符号)。我设法通过检查 elf 标头来做到这一点argv[0]: 我读取入口点并将其减去&_start

样本输出:

然后我可以

如何在没有访问权限的情况下获得基地址argv?我之前可能需要打印痕迹main()(全局变量的初始化)。转向 ASLR 或 PIE 不是一种选择。

0 投票
1 回答
259 浏览

arm - Atmel SAM Cortex-M0+ 的位置无关二进制文件

我正在尝试使用 Atmel Studio 7 中包含的 ARM GNU 工具链(arm-none-eabi ?)为 Cortex-M0+ 创建与位置无关的二进制文件。我已经在很多地方寻找有关如何执行此操作的信息,但没有成功。这将有助于在低高闪存区域中为 OTA 更新创建 ping-pong 映像,而无需知道或关心更新是该单元的 ping 映像还是 pong 映像。

我有一个位于 0x0000 的 8 kB 引导加载程序,我可以通过 UART 与它通信,如果它在此处检测到二进制文件(即不是 0xFFFF 擦除闪存),它将在重置后跳转到 0x6000(24 kB)。这个 SAM-BA 引导加载程序允许我在指定地址转储内存并使用 .bin 文件擦除和编程闪存。

在应用程序项目中(简单的 LED 闪烁),除了在链接器命令行中添加 -section-start=.text=0x6000 之外什么都不做会导致 LED 闪烁代码在引导加载程序在 0x6000 处编程后工作。我还在十六进制文件中看到它从 0x6000 开始。

在我尝试创建与位置无关的二进制文件时,我删除了上述链接器项,并将 -fPIC 标志添加到编译器、链接器和汇编器的命令行中。但是,我想我仍然在反汇编中看到绝对分支地址,例如:

28e: d001 beq.n 294

结果是我在 0x6000 加载的 LED 闪烁二进制文件不会执行,除非我明确告诉链接器将它放在 0x6000,这违背了目的。请注意,我也确实看到了反汇编其他部分中的相对分支:

21c:4b03 ldr r3,[pc,#12];(22c)

21e: 58d3 ldr r3, [r2, r3]

220:9301 str r3,[sp,#4]

222: 4798 blx r3

SRAM 总是在同一个地址(0x20000000),我只需要能够重新定位可执行文件。我没有修改链接器命令文件,并且它没有 .got 部分(例如(.got)或类似文件)。

谁能向我解释我需要对编译器/汇编器/链接器标志进行的具体更改以在此设置中创建与位置无关的二进制文件?提前谢谢了。

0 投票
0 回答
42 浏览

assembly - 为什么“主”符号不会在 pie 二进制文件中剥离?

像任何其他符号一样,main被归类为静态符号,
所以当二进制被剥离时,这通常会消失。
然而,昨天我发现这个main函数并没有在pie二进制文件中被剥离。

我在示例 C 程序中定义了几个符号,myfunc1, myfunc2, ... 和main.
我发现当我剥离二进制文件时任何其他符号确实消失了,但 main剥离后符号仍然存在。

我检查了原因,发现与其他任何用户定义的符号不同 ,它main被归类为动态符号。

问题:
为什么二进制main中被归类为动态符号 (我认为脱衣舞会没问题,就像它在.) pie
mainnon-pie binary

0 投票
2 回答
189 浏览

x86 - 分页和 PIC 可执行文件

当使用虚拟内存时,我很难理解对 PIC 可执行文件的需求。根据我收集到的信息,每个程序都在页表中分配了一个条目,因此有一种错觉,即它拥有整个内存可供使用,而分页机制负责可能的重定位、页面错误等。所以,如果任何程序有这种错觉拥有所有可能的内存地址,为什么要使用 PIC?

0 投票
0 回答
176 浏览

linux - 在 ELF LSB 共享对象模式下编译 curl

我正在尝试将 curl 构建为 pie(与位置无关的可执行文件)模式下的共享对象可执行文件。因此,我将 -pie -fPIC 添加到由 ./configure 生成的 MakeFile 的 CFLAGS 中。但是在 make 和 make install 之后,在 /usr/local/bin 下生成的 curl 可执行文件仍然是一个 ELF 64 位 LSB 可执行文件。那么有人可以给出一个关于如何在位置独立共享对象模式下生成 curl 可执行文件的想法吗?提前致谢。

0 投票
1 回答
1488 浏览

linux - 使用 -fPIC 编译的共享库的内存映射和变量位置

我正在使用 Linux 机器,我想在运行时找出 Position-Independent-Code 共享库中符号的地址,现在我可以根据一些观察来实现,但是,我仍然对程序/库有一些疑问加载(是的,我知道怎么做,但我不知道为什么)。假设我们有以下两个 C 源文件:

我们用下面的命令编译上面的代码:

readelf -sW lib.so显示global_field符号:

readelf -lW lib.so输出以下程序头:

现在我们运行程序,它输出以下内容:

cat /proc/<pid>/maps输出以下内容:

抱歉,这里的代码太多了......现在我的问题是:

  1. 如您所见,程序头中有两个 LOAD段,但内存映射有四个,为什么还有两个映射?

  2. 对于这两个LOAD段,如何确定哪个段映射到哪个内存区域?有没有标准或手册?

  3. 但是,根据 ELF 标准,符号global_field的值是0000000000201028(参见 的输出):readelf -sW lib.so

在可执行文件和共享对象文件中,st_value拥有一个虚拟地址。为了使这些文件的符号对运行时链接器更有用,节偏移(文件解释)让位于与节号无关的虚拟地址(内存解释)。

我知道这是与位置无关的代码,它不能是虚拟地址,并且必须是某种偏移量。global_field用符号的值减去的地址: 0x7ffff7dda028 - 0x201028 = 0x7ffff7bd9000,似乎偏移量是基于最低内存映射的起始地址(参见 的输出cat /proc/<pid>/maps)。但是,是否有任何标准告诉我们,如何以编程方式检测符号的值类型(虚拟地址或偏移量)?如果它是一个偏移量,为什么偏移量应该基于它,为什么它不基于它自己的内存区域(我猜它自己的区域是最后一个,因为它有写权限)?

0 投票
1 回答
62 浏览

c - PIE 文件在链接期间是否提供了虚拟内存地址?

我已经用 编译了一个简单的hello worldc 代码gcc -fpie test.c,现在使用以下方法查看二进制文件objdump

我们可以清楚地看到内存地址仍然是由左侧的链接器计算的。文件不pie应该没有静态关联的内存地址吗?

我的第二个问题是,pic文件(如共享库)是如何加载到内存中的?他们有自己的虚拟地址空间吗?如果是这样,为什么他们需要独立于位置?还是将它们加载到进程地址空间中?

0 投票
1 回答
516 浏览

gcc - 为什么 gcc 会生成没有标志 -fno-pie 的奇怪代码?

我正在尝试使用标志 -fno-pie 和不使用标志在 gcc 中编译虚拟函数。

当我在没有标志的情况下编译时。

我得到以下反汇编代码。

当我用标志编译时。

我的问题。

它是什么???

0 投票
0 回答
1383 浏览

c++ - 编译 GCC 时出现“输出中不可表示的部分”

我正在尝试使用模块 TS 支持从源代码编译 GCC,然后我克隆到了 devel 分支(如此所述):

这是我的配置选项:

make给了我以下错误:

和类似的错误sso_string.oistream-inst.o等。
这是什么意思?
我怎样才能重新编译它-fPIC

我需要修补 Makefile 吗?
任何帮助表示赞赏。谢谢。