16

I am trying to create a simple program in nasm that should display the letter a. however, It is giving me a Segfault and saying this:

./a.out: Symbol `printf' causes overflow in R_X86_64_PC32 relocation
Segmentation fault (core dumped)

Basically, I am trying to move the value 0x61 (hex for letter a) into memory address 1234, and then pass that as an argument to printf. Here is my exact code:

extern printf
section .text
global main
main:
push rbp
mov rax,0
mov qword [1234], 0x61 ; move 0x61 into address 1234
mov rdi, qword [1234] ; mov address 1234 into rdi
call printf ; should print the letter a
pop rbp
mov rax,0
ret

I am running Linux x86_64

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Unknown
  • 181
  • 1
  • 1
  • 6
  • memory address 1234 is almost certainly not writeable on Linux. `Printf` takes a format string as the first parameter. Don't see any such format string in this code. – Michael Petch Jan 03 '18 at 05:02
  • The call to `printf` in 64-bit code that is position independent should probably look like `call [printf wrt ..got]` – Michael Petch Jan 03 '18 at 05:07
  • printf can be called without format strings – Unknown Jan 03 '18 at 05:13
  • There is always a format string. If you just print a string the format is the actual string. If you want to print a single character you would use a format specifier of `"%c"` and the second parameter is the character to print. Or are you trying to create a NUL terimated string with a single character in it? – Michael Petch Jan 03 '18 at 05:19
  • `mov rdi, qword [1234] ` doesn't actually move the address of 1234 into _RDI_ it moves the 8 bytes at address 1234 to RDI – Michael Petch Jan 03 '18 at 05:27
  • There was a question in the past few days oddly reminiscent of your question. Is this a homework task? If so, What is the homework task you have? (What is it exactly what they want)? The previous question required printing the letter `a` without use the `.data` section for example. – Michael Petch Jan 03 '18 at 05:29
  • 2
    Something like this may work: `default rel ; Use RIP relative addressing by default.` `main: xor eax, eax` `push 0x61 ; Push 0x61 onto stack followed by 7 bytes of 0x00` `lea rdi, [rsp] ; Address of character a on stack` `call [printf wrt ..got]` `add rsp, 8 ; restore stack` `xor eax,eax ; return 0` `ret` – Michael Petch Jan 03 '18 at 05:54
  • How exactly are you linking this? Are you using a linker that doesn't generate a PLT for `printf`, and instead trying to directly resolve the symbol after dynamic linking? Unless you link some startup code that maps the low page of virtual memory, storing then reloading from `[1234]` will fault before you ever get to printf, of course. Use a debugger to see that. – Peter Cordes Jan 03 '18 at 06:16

2 Answers2

19

try compiling with -no-pie, check out these posts for explanation: Assembling with GCC causes weird relocation error with regards to .data

in short:

Debian switched to PIC/PIE binaries in 64-bits mode & GCC in your case is trying to link your object as PIC, but it will encounter absolute address in mov $str, %rdi.

brian
  • 509
  • 3
  • 14
  • It's not just 64-bit mode. Even `gcc -m32` makes PIE executables by default, which is nasty because that ties up `ebx` with a GOT pointer. (No RIP-relative addressing in 32-bit mode.) And BTW, this won't make the OP's program work, because it's trying to store / reload from `[1234]`, which will definitely segfault! – Peter Cordes Mar 19 '18 at 02:30
  • 1
    Related: [32-bit absolute addresses no longer allowed in x86-64 Linux?](https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux) also explains the default `-pie` stuff. – Peter Cordes Mar 19 '18 at 02:32
5

Full credit to https://stackoverflow.com/users/3062591/brian

for figuring out how to get this to work. If you're like me and very new to nasm OR if for some reason you're new to nasm and have done little to nothing with gcc then you're going to need to run the command:

nasm -felf64 YOUR_FILE.asm && gcc -no-pie YOUR_FILE.o && ./a.out

I was able to get this using a

call printf

without needing to change it to

printf wrt ..got

which had on previous attempts with some NASM introductory examples but not all.

  • It's `call [rel printf wrt ..got]` to use the `gcc -fno-plt` style of calling; the square brackets are important for NASM / YASM syntax. [Can't call C standard library function on 64-bit Linux from assembly (yasm) code](https://stackoverflow.com/a/52131094) – Peter Cordes Apr 17 '21 at 00:16