Size of the file produced by linker is too large - gcc

I have those three files that don't have many bytes.
.rw-r--r-- 936 28 Jan 00:53 kernel.o
.rw-r--r-- 512 28 Jan 00:53 kernel_entry.o
.rw-r--r-- 872 28 Jan 00:53 screen.o
I assembled kernel_entry.o using NASM 2.15.05:
nasm src/kernel_entry.asm -f elf32 -o ../build/obj/kernel_entry.o
And i compiled kernel.o and screen.o using gcc 11.1.0:
gcc -ffreestanding -m32 -fno-pie -c -Iinclude -MMD -o ../build/obj/kernel.o src/kernel.c
gcc -ffreestanding -m32 -fno-pie -c -Iinclude -MMD -o ../build/obj/driver/screen.o src/driver/screen.c
My goal is to produce 32 bit executable code.
Then i link those 3 files together using ld 2.36.31:
ld -m elf_i386 -Ttext 0x1000 --oformat binary ../build/obj/kernel_entry.o ../build/obj/kernel.o ../build/obj/driver/screen.o -o ../build/kernel.bin
However, I expected the output file to be the size of the three .o files but it is 135M which is way too much:
.rwxr-xr-x 135M 28 Jan 01:16 build/kernel.bin
Looking at the hexadecimal representation of the file, I see a little room for my instructions and the rest is just zeros.
Do you have any idea what's wrong? By removing the oformat parameter I get a decent size but the code does not execute as expected
Thank you.

Related

gcc compile error ld cannot find -l Permission denied

When I execute:
gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
it reports the error:
D:\project\c\test\collection>gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
cannot find D:\project\c\test\collection: Permission denied
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
cannot find -lfoo
collect2.exe: error: ld returned 1 exit status
I followed the steps found here: gcc example
My OS is Windows 10 and I use cmd with administrator role.
UPDATE 1
I execute:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
and get the error:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
d:/gcc-9.2.0-no-debug/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lfoo
collect2.exe: error: ld returned 1 exit status
My collection directory has libfoo.so file:
2019/12/28 11:19 <DIR> .
2019/12/28 11:19 <DIR> ..
2019/12/28 10:55 3,262 a.exe
2019/12/28 10:38 87 foo.c
2019/12/28 10:37 80 foo.h
2019/12/28 10:38 838 foo.o
2019/12/28 10:38 47,372 libfoo.so
2019/12/28 10:38 134 main.c
UPDATE 2
I change to execute:
gcc -L / -Wall -o test main.c
and get the error:
//libfoo.dll.a: Unrecognized file: File truncated,collect2.exe: error: ld returned 1 exit status
gcc D:\project\c\test\collection -Wall -o test main.c -lfoo
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Files that aren't part of an option (like -o test or -lfoo) are generally considered to be input files for compiling or linking.
There's a good chance that's meant to be a library location for locating the foo library, simply because the tutorial you're following has almost the exact same line:
gcc -L/home/username/foo -Wall -o test main.c -lfoo
If that's the case, then you're missing the -L to tell it this should be added to the library search path, so something like this should fix it:
gcc -L D:\project\c\test\collection -Wall -o test main.c -lfoo
In any case, since you appear to have all your files in a single directory (source, libs, etc), you don't need to adjust the search path. Or, if you do, you can just used -L. to specify the current directory, something like:
gcc -Wall -o test main.c -L. -lfoo

How to link 2 files with different starting addresses with ld

