[U-Boot] [patch 0/1] [Experimental] U-boot linking against libgcc

Related to the discussion we had earlier today about linking to libgcc I have here a experimental patch that removes the linking to libgcc. I called it experimental because I am not able to test if all architectures still compile properly, and as such it needs more (build)testing before integrating. I tested several ARM boards, and they all compile and link fine.
I am convinced that it is the way to go to remove libgcc of the link list, but if we integrate this patch I cannot guarantee it does not break some builds, but it makes clear which boards are depending on interfaces from a library it should not depend on in the first place. Those boards might need additional patches.
I hope you can find some time to do some more compile testing across different architectures.
Kind Regards,
Remy Böhmer

Currently U-boot is linking against libgcc. This should not be needed because the compiler toolchain is usually compiled with a certain OS interface in mind, and can even be configured for GNU-EABI interfaces. This can cause linking conflicts in U-boot when linking to libgcc.
It usually becomes really visible that these conflicts are there when some piece of code requires an external routine that is not available in U-boot itself. Such an unresolved external are finally searched in the libgcc library, because U-boot is told to link against. If the compiler happened to be a EABI compiler, linking will definately fail. These are not a compiler problems, but U-boot problems, because U-boot needs to keep its own pants up (It is not linking to any OS, it is standalone) If the compiler is _not_ a EABI compiler toolchain, linking might succeed, but its behaviour will be undefined, because it is unknown what the external dependencies of such libraries will be. (syscalls required?)
While looking at compiler includes, the only header used from GCC (I have seen) seems to be the stdarg.h header, which is even doubtful to include in U-boot, because of the same reasons not to link against libgcc. This patch only removes the linking part to libgcc.
I tested it on several ARM boards, and linking still works fine...
Several older mailthreads that show similar issues (just a simple grep): http://www.mail-archive.com/u-boot-users@lists.sourceforge.net/msg03176.html http://lists.denx.de/pipermail/u-boot/2008-August/039526.html http://lists.denx.de/pipermail/u-boot/2007-July/022881.html
Signed-off-by: Remy Bohmer linux@bohmer.net --- Makefile | 3 --- api_examples/Makefile | 5 +---- board/netstar/Makefile | 5 +---- board/trab/Makefile | 5 +---- board/voiceblue/Makefile | 5 +---- examples/Makefile | 10 ++++------ 6 files changed, 8 insertions(+), 25 deletions(-)
Index: u-boot/Makefile =================================================================== --- u-boot.orig/Makefile 2008-10-31 23:01:06.000000000 +0100 +++ u-boot/Makefile 2008-10-31 23:02:09.000000000 +0100 @@ -264,9 +264,6 @@ LIBS := $(addprefix $(obj),$(LIBS)) LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
-# Add GCC lib -PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc - # The "tools" are needed early, so put this first # Don't include stuff already done in $(LIBS) SUBDIRS = tools \ Index: u-boot/api_examples/Makefile =================================================================== --- u-boot.orig/api_examples/Makefile 2008-10-31 23:01:07.000000000 +0100 +++ u-boot/api_examples/Makefile 2008-10-31 23:03:22.000000000 +0100 @@ -57,8 +57,6 @@ OBJS := $(addprefix $(obj),$(COBJS)) ELF := $(addprefix $(obj),$(ELF)) BIN := $(addprefix $(obj),$(BIN))
-gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`) - CPPFLAGS += -I..
all: $(obj).depend $(OBJS) $(LIB) $(ELF) $(BIN) @@ -70,8 +68,7 @@ $(LIB): $(obj).depend $(LIBOBJS) $(ELF): $(obj)%: $(obj)%.o $(LIB) $(LD) $(obj)crt0.o -Ttext $(LOAD_ADDR) \ - -o $@ $< $(LIB) \ - -L$(gcclibdir) -lgcc + -o $@ $< $(LIB)
$(BIN): $(obj)%.bin: $(obj)% Index: u-boot/board/netstar/Makefile =================================================================== --- u-boot.orig/board/netstar/Makefile 2008-10-31 23:01:11.000000000 +0100 +++ u-boot/board/netstar/Makefile 2008-10-31 23:04:17.000000000 +0100 @@ -36,8 +36,6 @@ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ee OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS))
-gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`) - LOAD_ADDR = 0x10400000 LDSCRIPT = $(TOPDIR)/board/$(BOARDDIR)/eeprom.lds lnk = $(if $(obj),$(obj),.) @@ -54,8 +52,7 @@ $(obj)eeprom.srec: $(obj)eeprom.o $(obj) cd $(lnk) && $(LD) -T $(LDSCRIPT) -g -Ttext $(LOAD_ADDR) \ -o $(<:.o=) -e eeprom eeprom.o eeprom_start.o \ -L$(obj)../../examples -lstubs \ - -L$(obj)../../lib_generic -lgeneric \ - -L$(gcclibdir) -lgcc + -L$(obj)../../lib_generic -lgeneric $(OBJCOPY) -O srec $(<:.o=) $@
$(obj)eeprom.bin: $(obj)eeprom.srec Index: u-boot/board/trab/Makefile =================================================================== --- u-boot.orig/board/trab/Makefile 2008-10-31 23:01:11.000000000 +0100 +++ u-boot/board/trab/Makefile 2008-10-31 23:04:03.000000000 +0100 @@ -36,8 +36,6 @@ SOBJS := $(addprefix $(obj),$(SOBJS))
OBJS_FKT := $(addprefix $(obj),$(COBJS_FKT))
-gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`) - LOAD_ADDR = 0xc100000
######################################################################### @@ -50,8 +48,7 @@ $(LIB): $(obj).depend $(OBJS) $(SOBJS) $(obj)trab_fkt.srec: $(OBJS_FKT) $(LIB) $(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e trab_fkt $^ $(LIB) \ -L$(obj)../../examples -lstubs \ - -L$(obj)../../lib_generic -lgeneric \ - -L$(gcclibdir) -lgcc + -L$(obj)../../lib_generic -lgeneric $(OBJCOPY) -O srec $(<:.o=) $@
$(obj)trab_fkt.bin: $(obj)trab_fkt.srec Index: u-boot/board/voiceblue/Makefile =================================================================== --- u-boot.orig/board/voiceblue/Makefile 2008-10-31 23:01:12.000000000 +0100 +++ u-boot/board/voiceblue/Makefile 2008-10-31 23:03:45.000000000 +0100 @@ -33,8 +33,6 @@ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ee OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS))
-gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`) - LOAD_ADDR = 0x10400000 LDSCRIPT = $(TOPDIR)/board/$(BOARDDIR)/eeprom.lds lnk = $(if $(obj),$(obj),.) @@ -48,8 +46,7 @@ $(obj)eeprom.srec: $(obj)eeprom.o $(obj) cd $(lnk) && $(LD) -T $(LDSCRIPT) -g -Ttext $(LOAD_ADDR) \ -o $(<:.o=) -e eeprom eeprom.o eeprom_start.o \ -L$(obj)../../examples -lstubs \ - -L$(obj)../../lib_generic -lgeneric \ - -L$(gcclibdir) -lgcc + -L$(obj)../../lib_generic -lgeneric $(OBJCOPY) -O srec $(<:.o=) $@
$(obj)eeprom.bin: $(obj)eeprom.srec Index: u-boot/examples/Makefile =================================================================== --- u-boot.orig/examples/Makefile 2008-10-31 23:01:14.000000000 +0100 +++ u-boot/examples/Makefile 2008-10-31 23:05:12.000000000 +0100 @@ -42,11 +42,11 @@ LOAD_ADDR = 0x80200000 -T mips.lds endif
ifeq ($(ARCH),nios) -LOAD_ADDR = 0x00800000 -L $(gcclibdir)/m32 -T nios.lds +LOAD_ADDR = 0x00800000 -T nios.lds endif
ifeq ($(ARCH),nios2) -LOAD_ADDR = 0x02000000 -L $(gcclibdir) -T nios2.lds +LOAD_ADDR = 0x02000000 -T nios2.lds endif
ifeq ($(ARCH),m68k) @@ -73,7 +73,7 @@ endif endif
ifeq ($(ARCH),sparc) -LOAD_ADDR = 0x00000000 -L $(gcclibdir) -T sparc.lds +LOAD_ADDR = 0x00000000 -T sparc.lds endif
include $(TOPDIR)/config.mk @@ -158,7 +158,6 @@ ELF := $(addprefix $(obj),$(ELF)) BIN := $(addprefix $(obj),$(BIN)) SREC := $(addprefix $(obj),$(SREC))
-gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`) clibdir := $(shell dirname `$(CC) $(CFLAGS) -print-file-name=libc.a`)
CPPFLAGS += -I.. @@ -172,8 +171,7 @@ $(LIB): $(obj).depend $(LIBOBJS) $(ELF): $(obj)%: $(obj)%.o $(LIB) $(LD) -g $(EX_LDFLAGS) -Ttext $(LOAD_ADDR) \ - -o $@ -e $(SYM_PREFIX)$(notdir $(<:.o=)) $< $(LIB) \ - -L$(gcclibdir) -lgcc + -o $@ -e $(SYM_PREFIX)$(notdir $(<:.o=)) $< $(LIB)
$(SREC): $(obj)%.srec: $(obj)%

On Fri, Oct 31, 2008 at 11:37:33PM +0100, Remy Bohmer wrote:
Currently U-boot is linking against libgcc. This should not be needed because the compiler toolchain is usually compiled with a certain OS interface in mind, and can even be configured for GNU-EABI interfaces. This can cause linking conflicts in U-boot when linking to libgcc.
libgcc should *not* be expecting any OS interface. It may use a few basic libc functions such as memcpy, that u-boot provides.
While looking at compiler includes, the only header used from GCC (I have seen) seems to be the stdarg.h header, which is even doubtful to include in U-boot, because of the same reasons not to link against libgcc. This patch only removes the linking part to libgcc.
Why is it doubtful to remove the only portable way to get variable arguments? stdarg.h should *not* contain OS dependencies.
-Scott

Hello Scott (and Wolfgang),
libgcc should *not* be expecting any OS interface. It may use a few basic libc functions such as memcpy, that u-boot provides.
libgcc could also expect the 'raise()' routine to pass divide-by-zero execeptions. (if __div0, (or __aeabi_ldiv0) is not overruled) If not overruled, than libgcc can depend on libc, and thus indirectly depend on a OS interface.
In the mean time things are getting more clear. In the ARM section of U-boot a large amount of (division) routines which are usually provided by libgcc are also implemented in the lib_arm directory. For many ARM boards it is therefore possible to remove linking to libgcc at all, and it won't hurt the resulting binary at all (because nothing is currently used from libgcc on ARM).
At first, I thought 'why not remove libgcc if it is not used', but it is clear to me now that this is not the route to go. I got confused by the redundant implementation in lib_arm... (Other architectures than ARM seem to do it better, removing libgcc would break those for the wrong implementation which is currently in the ARM tree. )
Some routines are still lacking in the lib_arm tree and if GCC starts generating code (due to some code change) that requires those missing routines, we now get link errors if a EABI only compiler is used. (If for example the eabi compiler toolchain of CodeSourcery is used (e.g. 2008q1) then the provided libgcc is not compatible with the compile option -mabi=apcs-gnu, the libgcc of the non-EABI toolchain of CS however seems to be compatible with this flag) Today I even saw patches coming by that moves some division routines to do_div(), just to workaround these linking issues, and thus actually to prevent linking against libgcc. This happened before in the past resulting in the (rather big) lib_arm tree.
So, I agree (now) that libgcc should be used, but this is _not the case_ currently in the ARM tree.
While looking at compiler includes, the only header used from GCC (I have seen) seems to be the stdarg.h header, which is even doubtful to include in U-boot, because of the same reasons not to link against libgcc. This patch only removes the linking part to libgcc.
Why is it doubtful to remove the only portable way to get variable arguments? stdarg.h should *not* contain OS dependencies.
My _first_ conclusion was that the libraries provided by the compiler toolchain were not suitable to build a standalone application like U-boot. From that point of view it was logical to say that if no libraries from a compiler are used, why use any headers?(regardless what is in there...)
What I now believe that should be done is to investigate (compile time) what type of ABI is supported by the libgcc provided by the compiler, and adjust the compile settings to that ABI. I was already doing some hacks to check if I could get this working... (A person must have a hobby :-) ) I have removed a lot of redundant implementations in lib_arm and I have at least succeeded in linking to the EABI libgcc (no hardware here to test...)
I hope this explanation sounds much more sane to everybody ;-)
Remy

Dear "Remy Bohmer",
In message 3efb10970811021218g6d30d611r479c8e800991abf4@mail.gmail.com you wrote:
libgcc could also expect the 'raise()' routine to pass divide-by-zero execeptions. (if __div0, (or __aeabi_ldiv0) is not overruled)
raise()? exceptions? In C?
In the mean time things are getting more clear. In the ARM section of U-boot a large amount of (division) routines which are usually provided by libgcc are also implemented in the lib_arm directory. For many ARM boards it is therefore possible to remove linking to libgcc at all, and it won't hurt the resulting binary at all (because nothing is currently used from libgcc on ARM).
...unless you use some (probably older) tool chains where this may break. I guess there was a readon to add these functions. We did not do this for the fun of it.
Some routines are still lacking in the lib_arm tree and if GCC starts generating code (due to some code change) that requires those missing routines, we now get link errors if a EABI only compiler is used. (If for example the eabi compiler toolchain of CodeSourcery is used (e.g. 2008q1) then the provided libgcc is not
So, I agree (now) that libgcc should be used, but this is _not the case_ currently in the ARM tree.
I think I saw libgcc on the linker command line ?
What I now believe that should be done is to investigate (compile time) what type of ABI is supported by the libgcc provided by the compiler, and adjust the compile settings to that ABI.
If such a thing needs to be done, it is a compiler-issue, and we do not have to know or care about that.
Best regards,
Wolfgang Denk

Hello Wolfgang,
libgcc could also expect the 'raise()' routine to pass divide-by-zero execeptions. (if __div0, (or __aeabi_ldiv0) is not overruled)
raise()? exceptions? In C?
Please, do not get pikky about choice of words... You can call it an exception, signal, or whatever. (If I meant C++-exception handling, I would call it that way) According to the docs, overrule __div0 (as done in U-boot) or implement a raise() routine that does not return, in a OS it is probably redirected to a signal handler (via libc).
In the mean time things are getting more clear. In the ARM section of U-boot a large amount of (division) routines which are usually provided by libgcc are also implemented in the lib_arm directory. For many ARM boards it is therefore possible to remove linking to libgcc at all, and it won't hurt the resulting binary at all (because nothing is currently used from libgcc on ARM).
...unless you use some (probably older) tool chains where this may break. I guess there was a readon to add these functions. We did not do this for the fun of it.
I never told it was added for fun... Even in the case if these functions are added for an old toolchain, maybe it is preferable to link first to libgcc, and finally to lib_arm.a to make sure that the most of libgcc functions are used. Or make it somewhat compiler version related
Some routines are still lacking in the lib_arm tree and if GCC starts generating code (due to some code change) that requires those missing routines, we now get link errors if a EABI only compiler is used. (If for example the eabi compiler toolchain of CodeSourcery is used (e.g. 2008q1) then the provided libgcc is not
So, I agree (now) that libgcc should be used, but this is _not the case_ currently in the ARM tree.
I think I saw libgcc on the linker command line ?
Yep.. it is there on the commandline... but it is useless! No functions of this lib are used thus libgcc is not used. (on a modern GCC 4.2.3 toolchain to be precise) On ARM, you can remove it and still it works... You can probably link a 100 more libraries, if it won't resolve any unresolved external, it will not be used.
What I now believe that should be done is to investigate (compile time) what type of ABI is supported by the libgcc provided by the compiler, and adjust the compile settings to that ABI.
If such a thing needs to be done, it is a compiler-issue, and we do not have to know or care about that.
Okay, now I really lost you, first you have a very strong opinion that libgcc _must_ be used. I follow you (I admit I was wrong in the beginning), so I start investigating for a solution to actually start using libgcc on ARM, and now you tell me you do not want that libgcc is actually being used on ARM... (Besides, if you are consequent about the 'not caring' part, you should also not approve the do_div() patches which are used to get around linking problems with EABI toolchains..., or any other compiler-bug workarounds...)
Kind Regards,
Remy

Dear Remy,
In message 3efb10970811021323w71c480fdq507814c01b834441@mail.gmail.com you wrote:
What I now believe that should be done is to investigate (compile time) what type of ABI is supported by the libgcc provided by the compiler, and adjust the compile settings to that ABI.
If such a thing needs to be done, it is a compiler-issue, and we do not have to know or care about that.
Okay, now I really lost you, first you have a very strong opinion that libgcc _must_ be used. I follow you (I admit I was wrong in the beginning), so I start investigating for a solution to actually start using libgcc on ARM, and now you tell me you do not want that libgcc is actually being used on ARM... (Besides, if you are consequent about the 'not caring' part, you should also not approve the do_div()
I did not say that.
I said if any compiler options must be adapted to match the ABI implemented by the tool chain, then this is an issue that is internal to this tool chain, and nothing we should bother about. If the tool chain wants to produce FOO-comptible code it must make sure (internally) to set all required options and provide all required library routines for the FOO ABI - whatever that might be.
Best regards,
Wolfgang Denk

Dear Remy,
In message 20081031224856.847997187@bohmer.net you wrote:
Currently U-boot is linking against libgcc. This should not be needed because
And where would the GCC compiler gets its builtin functions from, then?
the compiler toolchain is usually compiled with a certain OS interface in mind, and can even be configured for GNU-EABI interfaces.
The toolchain is not OS dependent. It implements a cetrain ABI. And libgcc provides the needed support functions.
This can cause linking conflicts in U-boot when linking to libgcc.
I have an idea what you mean, but as stated here it's wrong.
It usually becomes really visible that these conflicts are there when some piece of code requires an external routine that is not available in U-boot itself.
This must never happen. U-Boot is supposed to be self-contained, except for any compiler-speeific functions which are provided by the compiler itself - in libgcc.a (assuming you use GCC).
Such an unresolved external are finally searched in the libgcc library, because U-boot is told to link against. If the compiler happened to be a EABI compiler, linking will definately fail. These are not a compiler problems, but U-boot problems, because
No, it will not, unless it is misconfigured.
U-boot needs to keep its own pants up (It is not linking to any OS, it is standalone)
Correct. But we cannot know what the compiler may need or provide.
If the compiler is _not_ a EABI compiler toolchain, linking might succeed, but its behaviour will be undefined, because it is unknown what the external dependencies of such libraries will be. (syscalls required?)
Huch? I cannot make any sense of this.
While looking at compiler includes, the only header used from GCC (I have seen) seems to be the stdarg.h header, which is even doubtful to include in U-boot, because of the same reasons not to link against libgcc. This patch only removes the linking part to libgcc.
Oops? How would you implement support for variable number of arguments then, when you remove the only standard way to do it?
I tested it on several ARM boards, and linking still works fine...
And, do they also run fine?
Several older mailthreads that show similar issues (just a simple grep): http://www.mail-archive.com/u-boot-users@lists.sourceforge.net/msg03176.html
I think the code would not run (because it uses an incompatible [with the compiler used] ABI version) if you omitted linking against libgcc here.
http://lists.denx.de/pipermail/u-boot/2008-August/039526.html
Different problem, has nothing to do with linking against libgcc per se.
Has nothing to do with libgcc.a
Your patch will break a lot of PPC boards, for example:
Configuring for BC3450 board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3' make: *** [u-boot] Error 1
Configuring for cm5200 board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3' make: *** [u-boot] Error 1
Configuring for fo300 board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3'
Configuring for TB5200 board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3'
Configuring for TQM5200 board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3' make: *** [u-boot] Error 1
Configuring for TQM5200_B board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3' make: *** [u-boot] Error 1
Configuring for TQM5200S board... post/libpost.a(post.o): In function `post_time_ms': /work/wd/u-boot/post/post.c:451: undefined reference to `__udivdi3' make: *** [u-boot] Error 1
and so on.
NAK.
Best regards,
Wolfgang Denk

On Friday 31 October 2008, Remy Bohmer wrote:
Related to the discussion we had earlier today about linking to libgcc I have here a experimental patch that removes the linking to libgcc. I called it experimental because I am not able to test if all architectures still compile properly, and as such it needs more (build)testing before integrating. I tested several ARM boards, and they all compile and link fine.
I am convinced that it is the way to go to remove libgcc of the link list, but if we integrate this patch I cannot guarantee it does not break some builds, but it makes clear which boards are depending on interfaces from a library it should not depend on in the first place. Those boards might need additional patches.
I hope you can find some time to do some more compile testing across different architectures.
it will break Blackfin builds as there are a bunch of places where the compiler generates calls to libgcc
i cant see why you'd want to remove libgcc or why you think this is a correct long term goal, but Wolfgang already made a much more detailed list ... -mike
participants (4)
-
Mike Frysinger
-
Remy Bohmer
-
Scott Wood
-
Wolfgang Denk