Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this movq instruction work on linux and not osx?

The following assembly code gives an error when running as on OSX 10.9.4, but works successfully on Linux (Debian 7.6). In particular, the movq instruction doesn't seem to like the label argument.

$ cat test.S
.globl _main
_main:
    movq $_main, %rax
    ret

Here is the error:

$ as -o test.o test.S 
test.S:3:32-bit absolute addressing is not supported for x86-64
test.S:3:cannot do signed 4 byte relocation

Changing $_main in line 3 to a literal like $10 works fine.

The code had to be modified in a very minor way to get it to run on Linux - by simply removing the underscores from the labels.

$ cat test.S
.globl main
main:
    movq $main, %rax
    ret

It's pretty easy to independently verify that the code does work on Linux:

$ as -o test.o test.S
$ gcc -o test.out test.o
$ ./test.out

Please ignore that the code doesn't really do much of anything, I've intentionally trimmed it down as much as possible to demonstrate the error.

I've looked quite a bit into using LEA (load effective address), but before I make that change I'd like to understand the difference - why does it work on Linux and not OSX?

like image 732
josh cough Avatar asked Sep 12 '14 01:09

josh cough


1 Answers

You are correct about the movq instruction not being able to reference the absolute address. This is in part due to the OS X ABI Mach-O format which uses relocatable addressing for symbols.

A Program that is compiled as a position-independent executable (PIE) generally cannot reference an absolute virtual address in the same manner as movq $_main, %rax does. Instead, Global Offset Tables are called upon, which allow position relative code (PC-rel) and position-independent code (PIC) to extract global symbols at their current absolute address location. Demonstrated below, GOTPCREL(%rip)creates an interpretation of lea rdi, _msg:

PC-rel code referencing it's Global Offset Table:

.globl _main
_main:

    movq     _main@GOTPCREL(%rip), %rax
    sub      $8, %rsp
    mov      $0, %rax
    movq     _msg@GOTPCREL(%rip), %rdi
    call     _printf
    add      $8, %rsp
    ret

.cstring
_msg:

    .ascii  "Hello, world\n"

Mac OS X Mach-O Assembler:

$ as -o test.o test.asm

Apple's version of GCC:

$ gcc -o test.out test.o

Output:

$ ./test.out
Hello, world
like image 56
l'L'l Avatar answered Nov 02 '22 13:11

l'L'l