I am trying to build a small os. I have an asm file that puts the processor in 64 bit mode with paging enabled. After this, i am jumping to my C code. I want the C code and asm code to be linked into the same file but the C code to have base address at 0xFFFFFF8000000000 and the asm file at 0x5000. How can I do this with ld.
This is what I have so far:
nasm -f elf64 os_init.asm -o ../bin/os_init.o
gcc -c -Os -nostdlib -nostartfiles -nodefaultlibs -fno-builtin vga/*.c utils/*.c *.c memory_management/*.c
ld -Ttext 0x5000 ../bin/os_init.o *.o -o ../bin/kernel.out
objcopy -S -O binary ../bin/kernel.out ../bin/kernel.bin
Currently both files are linked at 0x5000

i686-elf-gcc not creating output file (kernel.o)

I was following the osdev barebones tutorial and successfully created boot.o and linker.ld, but ran into a problem when the i686-elf-gcc compiler didn't create the kernel.o file. It gave no errors. This is what I ran to compile it:
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
But no matter how many times I do it, there's still no kernel.o!

MinGW compilation "file not recognized: File format not recognized"

I'm trying to compile a c++ program and I am having some issues. In particular, when I use x86_64-w64-mingw32-gcc as my compiler, it complains half way through my compilation saying "tmp/src/libfastms/solver/solver.cpp.o: file not recognized: File format not recognized".
Here is my makefile (not mine, I'm trying to adapt this makefile to a cygwin environment) https://pastebin.com/vgnVYJUL
Here is the console output when I run make:
x86_64-w64-mingw32-gcc -c -o tmp/src/libfastms/solver/solver.cpp.o src/libfastms/solver/solver.cpp -Wall -O3 -m64 -Isrc/libfastms -DDISABLE_OPENMP -DDISABLE_OPENCV -DDISABLE_CUDA
x86_64-w64-mingw32-gcc -c -o tmp/src/libfastms/solver/solver_base.cpp.o src/libfastms/solver/solver_base.cpp -Wall -O3 -m64 -Isrc/libfastms -DDISABLE_OPENMP -DDISABLE_OPENCV -DDISABLE_CUDA
x86_64-w64-mingw32-gcc -c -o tmp/src/libfastms/solver/solver_host.cpp.o src/libfastms/solver/solver_host.cpp -Wall -O3 -m64 -Isrc/libfastms -DDISABLE_OPENMP -DDISABLE_OPENCV -DDISABLE_CUDA
x86_64-w64-mingw32-gcc -c -o tmp/src/libfastms/util/has_cuda.cpp.o src/libfastms/util/has_cuda.cpp -Wall -O3 -m64 -Isrc/libfastms -DDISABLE_OPENMP -DDISABLE_OPENCV -DDISABLE_CUDA
x86_64-w64-mingw32-gcc -c -o tmp/src/libfastms/util/image_mat.cpp.o src/libfastms/util/image_mat.cpp -Wall -O3 -m64 -Isrc/libfastms -DDISABLE_OPENMP -DDISABLE_OPENCV -DDISABLE_CUDA
ld -r -o tmp/src/libfastms/libfastms.o tmp/src/libfastms/solver/solver.cpp.o tmp/src/libfastms/solver/solver_base.cpp.o tmp/src/libfastms/solver/solver_host.cpp.o tmp/src/libfastms/util/has_cuda.cpp.o tmp/src/libfastms/util/image_mat.cpp.o
tmp/src/libfastms/solver/solver.cpp.o: file not recognized: File format not recognized
Makefile:167: recipe for target 'tmp/src/libfastms/libfastms.o' failed
make: *** [tmp/src/libfastms/libfastms.o] Error 1
Some other notes:
I don't have this problem when I compile with g++ (only seems to be minGW)
A common solution to this problem is to clean the directory of residual object files. This does not work.
Another common reason for this is trying to compile .h files. Obviously I am not doing this.
Thanks in advance.
You are compiling your object files with a 64-bit compiler driver, w64-mingw32-gcc,
and with -m64 you are explicitly directing it to generate 64-bit code (unnecessarily,
as that is its default). But you are linking with a 32-bit linker that does not
understand 64-bit object files.
This is happening because in your makefile you are, unusually, invoking ld
explicitly for your incremental solver linkage:
COMMAND_LINK_SOLVER=ld -r -o $# $^
rather than delegating linkage to your compiler driver in the usual way, and
a 32-bit ld from a different toolchain is being found in your PATH before
the 64-bit one belonging to your mingw-w64 toolchain.
To avoid this, invoke the linker via the compiler driver as normal, which for your
solver linkage means:
COMMAND_LINK_SOLVER=$(GXX) -Wl,-r -o $# $^
You can depend on w64-mingw32-gcc to invoke the ld that was installed with it.
There is no need to correct your main linkage as it is already done the right way.

avr-gcc compiles too large optiboot hex to suit

I'd like to modify Arduino Uno's bootloader (optiboot) in order to increase upload commands timeout from 1s to 8s. So i need to recompile bootloaders and upload it.
I was able to replace deprecated '-mshort-calls' to '-mrelax' and i'm able to compile it but it produces too large binary:
MBA-Anton:optiboot asmirnov$ make atmega328
../../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mrelax -fno-move-loop-invariants -mmcu=atmega328p -DF_CPU=16000000L -mrelax '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' -c -o optiboot.o optiboot.c
../../../../tools/avr/bin/avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mrelax -fno-move-loop-invariants -mmcu=atmega328p -DF_CPU=16000000L -mrelax '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib -o optiboot_atmega328.elf optiboot.o
../../../../tools/avr/bin/avr-size optiboot_atmega328.elf
text data bss dec hex filename
530 0 0 530 212 optiboot_atmega328.elf
../../../../tools/avr/bin/avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_atmega328.elf optiboot_atmega328.hex
../../../../tools/avr/bin/avr-objdump -h -S optiboot_atmega328.elf > optiboot_atmega328.lst
rm optiboot.o optiboot_atmega328.elf
avr-gcc version:
MBA-Anton:optiboot asmirnov$ ../../../../tools/avr/bin/avr-gcc --version
avr-gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
MBA-Anton:optiboot asmirnov$
I've googled more and i found that pretty the same config produces much smaller binary, so what's wrong?
Solved by using pretty old (2012 year) avr-gcc from here

Resources