6

I want to compile the following program on Linux:

    .global _start
    .text
_start:
    mov $1,   %rax
    mov $1,   %rdi
    mov $msg, %rsi
    mov $13,  %rdx
    syscall
    mov $60,  %rax
    xor %rdi, %rdi
    syscall
msg:
    .ascii "Hello World!\n"

However, it gives me the following linker error:

$ gcc -nostdlib hello.s
/usr/bin/ld: /tmp/ccMNQrOF.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

I figured that the reason it doesn't work is because gcc is using -pie to generate a shared object by default. Thus, using -no-pie fixes it:

$ gcc -no-pie -nostdlib hello.s
$ ./a.out
Hello World!

How do I configure gcc to use -no-pie by default? I'm using Arch Linux.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299

2 Answers2

4

I guess just don't configure gcc with --enable-default-pie.

See this blog post: http://nanxiao.me/en/gccs-enable-enable-default-pie-option-make-you-stuck-at-relocation-r_x86_64_32s-against-error/, and Arch patch that enabled pie by default: https://git.archlinux.org/svntogit/packages.git/commit/trunk?h=packages/gcc&id=5936710c764016ce306f9cb975056e5b7605a65b.

ks1322
  • 33,961
  • 14
  • 109
  • 164
  • So the solution is to always use `-no-pie`? It seems that if I configure gcc without `--enable-default-pie` it might break something. – Aadit M Shah Mar 05 '18 at 19:05
  • 2
    gcc configured with `--enable-default-pie` is a security hardening strategy as it builds position independent binaries by default. Building no pie binaries by default could be less secure, but it should not break anything. – ks1322 Mar 06 '18 at 10:28
1

For this purpose you have to re-compile gcc to disable default PIE. Or you will need -no-pie each time you want to compile position dependent assembly code.

However, just for the example you provided, a better way is to use relative addressing like label_name(%rip).

Relative addressing allows PIE to function properly.

I modified yours into this: (see the leaq line)

.global _start
.text
_start:
    movq $1,        %rax
    movq $1,        %rdi
    leaq msg(%rip), %rsi
    movq $13,       %rdx
    syscall
    movq $60,       %rax
    xorq %rdi,      %rdi
    syscall
.section .rodata
msg:
    .ascii "Hello World!\n"

(I added .section .rodata just because usually this should be put into rodata section. Your version works fine, but output of objdump -d contains meaningless instructions from msg label.)

RabidBear
  • 182
  • 1
  • 6