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
How to Install Xvfb (X Virtual Framebuffer) on Redhat 6.5
How to Respond to Prompts in a Linux Bash Script Automatically
How to Get Docker Container Id from Within the Container with Cgroup V2
How to Use Stdin with Caption in Imagemagick
Why File Is Accessible After Deleting in Unix
What's the Point of Using Busybox in a Low Ram Embedded System
Run Shell Script When Saving a File in Sublime Text 3
Logcat Show Invisible Messages in Eclipse Mars
Advice Regarding Installing Arm Toolchain on Ubuntu Vm (64Bit)
Move Files That Are 30 Minutes Old
Paste Two Text Lists (One List a File) into One List Separated by Semicolon
How to Create an Rs256 Jwt Assertion with Bash/Shell Scripting
X86 Memory Access Segmentation Fault