Home > Software engineering >  Error while trying to compile nasm object code with gcc
Error while trying to compile nasm object code with gcc

Time:09-14

I'm trying to use the printf function in nasm. My program is set up like this:


section .text
global main
extern printf
main:
  endbr64
  push rbp
  
  mov rdi, [array   1 * 4]
  mov rsi, specifer
  mov rax, 0
  call printf

  pop rbp
  mov rax, 0
  ret
section .data
  array db 1,2,3,4,5,6,7,8,9,1
  arrlen equ $ - array
  specifer db '%d',0xa,0
  speclen equ $ - specifer

I am running these commands to compile:

nasm -f elf64 arrays.asm
gcc arrays.o

But when I do, I get this error:

arrays.asm:6: warning: label alone on a line without a colon might be in error [-w orphan-labels]
/usr/bin/ld: arrays.o: relocation R_X86_64_32S against `.data' can not be used when making a PIE object; recompile with -fPIE
collect2: error: ld returned 1 exit status

I tried recompiling with -fPIE but I got the literal same exact error. What am I doing wrong?

Here are the versions of the tools I am using:

NASM: 2.14.02
GCC: 9.4.0
ld: 2.34

My goal at this point is just to get it to compile. I have tried using LD instead of GCC, but I just kept getting a segfault.

CodePudding user response:

Update your version of nasm or get rid of the endbr64 instruction to fix the first error. Your version of nasm it too old to support it. As you do not seem to enable control flow enforcement anyway, it's not really important to have that instruction in your code anyway.

The error message is misleading; you don't have a compilation step in your code. Usually the compiler generates assembly code. If you did not instruct the compiler to obey the PIE (position independent executable) rules but then try to link a PIE binary, the linker gives you this hint. However, when you write in assembly, you are the compiler and you need to obey these rules yourself.

There are two solutions: either link with -no-pie to disable generation of a PIE binary, or fix your code to confirm to PIE rules. The second fix is done by not referencing the absolute address of any symbol from code. The offending instruction is mov rsi, specifer which loads the (absolute) address of specifer into rsi. Replace it with lea rsi, [rel specifer] to instead use rip-relative addressing to conform to the rules. You'll also have to add a rel keyword to mov rdi, [array 1 * 4] to make it use the same rip-relative addressing mode.

You can use the default rel directive to always use such an addressing mode if possible.

Relevant canonical questions/answers:

  • Related