重定位 R_X86_64_8 针对未定义的符号 `ELF' 在制作 PIE 对象时不能使用

relocation R_X86_64_8 against undefined symbol `ELF' can not be used when making a PIE object

加油:

    .text
    .globl main
main:
    xor %eax, %eax
    lea str(%rip), %rdi
    call printf
    call exit

str: .byte 0x7F, "ELF", 1,1,1,0

我认为 .byte 指令可以像 nasm

中那样连接
db      0x7F, "ELF", 1, 1, 1, 0         ;   e_ident

来源:http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

在 GAS 语法中,"ELF" 是对符号名称 ELF 的符号引用,而不是多字符字符串。在 .byte 指令的上下文中,它只是在寻找一个数字,而不是一个可能的字符串。

并且由于您将它用作 .byte 值列表的一个元素,它要求绝对地址的低字节,因此需要 .._8 重定位。意思和NASM的db完全不一样。

在 GAS 中,当它需要一个数字时,'E' 被允许作为 ASCII 常量,但 "E" 不是。例如mov $"E", %eax会给你一个R_X86_64_32 E搬迁。

单引号也不起作用。单字符文字确实可以用作数字,例如作为立即数 mov $'a', %eax。但与 NASM 不同的是,GAS 不支持多字符字面量。所以 mov eax, 'Hey!' 在 NASM 中有效,但 mov $'Hey!', %eax 在 GAS 中无效。

AFAIK,GAS 只允许您使用多个 ASCII 字符序列作为 .ascii / .asciz 指令或相关 .string / .string16 的文字数据/.string32 窄字符或宽字符指令。 (GAS manual)


您有几个选择:

str: .byte 0x7F
     .ascii "ELF"         # separate directives
     .byte 1,1,1,0
str: .byte 0x7F, 'E', 'L', 'F', 1,1,1,0   # separate character literals
str: .asciz "\x7F\ELF\x1\x1\x1"         # hex escapes in a string

\E 阻止整个 7FE 被视为一个十六进制数。如果没有额外的反斜杠,它会组装成 fe 4c 46 01...(坏)而不是所需的 7f 45 4c 46 01...(好)。

IDK 如果有更好/更清洁的方法来做到这一点;也许是 3 位八进制转义序列?


该教程使用 NASM 的平面二进制输出模式手动创建 ELF 程序头(对于 32 位可执行文件)。我猜你出于某种原因正在尝试创建一个打印该输出的 64 位程序?它恰好不包含任何 0% 字节,所以是的,您可以使用 printf.

输出它

将教程移植到 GAS 语法的更直接方法是使用 ld 到 link 到 as 输出到平面二进制文件。 How to generate plain binaries like nasm -f bin with the GNU GAS assembler?

或使用 objcopy.o 或可执行文件的 .text 部分复制到平面二进制文件中。如果您使用 objcopy.

,请确保所有内容都在 .text 部分中