Assembling with GCC causes weird relocation error with regards to .data - gcc

This is an issue that didn't used to ever occur. I'm pretty convinced it's probably an issue with my package repos (I recently reinstalled my Arch system and this has only just started happening).
I wrote a small hello world in x86_64:
.data
str: .asciz "Test"
.text
.globl main
main:
sub $8, %rsp
mov $str, %rdi
call puts
add $8, %rsp
ret
and then I attempt to assembly and link using GCC - like I have done many times in the past - with, simply:
gcc test.s -o test
and then this error is outputted:
/usr/bin/ld: /tmp/ccAKVV4D.o: relocation R_X86_64_32S against `.data' 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
This error has never occured for me ever. I've tried to fix the issue by googling the same error message but it comes up with things that are so specific whereas I'd consider this a general issue. I've tried reinstalling base-devel and the entire GCC toolchain. I dunno what else I can do (please don't suggest using nasm, that's heresy).
I'd like to think I'm missing something obvious but I've used GCC for my assembly needs for a long time.

The way to get around this error is to generate a no-pie (Non Position Independent executable) executable :
gcc -no-pie test.s -o test
The reason for this behaviour is as explained by #Ped7g :
Debian switched to PIC/PIE binaries in 64-bits mode & GCC in your case is trying to link your object as PIC, but it will encounter absolute address in mov $str, %rdi.

Related

Why is LLVM linker complaining about BRANCH relocation width?

I'v been trying to assemble and link some x86_64 assembler using llvm-mc (13.0.1) and lld (13.0.1) on macos (12.5). I'm using the following procedure to assemble and link:
llvm-mc --filetype=obj -g -o test.o test.s
ld64.lld -arch x86_64 -platform_version macos 12.0.0 12.0.0 -e start -o test test.o
Today I got an error that I don't understand:
ld64.lld: error: BRANCH relocation has width 1 bytes, but must be 4 bytes at offset 1 of __TEXT,__text in test.o
I couldn't find an explanation of this error. Google tells me nothing, and I couldn't find the error by searching the llvm source.
Figuring it has something to do with jumps, I commented out code until the error went away, then worked backwards to make a minimum example showing the issue:
.text
.globl start
start:
main:
endloop:
loop main
The key detail is the endloop label between the loop instruction and the label main to which we are looping. If I comment out the main: label, I don't get the error.
Questions:
Anybody know what this error message means?
How can I fix the issue?
Where are the error messages for llvm's lld documented?

Compiling error whilst using command from NASM and mingw

I want to play a bit with assembly. To get started I've created a little asm script and tried to compile it. In the first step everything went great:
nasm -felf64 hello.asm
But when I tried to use
ld -o hello.o hello
from MinGW an error occured:
hello.o: file not recognized: File format not recognized
What can I do to fix this problem? I've tried it with gcc as well but then the same error plus one other error occurs.
MinGW creates binaries targeting Windows. Windows does not support ELF binaries (or does it? with Windows subsystem for Linux?). Anyway, ld in MinGW will expect that you provide binaries in win64 format not elf64.
nasm -fwin64 hello.asm will most likely work.
No it won't work because I just saw your code, and you are using Linux syscalls under Windows.
Write,
mov rcx, 69
call ExitProcess
instead of,
mov rax, SYS_EXIT
mov rdi, 69
syscall
Leave a comment if it doesn't work.

GNU Assembler in Windows Subsystem for Linux fail

I would like to compile "Hello World" in Windows Subsystem for Linux (WLS) with Debian.
.text
.global _start
_start:
movl $len,%edx
movl $msg,%ecx
movl $1,%ebx
movl $4,%eax
int $0x80
movl $0,%ebx
movl $1,%eax
int $0x80
.data
msg:
.ascii "Hello, world!\n"
len = . - msg
If i compile in a Debian server with
gcc -nostdlib -o hello hello.s
It work, but in WLS return error
/usr/bin/ld: /tmp/cciVVddg.o: relocation R_X86_64_32 against `.data' 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 also tried
gcc -fPIC -nostdlib -o hello hello.s
There are two problems with your code:
your code is intended to be 32 bit code but gcc tries to assemble it as 64 bit code. You can fix this by passing -m32 in all stages of assembly and linkage. Please keep in mind that WSL does not actually support 32 bit code so you won't be able to run your program even if you manage to assemble it.
gcc tries to generate a position-indepentent executable. To make your code work in such an executable, you need to write position indepentent code. To do so, you need to avoid any absolute references to the addresses of variables. In 32 bit code, this is a bit tricky and I'm not going to explain this further as 32 bit code won't run on WSL anyway. The compiler advises you to compile with -fpic because that causes the compiler to generate position independent code from C files, but for assembly files it's ineffective. You can fix this issue by linking with -no-pie, causing the linker to generate a normal position-dependent binary. Note that this still doesn't mean that a 32 bit binary is going to run in WSL.

