Nasm - Symbol 'Printf' Causes Overflow in R_X86_64_Pc32 Relocation

Compile error: relocation R_X86_64_PC32 against undefined symbol

From http://www.nasm.us/xdoc/2.10rc8/html/nasmdoc9.html#section-9.2.5:

To call an external routine, you must use another special PIC relocation type, WRT ..plt. This is much easier than the GOT-based ones: you simply replace calls such as CALL printf with the PLT-relative version CALL printf WRT ..plt.

so instead of

; ...
call printf

use

; ...
call printf WRT ..plt

and compile and link as normal.

BTW, "WRT" means "With Respect To ...", i.e, "in the context of ..."

Relocation R_X86_64_32S against .data cannot be used when making a shared object (64 bit NASM + gcc)

rbp is a callee-saved register hence you need to preserve it. You are not changing it so you don't have to push/pop it here. However you need to preserve 16 byte stack alignment, and a push is a simple way to do that. You could have used any other register, or even sub rsp, 8.

mov rdi, hi should be lea rdi, [rel hi].

Functions are called through the PLT not the GOT, and not through a pointer. Just do call puts ..wrt plt.

As such, the following should work:

global main
extern puts

section .data
hi db 'hello', 0

section .text
main:
push rbp
lea rdi, [rel hi]
call puts wrt ..plt
pop rbp
ret

Assembling with GCC causes weird relocation error with regards to .data

The way to get around this error is to generate a no-pie (Non Position Independent executable) executable :

gcc -no-pie test.s -o test

The reason for this behaviour is as explained by @Ped7g :


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.

Can't call C standard library function on 64-bit Linux from assembly (yasm) code

The 0xe8 opcode is followed by a signed offset to be applied to the PC (which has advanced to the next instruction by that time) to compute the branch target. Hence objdump is interpreting the branch target as 0x671.

YASM is rendering zeros because it has likely put a relocation on that offset, which is how it asks the loader to populate the correct offset for puts during loading. The loader is encountering an overflow when computing the relocation, which may indicate that puts is at a further offset from your call than can be represented in a 32-bit signed offset. Hence the loader fails to fix this instruction, and you get a crash.

66c: e8 00 00 00 00 shows the unpopulated address. If you look in your relocation table, you should see a relocation on 0x66d. It is not uncommon for the assembler to populate addresses/offsets with relocations as all zeros.

This page suggests that YASM has a WRT directive that can control use of .got, .plt, etc.

Per S9.2.5 on the NASM documentation, it looks like you can use CALL puts WRT ..plt (presuming YASM has the same syntax).



Related Topics



Leave a reply



Submit