Page 1 of 4

[UEFI bare bones/x-compiler config] - LD not finding libgcc

Posted: Fri Jan 01, 2021 12:12 pm
by Schol-R-LEA
Warning: long post, with a fair amount of code.

Following the 'Recoding' thread, I decided to go ahead and write a more conventional kernel as practice for my more ambitious plans. To this end, I was trying out the UEFI bare bones tutorial to see how to boot on a modern system.

I followed the tutorial example for compiling with GCC - mostly blindly, in part to see what faults I might find - and after making symoblic links to the data.c and efi.h files, I compiled the code successfully as follows:

Code: Select all

x86_64-w64-mingw32-gcc -ffreestanding -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/ -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/x86_64/ -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/protocol/ -c -o hello.o boot.c

x86_64-w64-mingw32-gcc -ffreestanding -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/ -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/x86_64/ -I ~/Deployments/cross-dev-utils/gnu-efi-code/inc/protocol/ -c -o data.o data.c 
However, the linking phase went as follows:

Code: Select all

x86_64-w64-mingw32-gcc -nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main -o BOOTX64.EFI hello.o data.o -lgcc
and got the error message
/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lgcc
collect2: error: ld returned 1 exit status


I tried adding the library path as recommended here,

Code: Select all

x86_64-w64-mingw32-gcc -nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main -L /home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/lib/ -lgcc -o BOOTX64.EFI hello.o data.o
But this got the same error message back.

I suspect the problem is either with my cross-compiler setup, or with the library path I am adding. To get the path and other relevant details, I used the following command:

Code: Select all

$ x86_64-w64-mingw32-gcc -xc -E -v -lgcc
which yielded

Code: Select all

Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
Target: x86_64-w64-mingw32
Configured with: /home/schol-r-lea/Deployments/cross-dev-utils/gcc/configure --target=x86_64-w64-mingw32 --prefix=/home/schol-r-lea/opt/cross --disable-nls --enable-languages=ada --without-headers
Thread model: win32
Supported LTO compression algorithms: zlib zstd
gcc version 11.0.0 20201231 (experimental) (GCC) 
COMPILER_PATH=/home/schol-r-lea/opt/cross/libexec/gcc/x86_64-w64-mingw32/11.0.0/:/home/schol-r-lea/opt/cross/libexec/gcc/x86_64-w64-mingw32/11.0.0/:/home/schol-r-lea/opt/cross/libexec/gcc/x86_64-w64-mingw32/:/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/:/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/:/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/bin/
LIBRARY_PATH=/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/:/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/lib/../lib/:/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/../../../../x86_64-w64-mingw32/lib/
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'
To install and update my cross-compilers for various targets, I use a pair of shell scripts, one to update binutils, and the other for updating gcc. These are:

Code: Select all

#!/bin/bash

HOME_DIR="/home/schol-r-lea"
BINUTILS_SRC="$HOME_DIR/Deployments/cross-dev-utils/binutils-gdb"
BINUTILS_BUILD="$BINUTILS_SRC/build"
DEST="$HOME_DIR/opt/cross"

cd $BINUTILS_SRC
git pull origin master

cd $BINUTILS_BUILD
for TARGET in "i686-elf" "x86_64-elf" \
"x86_64-w64-mingw32" \
"arm-none-eabi" "aarch64-none-elf" \
"arm-linux-gnueabihf"  "aarch64-linux-gnu" \
"riscv32-unknown-elf" "riscv64-unknown-elf" \
"mipsel-unknown-elf" "mips64el-unknown-elf" 
do
  TARGET_DIR="$BINUTILS_BUILD/$TARGET"
  if [ ! -d $TARGET_DIR ]; then
     mkdir -p $TARGET_DIR
  fi
  make distclean
  
  cd $TARGET_DIR
  $BINUTILS_SRC/configure --target=$TARGET --prefix=$DEST --with-sysroot --disable-nls --disable-werror
  make
  make install
done
and

Code: Select all

#!/bin/bash

GCC_SRC="/home/schol-r-lea/Deployments/cross-dev-utils/gcc"
GCC_BUILD="$GCC_SRC/build"
DEST="/home/schol-r-lea/opt/cross"

cd $GCC_SRC
git pull origin master

cd $GCC_BUILD
for TARGET in "i686-elf" "x86_64-elf" \
"x86_64-w64-mingw32" \
"arm-none-eabi" "aarch64-none-elf" \
"arm-linux-gnueabihf" "aarch64-linux-gnu"   \
"riscv32-unknown-elf" "riscv64-unknown-elf" \
 "mipsel-unknown-elf" "mips64el-unknown-elf"
do
  TARGET_DIR="$GCC_BUILD/$TARGET"
  if [ ! -d $TARGET_DIR ]; then
     mkdir -p $TARGET_DIR
  fi

  cd $TARGET_DIR
  $GCC_SRC/configure --target=$TARGET --prefix=$DEST --disable-nls \
                     --enable-languages=objc,c,d,c++,go,ada \
                     --without-headers
  make all-gcc
  make all-target-libgcc
  make install-gcc
  make install-target-libgcc
done
While this is undoubtedly overkill, it does give me plenty of options for both source and target.

One thing I did note was the absence of a linker script in the tutorial. LD scripts are something I sadly have ignored for the most part up until now, and I will definitely need help with writing one here.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Fri Jan 01, 2021 3:51 pm
by Doctor5555
When you tried adding the library path as explained in the link, I believe the library path you needed was

Code: Select all

