I was trying to write an OpenGL/GLFW application with nasm assembly, and I decided to link using gcc since ld was giving me some trouble, but it kept giving me the same error recompile with -fPIE
, which I did but that did not change the output in the slightest. This was the error produced:
/usr/bin/ld: Main.o: relocation R_X86_64_32S against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
These are the commands that I have tried:
$ nasm -f elf64 Main.asm
$ gcc -nostartfiles Main.o -lc -glfw -lGL -o Application
$ gcc -nostartfiles Main.o -lc -glfw -lGL -o Application -fPIE
$ gcc -fPIE -nostartfiles Main.o -lc -glfw -lGL -o Application
$ gcc Main.o -o Application -glfw -lGL -lc
$ gcc Main.o -o Application -glfw -lGL -lc -fPIE
$ gcc -fPIE Main.o -o Application -glfw -lGL -lc
and yes, I have changed _start
to main
when needed (when I changed assembler)
This is the assembly code if it mattered:
global _start
%define GL_COLOR_BUFFER_BIT 0x00004000
%define GL_TRIANGLES 0x0004
extern glfwInit
extern glfwTerminate
extern glfwCreateWindow
extern glfwDestroyWindow
extern glfwMakeContextCurrent
extern glfwSwapBuffers
extern glfwPollEvents
extern glfwWindowShouldClose
extern glClear
extern glBegin
extern glVertex2f
extern glEnd
section .data
title: db "OpenGL/ASM", 0x00
section .bss
window resq 0x1
section .text
_start:
call glfwInit
mov rdi, 0x500
mov rsi, 0x2D0
mov rdx, title
mov rcx, 0x00
mov r8, 0x00
call glfwCreateWindow
mov [window], rax
mov rdi, [window]
call glfwMakeContextCurrent
gameLoop:
mov rdi, GL_COLOR_BUFFER_BIT
call glClear
mov rdi, GL_TRIANGLES
call glBegin
mov rdi, __float32__(-0.5)
mov rsi, __float32__(-0.5)
call glVertex2f
mov rdi, __float32__( 0.5)
mov rsi, __float32__(-0.5)
call glVertex2f
mov rdi, __float32__( 0.0)
mov rsi, __float32__( 0.5)
call glVertex2f
call glEnd
mov rdi, [window]
call glfwSwapBuffers
call glfwPollEvents
mov rdi, [window]
call glfwWindowShouldClose
cmp rax, 0x00
je gameLoop
exit:
mov rdi, [window]
call glfwDestroyWindow
call glfwTerminate
mov rax, 0x3C
mov rdi, 0x00
SOLVED
Thanks to @xiver77, he pointed out that gcc was using relative addressing in this case, that was part of the issue, but also what allowed this to work finally was using the procedural linkage table (using wrt ..plt
statements on every C function call). This is the final code
global _start
%define GL_COLOR_BUFFER_BIT 0x00004000
%define GL_TRIANGLES 0x0004
extern glfwInit
extern glfwTerminate
extern glfwCreateWindow
extern glfwDestroyWindow
extern glfwMakeContextCurrent
extern glfwSwapBuffers
extern glfwPollEvents
extern glfwWindowShouldClose
extern glClear
extern glBegin
extern glVertex2f
extern glEnd
section .data
title: db "OpenGL/ASM", 0x00
section .bss
window resq 0x1
section .text
_start:
call glfwInit wrt ..plt
mov rdi, 0x500
mov rsi, 0x2D0
mov rdx, title
mov rcx, 0x00
mov r8, 0x00
call glfwCreateWindow wrt ..plt
mov [rel window], rax
mov rdi, [rel window]
call glfwMakeContextCurrent wrt ..plt
gameLoop:
mov rdi, GL_COLOR_BUFFER_BIT
call glClear wrt ..plt
mov rdi, GL_TRIANGLES
call glBegin wrt ..plt
mov rdi, __float32__(-0.5)
mov rsi, __float32__(-0.5)
call glVertex2f wrt ..plt
mov rdi, __float32__( 0.5)
mov rsi, __float32__(-0.5)
call glVertex2f wrt ..plt
mov rdi, __float32__( 0.0)
mov rsi, __float32__( 0.5)
call glVertex2f wrt ..plt
call glEnd wrt ..plt
mov rdi, [rel window]
call glfwSwapBuffers wrt ..plt
call glfwPollEvents wrt ..plt
mov rdi, [rel window]
call glfwWindowShouldClose wrt ..plt
cmp rax, 0x00
je gameLoop
exit:
mov rdi, [rel window]
call glfwDestroyWindow wrt ..plt
call glfwTerminate wrt ..plt
mov rax, 0x3C
mov rdi, 0x00
And to assemble and link:
$ nasm -f elf64 Main.asm
$ gcc -nostartfiles Main.o -o Application -lglfw -lGL -lc -fPIE
$ ./Application