Unrelocated address when linking with link.exe

Viewed 330

Problem

When I compile my assembly code with as (binutils) and link using link.exe (Visual Studio 2015) the program crashes because of an unrelocated address.

When linking with gcc (gcc hello-64-gas.obj -o hello-64-gas.exe) the program runs correctly without crash though. Am I correctly assuming that the object file generated by as should be compiler independent, since abi compatibility problems are in the hands of the assembly code writer? Since I am a beginner, any explanation of my mistakes/incorrect assumptions is appreciated.

Platform

  • Windows 10, 64 bit
  • Linker: Visual Studio 2015 using the native command tools command prompt (x64)
  • Compiler: as from MinGW-w64

Example

The following code does not link correctly:

# hello-64-gas.asm    print a string using printf
# Assemble:   as hello-64-gas.asm -o hello-64-gas.obj --64
# Link:       link -subsystem:CONSOLE hello-64-gas.obj -out:hello-64-gas.exe libcmt.lib libvcruntime.lib libucrt.lib legacy_stdio_definitions.lib
.intel_syntax noprefix

.global main

# Declare needed C  functions
.extern printf

.section .data
msg:       .asciz "Hello world"
fmt:       .asciz "%s(%d; %f)\n"
myDouble:   .double 2.33, -1.0

.text
main:
    sub rsp, 8*5
    mov rcx, offset flat: fmt
    mov rdx, offset flat: msg
    mov r8, 0xFF
    mov r9, offset flat: myDouble
    mov r9, [r9]
    movq xmm4, r9
    call printf
    add rsp, 8*5

    mov rax, 0
    ret

When debugging it seems mov r9, offset flat: myDouble is not relocated: mov r9,18h, where 18h would be correct if the .data section where at position zero. Looking at the relocation table with objdump -dr hello-64-gas.obj yields:

...
19:   49 c7 c1 18 00 00 00    mov    $0x18,%r9
                      1c: R_X86_64_32S        .data
...

Variation (workaround?)

Replacing mov with movabs seems to work:

# hello-64-gas.asm    print a string using printf
# Assemble:       as hello-64-gas.asm -o hello-64-gas.obj --64
# Link:           link -subsystem:CONSOLE hello-64-gas.obj -out:hello-64-gas.exe libcmt.lib libvcruntime.lib libucrt.lib legacy_stdio_definitions.lib
.intel_syntax noprefix

.global main

# Declare needed C  functions
.extern printf

.section .data
msg:       .asciz "Hello world"
fmt:       .asciz "%s(%d; %f)\n"
myDouble:   .double 2.33, -1.0

.text
main:
    sub rsp, 8*5
    movabs rcx, offset flat: fmt
    movabs rdx, offset flat: msg
    mov r8, 0xFF
    movabs r9, offset flat: myDouble
    mov r9, [r9]
    movq xmm4, r9
    call printf
    add rsp, 8*5

    mov rax, 0
    ret

This does somehow run correctly when linked using link.exe.

1 Answers
Related