【问题标题】:Why do I get oveflow in printf? [duplicate]为什么我会在 printf 中溢出? [复制]
【发布时间】:2020-03-10 10:54:48
【问题描述】:

嘿,我必须在汇编中调用 glibc 的一个函数来进行练习。所以我找到了这段代码来调用printf。

section .rodata
    format: db 'Hello %s', 10
    name:   db 'Conrad'

section .text
        global main
        extern printf
    main:
        ; printf(format, name)
        mov rdi, format
        mov rsi, name
        call printf
        ; return 0
        mov rax, 0
        ret

但我得到了错误:

符号 `printf' 导致 R_X86_64_PC32 重定位溢出

编译:

nasm -f elf64 -o test.o test.asm

gcc -o test test.o

执行后出现错误

./测试

【问题讨论】:

  • 将\0 添加到format 和name。
  • 同样的错误
  • @eanmos:这是一个单独的问题。

标签: c assembly


【解决方案1】:

你应该用-no-pie编译你的

here 解释了此错误。引用原帖:

Debian 切换到 64 位模式下的 PIC/PIE 二进制文件,在您的情况下,GCC 正在尝试将您的对象链接为 PIC,但它会在 mov $str, %rdi 中遇到绝对地址。

【讨论】:

  • 那我只有分段错误
  • @JanWolfram 这可能是由于 eanmos 指出的字符串末尾缺少 '\0'
  • :/ 不,这不是错误。对不起,我的知识不好
  • @JanWolfram: 因为你在调用printf 之前没有对齐堆栈。 (并且没有设置 AL=0,因此它会将 XMM regs 保存到其具有对齐存储的寄存器保存区域,因此这种 ABI 违规可能会在实践中崩溃)。
【解决方案2】:

将call printf 更改为call printf@PLT。前者仅在printf 的实际定义在call 指令的±2GB 范围内有效,如果定义在共享库中则无法知道(但如果您使用静态链接,它会起作用)。 “溢出”告诉您,需要达到 64 位的相对地址在 32 位调用指令偏移量中溢出。

通过使用printf@PLT,您将获得一个在链接时静态解析为 PLT 中的 thunk 的相对地址,该地址加载并跳转到函数定义的地址,在动态链接时解析。

正如 Maxime B. 所指出的,format 和 name 的地址负载对于与位置无关的代码也不正确。它们应该以“rip-relative”形式加载,但看起来您正在为 asm 使用奇怪的“Intel 语法”,我不知道如何用这种语法编写它。正如 Maxime B. 建议的那样,您可以使用 -fno-pie 构建,但更好的是找出修复代码的方法,这样它就不会依赖于链接到特定的固定地址。

【讨论】:

  • 对我来说@plt 是未定义的
  • @JanWolfram:可能是 nasm 期望它以某种奇怪的方式编写(同样,我不熟悉它使用的语法),或者可能只是你引入了额外的空格或其他东西否则语法错误。
  • @JanWolfram 对于 NASM,您可能需要考虑 call printf wrt ..plt。 call printf@plt 是 GNU 汇编语法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 2022-11-07
  • 2020-04-29
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多