mikaku / Fiwix

A UNIX-like kernel for the i386 architecture
https://www.fiwix.org
Other
407 stars 32 forks source link

Compiling Fiwix with some versions of gcc requires -fno-pie #6

Closed rick-masters closed 1 year ago

rick-masters commented 1 year ago

Depending on the version of gcc or linux distribution, gcc may build with the -fPIE (position independent executable) option enabled by default. PIE code is incompatible with Fiwix for several reasons. Therefore, the -fno-pie option must be added to the CFLAGS in the Makefile in order to build Fiwix properly for some builds or versions of gcc.

For me, I built Fiwix on Ubuntu 20.04 and Fiwix would not boot. There was no obvious indication what the problem was and it took me several days of difficult debugging to fully understand the issue and the solution. My version of gcc is "gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0" and it builds with -fPIE enabled by default. This can be verified by building with the gcc options "-Q -v". In contrast, the version of gcc (4.8.5) on Centos 7 does not enable -fPIE by default.

I tried to make Fiwix work with my gcc, as is, but I was unable. First, gcc with -fPIE produces several new ELF sections such as ".data.rel" which are not accounted for in the fiwix.ld linker script. After solving that, I found that gcc's PIE code populates the ebx register with the current instruction pointer and locates data structures relative to that register. However, routines in core386.S such as tlbinfo modify the ebx register without saving it, which is catastrophic. (Not consistently saving registers is a separate issue which is probably worth fixing). After solving that, I found that Fiwix copies the init_trampoline function to a different location, so data structures cannot be found in the same place, relative to the instruction pointer. Fixing that could be done by porting init_trampoline to assembly, but I eventually figured out that simply adding the -fno-pie option would get gcc to build Fiwix the way it was intended.

mikaku commented 1 year ago

Yes, as stated here it's not expected that you use the compiler of your system to compile a totally different kernel.

I've not tried to build Fiwix with newer GCC versions. I use a cross-compiler GCC 4.7.4 for several reasons:

In any case, if you think that Makefile requires an extra argument to be able to build Fiwix under newer GCC versions, please, feel free submit a patch.

rick-masters commented 1 year ago

You are absolutely right that compiling gcc from source resolves this issue. To my surprise, even the latest version, gcc 12.2.0 does not enable -fPIE by default. I was mislead otherwise by something I read, but the current status is confirmed here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103398.

Nevertheless, as noted in the above bug report, many distributions enable PIE by default and so this issue is likely to catch others who have not taken the care to build gcc themselves. So I think it would be helpful to add the option. Assuming version 4.7.4 recognizes it, there shouldn't be any downside. I've tested 4.8.5 and it is recognized.

Here is a patch. Please let me know if you prefer pull requests and whether I should submit one for this change. Thanks.

--- Makefile.orig       2022-11-14 18:33:35.642232622 +0000
+++ Makefile    2022-11-14 18:32:41.762232265 +0000
@@ -14,7 +14,7 @@
 CC = $(CROSS_COMPILE)gcc $(ARCH) $(CPU) $(LANG) -D__KERNEL__ #-D__DEBUG__
 LD = $(CROSS_COMPILE)ld

-CFLAGS = -I$(INCLUDE) -O2 -ffreestanding -Wall -Wstrict-prototypes #-Wextra -Wno-unused-parameter
+CFLAGS = -I$(INCLUDE) -O2 -fno-pie -ffreestanding -Wall -Wstrict-prototypes #-Wextra -Wno-unused-parameter
 LDFLAGS = -m elf_i386 -nostartfiles -nostdlib -nodefaultlibs -nostdinc

 DIRS = kernel \
mikaku commented 1 year ago

Assuming version 4.7.4 recognizes it, there shouldn't be any downside. I've tested 4.8.5 and it is recognized.

I checked this option with 4.7.4 and it is accepted.

Here is a patch. Please let me know if you prefer pull requests and whether I should submit one for this change. Thanks.

Yes, I think a pull request is the best way.