Static linkage with glibc without calling main

I have created a simple hello world using NASM which calls printf and _exit from libc but does not use main.
extern printf
extern _exit
section .data
hello: db 'Hello world!',10
section .text
global _start
_start:
xor eax, eax
mov edi, hello
call printf
mov rax, 0
jmp _exit
I create the object file like this
nasm -felf64 hello.asm
Then I can link it using dynamic linkage with glibc like this
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64
This runs correctly with no errors. But now I want to do it statically. I do
ln -s `gcc -print-file-name=libc.a`
ln -s `gcc -print-file-name=libgcc_eh.a`
ld hello.o -static libc.a libgcc_eh.a libc.a -melf_x86_64
This links but when I run the code I get a segmentation fault. Using gdb I see it gives
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401004 in vfprintf ()
If I write a simple hello world in C and compile with static in runs fine so apparently it's possible to link statically to glibc on my system. How can I use static linkage with glibc with my assembly code?
If I link to an alternative to glibc such as musl-libc it works fine
ld hello.o -static /usr/local/musl/lib/libc.a -melf_x86_64
I'm using Ubuntu 14.04, eglibc 2.19, and GCC 4.9.1
Glibc have a huge initialization sequence, because it is done with strong intention to work in multithreading systems. Also GLIBC properly handles some GNU extensions like constructor attributes. On startup, it caching a lot inside TLS, including locale information, it initializes synchronization objects and so on.
Exact problem with your vprintf is uninitialized locale access.
When you are linking to it dynamically, all this work is done on loading and everything works.
Statically linked glibc requires __libc_init_first to be called to initialize all it need. Before this call you need __dl_tls_setup to properly setup TLS and after this call you will need __libc_csu_init to properly call all global constructors.
All this stuff is highly version-dependent and practically undocumented. Strictly saying, there is no safe way to link statically to glibc, skipping or modifying its normal _start sequence.
On the other hand, embedded-oriented libraries like musl or newlib are not so restrictive about initialization and multithreading and locales.

Problem building ECOS for "Linux Synthetic" target

I'm trying to building Synthetic Linux target with ECOS. My software environment:
Ubuntu 11.4
GCC 4.5.2
ECOS 3.0
In the Config Tool I have set up "Linux Sythetic" target with "all" packages. Pressing F7 (build) the compilation starts, but later it says:
/opt/ecos/ecos-3.0/packages/hal/synth/i386linux/v3_0/src/syscall-i386-linux-1.0.S:
Assembler messages: make: Leaving
directory `/opt/ecos/linux_build'
/opt/ecos/ecos-3.0/packages/hal/synth/i386linux/v3_0/src/syscall-i386-linux-1.0.S:457:
Error: .size expression for
__restore_rt does not evaluate to a constant
/opt/ecos/ecos-3.0/packages/hal/synth/i386linux/v3_0/src/syscall-i386-linux-1.0.S:457:
Error: .size expression for __restore
does not evaluate to a constant
make:
[src/syscall-i386-linux-1.0.o.d] Error 1 make: [build] Error 2
The content of the file /opt/ecos/ecos-3.0/packages/hal/synth/i386linux/v3_0/src/syscall-i386-linux-1.0.S from the line 434 is:
// ----------------------------------------------------------------------------
// Special support for returning from a signal handler. In theory no special
// action is needed, but with some versions of the kernel on some
// architectures that is not good enough. Instead returning has to happen
// via another system call.
.align 16
.global cyg_hal_sys_restore_rt
cyg_hal_sys_restore_rt:
movl $SYS_rt_sigreturn, %eax
int $0x80
1:
.type __restore_rt,#function
.size __restore_rt,1b - __restore_rt
.align 8
.global cyg_hal_sys_restore
cyg_hal_sys_restore:
popl %eax
movl $SYS_sigreturn, %eax
int $0x80
1:
.type __restore,#function
.size __restore,1b - __restore
So the __restore and __restore_rt is undefinied.
I've tried to comment out this part and remove signal-related packages (it says, that it is a signal handler stuff), but it looks to be the base part of the ECOS kernel; the build seems succeed when parts are outcommented, but when I compile example apps, there are linker error because of the missing symbols (cyg_hal_sys_restore).
Silly idea, but I've tried to replace "__restore" with "cyg_hal_sys_restore"
and "...rt" same way, just to eliminate undefs (not really hoping that the wrong code causes no error), and the result is: the build is ok (as there're no undefs), example compiling is ok (as no missing symbols), but example a.out throws segfault just at the holy moment I start it.
Halp, pls., I'm not familiar with inline asm nor ECOS.
The problem seems to be related to binutils. On Debian, a downgrade to 2.20.1-16 worked for me.
http://ecos.sourceware.org/ml/ecos-discuss/2011-06/msg00010.html
EDIT: Follow link, there's a proper fix too.

Resources