/home/schol-r-lea/opt/cross/lib/gcc/x86_64-w64-mingw32/11.0.0/
If you actually follow the directories, at least in my installation (which is 10.2.0 and x86_64-elf only), the libgcc is in the equivalent path and only an ldscripts folder at the one you used.
You can see both folders reported under "LIBRARY_PATH" in the "x86_64-w64-mingw32-gcc -xc -E -v -lgcc" result.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Fri Jan 01, 2021 9:28 pm
by kzinti
You can simply ask GCC where libgcc is:

Code: Select all

x86_64-w64-mingw32-gcc $(CFLAGS) -print-file-name=libgcc.a
Or in a makefile:

Code: Select all

LIBGCC = $(shell x86_64-w64-mingw32-gcc $(CFLAGS) -print-file-name=libgcc.a)
If this fails, it means there is a problem with your cross compiler build / installation.

Once you have the location of libgcc, you can use it for linking:

Code: Select all

x86_64-w64-mingw32-ld $(LDFLAGS) $(OBJECTS) $(LIBGCC) -o $@

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sat Jan 02, 2021 1:13 pm
by Schol-R-LEA
kzinti wrote:You can simply ask GCC where libgcc is:

Code: Select all

x86_64-w64-mingw32-gcc $(CFLAGS) -print-file-name=libgcc.a
Unfortunately, all this gives is the file name, not the path to it.

Also, I apparently overlooked something important, though not directly related to the problem: I didn't build libgcc.a with -noredzone set. This means I probably need to completely rebuild my cross-compiler anyway.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sat Jan 02, 2021 2:00 pm
by kzinti
Schol-R-LEA wrote:Unfortunately, all this gives is the file name, not the path to it.
This means there is a problem with your setup: GCC cannot find libgcc on its search path.

It sounds to me that your cross-compiler was not built or installed properly.
Schol-R-LEA wrote:Also, I apparently overlooked something important, though not directly related to the problem: I didn't build libgcc.a with -noredzone set. This means I probably need to completely rebuild my cross-compiler anyway.
Mingw uses the MS ABI which doesn't have red zones. So that's probably not the issue. But it doesn't hurt to be explicit and add "-mno-red-zone" just to be safe.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sat Jan 02, 2021 3:41 pm
by Octocontrabass
Schol-R-LEA wrote:To install and update my cross-compilers for various targets, I use a pair of shell scripts, one to update binutils, and the other for updating gcc.
Are there prebuilt MinGW-w64 packages available for your OS? You might have better luck with those.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sat Jan 02, 2021 5:33 pm
by kzinti
Octocontrabass wrote:Are there prebuilt MinGW-w64 packages available for your OS? You might have better luck with those.
+1. When I played with mingw 32/64 on Linux, I simply downloaded the pre-built packages and installed them. I was able to compile and run my UEFI bootloader successfully using them.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sun Jan 03, 2021 12:27 pm
by Schol-R-LEA
kzinti wrote:
Schol-R-LEA wrote:Unfortunately, all this gives is the file name, not the path to it.
This means there is a problem with your setup: GCC cannot find libgcc on its search path.

It sounds to me that your cross-compiler was not built or installed properly.
OK, then. I'll look over my install script again, and see if there is anything I am missing. If anyone could look at it for me (as given in the first post of the thread) and see if anything pops out as clearly incorrect, I would appreciate it.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sun Jan 03, 2021 2:28 pm
by nullplan
Schol-R-LEA wrote:OK, then. I'll look over my install script again, and see if there is anything I am missing. If anyone could look at it for me (as given in the first post of the thread) and see if anything pops out as clearly incorrect, I would appreciate it.
In the GCC script, there is no "set -e" anywhere, and -e is not part of the Shebang line. There is also no explicit exit out of the loop if any of the make commands fail. Therefore, how do you know the GCC build for MinGW succeeded? Unless you like watching your terminal screen four hours with scrolling text, and catching the short instance of something failing before the build moves on to MIPS or something, you don't. Is it possible the build failed and you didn't notice?

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Sun Jan 03, 2021 3:07 pm
by Schol-R-LEA
I will try running it again with the '-e' option in the shebang and find out.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Tue Jan 05, 2021 12:04 pm
by Schol-R-LEA
OK, so running the script with the '-e' (stop on error?) option did come up with a problem when trying to compile with the 'Ada' option; there also was an issue in the Binutils script with the 'make distclean' invocation. Removing those causes them both to run to completion, but the result of trying to get the Libgcc path from GCC still returns only the file name. I'll review the installation process to make sure I didn't overlook any steps or perform them incorrectly.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Tue Jan 05, 2021 12:32 pm
by kzinti
I've taken a 4th look at your scripts. They look fine. I am not sure what is going on here.

I do recall trying to compile mingw a long time ago and giving up, but I don't remember what problems I ran into.

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Tue Jan 05, 2021 1:40 pm
by nexos
Do the other targets you compiled look alright?

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Tue Jan 05, 2021 2:14 pm
by xenos
This might be a suggestion which you tried first already, as it is so simple, but since I saw it nowhere mentioned above, let me still state it:

Have you checked that libgcc is actually built successfully and installed in the path where ld is looking for it?

Re: [UEFI bare bones/x-compiler config] - LD not finding li

Posted: Wed Jan 06, 2021 12:54 am
by Schol-R-LEA
I've checked the expected paths where libgcc.a ought to be for each target triplet (~/opt/cross/lib/gcc/<triplet>/11.0.0/) and the only ones where it is missing x86_64-w64-mingw32, aarch64-linux-gnu, and arm-linux-gnueabihf . I can only assume that there is some additional step (or omitted one) specific to those triplets.

Or perhaps the ones with specific OS targets simply don't build libgcc.a by default. Not sure.