问题标签 [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.
assembly - RIP 在编译时注册
链接器或编译器在编译期间是否计算 RIP?如果不是,该指令如何工作?链接时地址会被硬编码,还是处理器架构的特殊功能允许在运行时进行指针运算?
gcc - 为什么动态库源代码应该使用与位置无关的代码编译?
我对与位置无关的代码及其在动态库中的使用感到非常困惑。
我发现了这个关于 GCC 的 -fPIC 选项的好例子:GCC -fPIC 选项 ,我弄清楚了它是如何工作的。
但是,我很难理解为什么动态库需要独立于特定地址的代码。加载动态库时,为什么我们不能只保存其绝对地址(例如库中函数的地址)并使用它们?为什么在这种情况下必须使用相对地址?
用“gcc main.c”编译的简单程序int main() { return 0; }
总是依赖于位置?
assembly - nasm:“符号 rip 未定义” - 如何使用相对于“rip”寄存器的 lea 指令?
我想将指令lea rax, [rip + 0x1020304]
与 NASM 一起使用,但似乎它不允许使用rip
.
GAS(GNU 汇编程序)确实允许数字和符号的这种语法(如何在 x86-64 GAS 英特尔语法中使用 RIP 相对变量引用,如“[RIP + _a]”?)。如何使用 NASM 实现这一目标?
assembly - nasm:在运行时从 rip(指令指针)获取重定位二进制文件的偏移量
我有一个适用于 x86_64 的 multiboot2 兼容 ELF 文件,其中开始符号在start.asm
NASM 程序集文件中定义。multiboot2 标头包含relocatable
标记。
因为 GRUB 不支持 multiboot2 + 可重定位的 ELF(至少在 2021 年 7 月 [ 3 ]),所以我想自己解决一些重定位问题以解决此问题并仅加载静态 ELF。
为此,我需要在运行时在我的第一个条目符号(在 ELF 标头中指定)中获取偏移量,以便手动解决重定位问题。偏移量是指 GRUB 在内存中定位二进制文件的位置与 ELF 文件中符号的静态地址之间的差异。
在我的输入符号中,我处于 64 位长模式。无法直接rip
以 NASM 语法访问,因此我需要某种解决方法。
[ 1 ] [ 2 ] 之类的解决方案不起作用,因为rip
关键字/寄存器在 NASM 中不可用。因此我不能使用
我该如何解决这个问题?
assembly - NASM 如何找到这个标签地址?
我想知道 NASM 如何处理这段代码:
只需让您知道它是由引导加载程序在 0x1000 加载的,并且引导加载程序在跳转到 0x1000(这段代码)之前进入保护模式(设置 GDT 的段覆盖整个内存,设置段寄存器......):
当我在单独的文件中编译这段代码时,NASM如何知道内存中测试标签的地址进行跳转(应该是0x1000 +文件差异)?因为它有效,但我不明白如何。
gcc - 如何使用 nasm 和 ld 生成与位置无关的可执行文件?
我有一个简单的 nasm 代码:
test.nasm
我构建它如下:
然后我尝试运行它:
它给了我这个:
所以我检查了文件头:
它显示了这一点:
但是我可以很容易地使用 GCC 为以下程序创建一个与位置无关的可执行文件:
测试2.c
我用以下方式构建它:
它像这样运行:
那么如何使用而不是共享对象创建与位置无关的可执行文件?nasm
ld
加 1
我检查了test2
ELF 标头。它也是一个共享对象。所以这可能不是问题。(感谢@Nate Eldredge)
那么如何使用ld
生成的目标文件获取与位置无关的可执行文件nasm
?
gcc - 位置无关的可执行文件和固定入口点地址
可以从虚拟地址空间内的任意地址加载和运行与位置无关的 ELF 可执行文件。
我尝试构建以下简单程序:
馅饼.c
构建命令:
可执行文件的 ELF 标头是:
馅饼:
所以入口点地址是固定的。
它是_start
那里的符号:
所以这意味着_start
必须放在0x530
.
这与位置独立不是矛盾的吗?
2021 年 8 月 16 日上午 10 点 44 分添加
我试图在没有-pie
标志的情况下构建相同的程序:
生成的 ELF 头是:
pie_not:
我进一步比较了构建的结果pie
和pie_not
. 它们的二进制文件是相同的。
那么操作系统如何判断哪一个应该被视为与位置无关的代码呢?
添加 2 - 2021 年 8 月 16 日上午 10:56
我想我想通了。似乎 gcc-pie
默认使用。为避免这种情况,我必须-no-pie
明确添加标志。
而生成的ELF头是这样的:
pie_not:
我相信加载器依赖于 ELF 标头中的类型来决定如何处理二进制文件。
linux - 在 PIC(位置无关代码)中编译的可执行文件的行为
我以前在 Linux 中编译共享库时使用了-fPIC
选项,但当时我对 PIC 了解不多,所以我只是把它当作约定来输入。
最近我在wiki和几个网站上读到了PIC,我想我现在理解了一般概念。但是,我发现-fPIC
不仅在编译和链接共享库时包含选项,而且在可执行文件a.out
(例如,我用 C++ 测试了一个简单的 Hello world 程序,有无-fPIC
选项,两者都运行良好,没有任何错误。
在这种情况下,我想知道-fPIC
行为上的差异是什么。我所得到的只是地址和_GLOBAL__sub_I_(sth)
检查的细微差别objdump -t
。-fPIC
另外,我很好奇在使用选项编译可执行文件时是否会有任何有害影响。
提前致谢!
gcc - 在 GCC 中创建和上传 PIC
假设我希望创建将由 MCU 动态加载的与位置无关的代码。
GCC 允许编译 PIC,但我不确定获得最终二进制输出的过程是什么。
为了澄清,假设我已经实现了一个自包含的 C 函数(没有全局变量)。我的 MCU 上有一个单独的 RTOS,它将下载此功能并在特定地址运行它。
编译这个函数并获取二进制图像上传到MCU的过程是什么?在这种情况下,我的链接器脚本会是什么样子?