【问题标题】:Call libc function from assembly从程序集中调用 libc 函数
【发布时间】:2019-08-28 20:49:29
【问题描述】:

我在程序集中定义了一个调用 libc 函数 (swapcontext) 的函数。我从我的 C 代码中调用该函数。为了创建可重现的示例,我使用“puts”代替:

foo.S:

.globl foo 
foo:
    call puts
    ret

test.c:

void foo(char *str);

int main() {
    foo("Hello World\n");
    return 0;
}

编译:

gcc test.c foo.S  -o test

这编译得很好。然而,反汇编结果二进制显示链接器没有插入有效的调用指令:

objdump -dR:

0000000000000671 <foo>:
 671:   e8 00 00 00 00          callq  676 <foo+0x5>
            672: R_X86_64_PC32  puts@GLIBC_2.2.5-0x4
 676:   c3                      retq   
 677:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
 67e:   00 00 

0000000000000530 <puts@plt>:
 530:   ff 25 9a 0a 20 00       jmpq   *0x200a9a(%rip)        # 200fd0 <puts@GLIBC_2.2.5>
 536:   68 00 00 00 00          pushq  $0x0
 53b:   e9 e0 ff ff ff          jmpq   520 <.plt>

执行:

./test1: Symbol `puts' causes overflow in R_X86_64_PC32 relocation
Segmentation fault

有什么想法吗?

【问题讨论】:

  • objdump -dR test 可能很有启发性。另外,在foo 的定义中不需要ret 吗?还有,swapcontext有异常的控制流,需要特别小心才能安全调用。
  • 似乎你 OBJDUMP'ed 一个具有重定位的目标文件。尝试使用 -r 选项 OBJDUMPing 最终可执行文件或 OBJDUMP .o 文件以显示重定位条目。
  • minimal reproducible example,拜托。这不会重现行为,并且在运行时不起作用。
  • ... 那么# 200fd0 &lt;swapcontext@GLIBC_2.2.5&gt; 是什么?
  • 我已经更新了原始示例,通过将 puts 与存储在 %rdi 中的参数一起使用使其有效。我在运行时也指出了失败。

标签: c assembly extern libc


【解决方案1】:

对于您更新的完全独立的问题,它取代了您关于拆卸.o 的问题:

semi-related: Unexpected value of a function pointer local variable 提到链接器在非 PIE 中为您将 puts 的引用转换为 puts@plt (因为如果静态链接可以让您获得高效的代码),但不是在饼图。

libc 被映射到距离主可执行文件超过 2GiB 的位置,因此 call rel32 无法访问它。

另请参阅Can't call C standard library function on 64-bit Linux from assembly (yasm) code,它显示了用于从 PIE 可执行文件调用 libc 函数的 AT&T 和 NASM 语法,可以通过带有call *puts@gotpcrel(%rip) 的 PLT call puts@pltgcc -fno-plt 样式。

【讨论】:

  • 感谢您提供的链接,这些链接完全简洁地解释了!
  • 至于原始帖子的更新,我试图创建一个有效的示例(与我最初调用 swapcontext 的示例相反),并且不仅提供反汇编的输出,而且提供最终的输出失败我也遇到了。感谢您的耐心等待!
【解决方案2】:

您似乎正在使用重定位来反汇编目标文件。

重定位是链接器在加载文件时解析的存根。

要正确查看重定位和符号名称,请使用objdump -dr testobjdump -dR test

输出将与此类似:

0000000000000000 <foo>:
   0:   e8 00 00 00 00          callq  5 <foo+0x5>
                        1: R_X86_64_PLT32       swapcontext-0x4

您也可以考虑在foo 的末尾添加一条ret 指令,以防swapcontext 出错。

如您的 objdump -dR 输出所示,这两个都指的是 libc 函数:

            670: R_X86_64_PC32  swapcontext@GLIBC_2.2.5-0x4
        # 200fd0 <swapcontext@GLIBC_2.2.5>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    相关资源
    最近更新 更多