【发布时间】:2020-01-26 02:43:09
【问题描述】:
我正在使用 NASM 编译器并与 ld 链接在 Linux 中编译 NASM 64 位共享对象。它使用以下字符串编译为目标文件:
sudo nasm -felf64 Test_File.asm
我与 ld 链接:
sudo ld -shared Test_File.o -o Test_File.so
我收到以下错误:
Relocation R_X86_64_32S against '.data' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output
很遗憾,NASM 编译器没有 -fPIC 选项。
在阅读了许多关于在 Linux 中为 64 位共享库编写与位置无关的代码的资源后,我非常了解这个问题,但我仍然不清楚我需要对位置进行哪些指令更改- 独立于 64 位 NASM。例如,是否所有涉及命名变量的指令都必须是“rel”——例如,movsd xmm0,[rel abc] 而不是 movsd xmm0,[abc]?我知道 R_X86_64_32S 表示 32 位寻址,但我的代码中没有任何 32 位寻址。
此外,32 位和 64 位在如何编写位置无关代码方面存在显着差异,并且一些资源仅集中在 32 位代码上。甚至 NASM 手册中的第 9.2 节编写 NetBSD/FreeBSD/OpenBSD 和 Linux/ELF 共享库也不清楚如何将 64 位代码更改为与位置无关的代码。该部分侧重于 32 位代码(使用全局偏移表),而不是(基于其他研究)用于 64 位代码。
根据需要,文件以 [BITS 64] 和 [default rel] 开头。
数据段声明为section .data align=16
.data 部分中的每个变量都定义为 dq,例如 number: dq 0。
文件顶部包含以下格式的导出:全局 ABC:function。
我怀疑只有数据移动指令会受到影响——数学指令不会。对于 realloc 的外部调用,我添加了 wrt ..plt 特殊符号,但我仍然得到相同的错误。
这是我的问题:
是否所有的 mov 指令都需要用“rel”关键字重写,例如 mov rax,[rel abc] 而不是 mov rax,[abc]?
是否需要更改 lea 指令(例如 lea rdi,[rel abc])?
还有其他需要特殊处理的指令类型吗?
我不会在此处发布整个(非常长的)nasm 代码列表,因为我不是在寻找逐行分析。我只想知道 64 位相对寻址需要重写哪些指令类型(例如 mov、cmp、jmp、lea),以及如何重写。它是否只涉及对数据段中定义的变量的访问(例如,mov rcx,[abc],其中 abc 在数据段中定义为 abc:dq 0)。
总而言之,我的问题是:我需要对 64 位 NASM 的位置无关代码进行哪些更改,因为 NASM 编译器没有 fPIC 选项?我当然不是指逐行,而是需要添加或重写哪些类型的指令。
非常感谢。
【问题讨论】: