How can I call printf normally in assembly without @PLT but just call printf with -l option in gcc with standard library,

巧了我就是萌 提交于 2020-03-26 06:48:09

问题


I want to call printf in assembly and link it using gcc -l option with standard library, But it says:

  Symbol `printf' causes overflow in R_X86_64_PC32 relocation
  Segmentation fault (core dumped)

this is How i compile:

   gcc mod.s -l:libc.so -o mod

when I replace libc.so with libc.a, It still shows Sementation fault

 .file  "mod.c"
.text
.section    .rodata
.LC0: 
   .string  "%d"
.text
.globl  main
.type   main, @function
main:
pushq   %rbp
movq    %rsp, %rbp
subq    $16, %rsp
movl    $3, -8(%rbp)
movl    $2, -4(%rbp)
movl    -8(%rbp), %eax
cltd
idivl   -4(%rbp)
movl    %edx, -4(%rbp)
movl    -4(%rbp), %eax
movl    %eax, %esi
leaq    .LC0(%rip), %rdi
movl    $0, %eax
call    printf
movl    $0, %eax
leave
ret
.size   main, .-main
.ident  "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0"
.section    .note.GNU-stack,"",@progbits

When I add @PLT after printf it goes right, But I just want to use -l in gcc


回答1:


You don't need -llibc, gcc already links that by default.

The problem here is that modern GCC defaults to making a PIE executable (position-independent), which is an ELF "shared object". The linker treats it more like a library and doesn't automatically create PLT stubs for calls to undefined symbol names. (I don't think this behaviour is necessary, ld could let you do this.)

The easy solution here is gcc -no-pie -fno-pie -o mod mod.s

Then you can write call printf and it Just Works.

With that command line, you'll create a dynamically-linked ELF executable. The linker rewrites your call printf to call printf@plt for you (disassemble it and see, with objdump -drwC to print relocations.). The offset between the libc load address and your code's address is not a link-time constant. (And could be larger than 2^32 anyway).

If you use -static, the call printf resolves to the actual address of the printf definition copied into your executable from libc.a.


I'm guessing that the option of building a static or dynamic executable from the same source is why ld is willing to rewrite calls to PLT stubs for ELF executables but not ELF shared objects (like PIE executables).

See 32-bit absolute addresses no longer allowed in x86-64 Linux? for more about PIE.

The other way to call shared library functions is call *printf@GOTPCREL(%rip), like gcc does if you compile with -fno-plt. This bypasses the PLT entirely, just doing a call through the function pointer in the GOT (which you access with a RIP-relative addressing mode).

The NASM version of this is call [rel printf wrt ..got]
as an alternative to call printf wrt ..plt. Can't call C standard library function on 64-bit Linux from assembly (yasm) code



来源:https://stackoverflow.com/questions/56404855/how-can-i-call-printf-normally-in-assembly-without-plt-but-just-call-printf-wit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!