[uClinux-dev] gcc-3.0.2 toolchain for arm-uclinux

From: Adrian von Bidder (avbidder@acter.ch)
Date: Thu Dec 20 2001 - 11:09:35 EST


Hey dol! merry dol! ring a dong dillo!

As this is quite long - Who should read this:
people interested in the arm-uclinux platform using flat binaries
people willing to experiment with the gcc/binutils toolchain
people who are pissed of with the aplio tools
people who want to move to gcc-3 because it may perhaps one day
	be usable for producing thumb instructions

Who does not need to read this:
people not using uclinux
people using uclinux on other than arm

Now for the real stuff:

It is here - the first public release of a gcc-3.0.2 toolchain for arm
uclinux. Please be aware that this is somewhat experimental, there are a
few problems right now:
 - elf2flt does not like the libbfd/libiberty from binutils-2.11.2, so 
	you'll need those files of binutils-2.10
 - C++ is untested
 - thumb is untested and known to have problems
 - compressed binaries are untested
 - not tested on anything other than arm7tdmi
 - not tested with anything other than uClinux-2.0

How to build it:
The build process is based on the build script David has done for the
gcc-2.95 toolchain. The attached build script is the one I use for
development, so it assumes the source code directories are already set
up.

1. untar binutils-2.11.2.tar.gz, gcc-core-3.0.2.tar.gz,
	gcc-g++-3.0.2.tar.gz, elf2flt-20011217.tar.gz, 	genromfs-0.3.2.tar.gz
(if you don't know where to find some of
	the files, they are in
	http://www.uclinux.org/pub/uClinux/m68k-elf-tools )
2. rename the directories so they contain no version numbers (gcc-3.0.2
	becomes gcc etc.).
3. apply the patches to gcc, binutils, elf2flt:
	cd <tooldir>
	patch -p0 < <thepatchfile>
4. get reasonably recent uClibc and uClinux trees. make config in the
	uClinux tree.
5. get libbfd.a and libiberty.a from a binutils-2.10 build (for instance
	from a build of the 2.95.3 toolchain). I have not attached them 	as
libbfd.a is quite big.)
6. read the build script and adapt it (location of uclinux, uclibc,
	installation directory)
7. ./build-uclinux-tools.sh build
8. ./build-uclinux-tools.sh uclibc

Marketing people would say 'after these eight easy steps...'. But we do
of course see immediately that there are enough pitfalls in there. Don't
be afraid, you can do it!

How to use it:
Thanks to the sensible default, we can drop -mcpu=arm7tdmi and
-msingle-pic-base from the commandline. Thanks to the new elf2flt we get
rid of -mdisable-got -shared -symbolic and who knows what else was
necessary with the aplio toolchain. That leaves us with

arm-uclinux-gcc -c -fpic hello.c
arm-uclinux-gcc -fpic -Wl,-elf2flt -o hello hello.o

This generates a GOT relocated FLAT version 4 binary, ready for XIP. It
is essential to specify -fpic on the linker command line as well as when
compiling, or the multilib magic will select the wrong libc.

If you have looked close enough, you see that thumb libgcc.a have been
built, too. So feel free to hack on uclibc - but be aware that there are
several problems with the thumb code generator, so be prepared to do a
bit gcc hacking, too.

Ok, that's it so far. Feel free to comment, send patches, flowers,
money, ... ;-) (I'll not read mail after tomorrow, though, so don't
expect answers too soon.)

Thanks go to David McCullough who beat elf2flt into submission, so it
does XIP for GOT relocated flat binaries, and generally gave me a lot of
advice. Nick Clifton and Philip Blundell were very helpful with binutils
and gcc issues. And of course I should mention acter who pay me for
doing this stuff.

greets from Zürich - happy christmas and all this.
-- vbi


Index: config.sub
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/binutils/config.sub,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- config.sub	2001/12/06 14:06:02	1.1.1.1
+++ config.sub	2001/12/10 16:22:33	1.2
@@ -1017,7 +1017,8 @@
 	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
-	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -uclinux*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
Index: bfd/elf32-arm.h
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/binutils/bfd/elf32-arm.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- bfd/elf32-arm.h	2001/12/06 14:06:10	1.1.1.1
+++ bfd/elf32-arm.h	2001/12/07 07:34:25	1.2
@@ -1145,6 +1145,9 @@
 		      && (h->elf_link_hash_flags
 			  & ELF_LINK_HASH_DEF_REGULAR) != 0))
 		{
+                  if (r_type == R_ARM_ABS32 && sym_flags == STT_ARM_TFUNC)
+                    value |= 1;
+
 		  relocate = true;
 		  outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
 		}

Index: config.sub
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/gcc/config.sub,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- config.sub	2001/12/06 14:07:32	1.1.1.1
+++ config.sub	2001/12/10 16:22:33	1.2
@@ -1035,7 +1035,8 @@
 	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
-	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -uclinux*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
Index: gcc/config.gcc
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/gcc/gcc/config.gcc,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- gcc/config.gcc	2001/12/06 14:07:43	1.1.1.1
+++ gcc/config.gcc	2001/12/20 14:02:57	1.2
@@ -601,7 +601,7 @@
 	;;
 arm*-*-uclinux*)		# ARM ucLinux
 	tm_file=arm/uclinux-elf.h
-	tmake_file=arm/t-arm-elf
+	tmake_file=arm/t-uclinux
 	;;
 arm*-*-aout)
 	tm_file=arm/aout.h
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- gcc/config/arm/arm.h	2001/12/06 14:08:06	1.1.1.1
+++ gcc/config/arm/arm.h	2001/12/07 11:41:20	1.4
@@ -896,8 +896,19 @@
 /* Return the regiser number of the N'th (integer) argument.  */
 #define ARG_REGISTER(N) 	(N - 1)
 
+#if 0 /* FIXME: The ARM backend has special code to handle structure
+        returns, and will reserve its own hidden first argument.  So
+        if this macro is enabled a *second* hidden argument will be
+        reserved, which will break binary compatability with old
+        toolchains and also thunk handling.  One day this should be
+        fixed.  */
 /* RTX for structure returns.  NULL means use a hidden first argument.  */
 #define STRUCT_VALUE		0
+#else
+/* Register in which address to store a structure value
+   is passed to a function.  */
+#define STRUCT_VALUE_REGNUM   ARG_REGISTER (1)
+#endif
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -1579,7 +1590,7 @@
 
 #define THUMB_FUNCTION_PROFILER(STREAM, LABELNO)	\
 {							\
-  fprintf (STREAM, "\tmov\\tip, lr\n");			\
+  fprintf (STREAM, "\tmov\tip, lr\n");			\
   fprintf (STREAM, "\tbl\tmcount\n");			\
   fprintf (STREAM, "\t.word\tLP%d\n", LABELNO);		\
 }
@@ -1681,7 +1692,8 @@
 	      && ! call_used_regs[HARD_FRAME_POINTER_REGNUM])		\
 	    saved_hard_reg = 1, offset += 4;				\
 	  /* PIC register is a fixed reg, so call_used_regs set.  */	\
-	  if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])	\
+	  if (flag_pic && ! TARGET_SINGLE_PIC_BASE &&                   \
+                  regs_ever_live[PIC_OFFSET_TABLE_REGNUM])	        \
 	    saved_hard_reg = 1, offset += 4;				\
           for (regno = FIRST_ARM_FP_REGNUM;				\
 	       regno <= LAST_ARM_FP_REGNUM; regno++)			\
Index: gcc/config/arm/linux-gas.h
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/gcc/gcc/config/arm/linux-gas.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- gcc/config/arm/linux-gas.h	2001/12/06 14:08:05	1.1.1.1
+++ gcc/config/arm/linux-gas.h	2001/12/20 14:02:57	1.2
@@ -74,6 +74,7 @@
 
 /* Clear the instruction cache from `beg' to `end'.  This makes an
    inline system call to SYS_cacheflush.  */
+#ifndef __thumb__
 #define CLEAR_INSN_CACHE(BEG, END)					\
 {									\
   register unsigned long _beg __asm ("a1") = (unsigned long) (BEG);	\
@@ -83,3 +84,25 @@
 		    : "=r" (_beg)					\
 		    : "0" (_beg), "r" (_end), "r" (_flg));		\
 }
+#else
+/* This is a hack. Use the thumb ABI or make it an (interworking)
+   function call */
+#define CLEAR_INSN_CACHE(BEG, END)					\
+{									\
+  register unsigned long _beg __asm ("a1") = (unsigned long) (BEG);	\
+  register unsigned long _end __asm ("a2") = (unsigned long) (END);	\
+  register unsigned long _flg __asm ("a3") = 0;				\
+  unsigned long temp;							\
+  __asm __volatile (							\
+	"adr	%1, 0f\n"						\
+"	bx	%1\n"							\
+"	.align 2\n"							\
+"	.code 32\n"							\
+"0:	swi 0x9f0002		@ sys_cacheflush\n"			\
+"	adr	%1, 0b + 13\n"						\
+"	bx	%1\n"							\
+"	.code 16"							\
+		    : "=r" (_beg), "=r" (temp)				\
+		    : "0" (_beg), "r" (_end), "r" (_flg));		\
+}
+#endif
Index: gcc/config/arm/t-uclinux
===================================================================
RCS file: t-uclinux
diff -N t-uclinux
--- /dev/null	Fri Sep  1 16:01:47 2000
+++ gcc/config/arm/t-uclinux	Thu Dec 20 15:44:54 2001
@@ -0,0 +1,82 @@
+# this file is a modified copy of t-arm-elf. Try to change as little as possible
+# so tracking of changes will be easier.
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = arm/lib1funcs.asm
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	echo '#ifndef __ARMEB__' >> fp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+	echo '#endif' >> fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#ifndef __ARMEB__' > dp-bit.c
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+	echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
+	echo '#endif' >> dp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+MULTILIB_OPTIONS     = marm/mthumb
+MULTILIB_DIRNAMES    = arm thumb
+MULTILIB_EXCEPTIONS  = 
+
+MULTILIB_OPTIONS    += fno-pic/fpic
+MULTILIB_DIRNAMES   += no-pic pic
+
+# MULTILIB_OPTIONS     = mlittle-endian/mbig-endian
+# MULTILIB_DIRNAMES    = le be
+# MULTILIB_EXCEPTIONS  = 
+# MULTILIB_MATCHES     = mbig-endian=mbe mlittle-endian=mle
+# 
+# MULTILIB_OPTIONS    += mhard-float/msoft-float
+# MULTILIB_DIRNAMES   += fpu soft
+# 
+# MULTILIB_OPTIONS    += mapcs-32/mapcs-26
+# MULTILIB_DIRNAMES   += 32bit 26bit
+# 
+# MULTILIB_OPTIONS    += mno-thumb-interwork/mthumb-interwork
+# MULTILIB_DIRNAMES   += normal interwork
+# MULTILIB_EXCEPTIONS += *mapcs-26/*mthumb-interwork*
+# 
+# MULTILIB_OPTIONS    += fno-leading-underscore/fleading-underscore
+# MULTILIB_DIRNAMES   += elf under
+# 
+# MULTILIB_OPTIONS    += mcpu=arm7
+# MULTILIB_DIRNAMES   += nofmult
+# MULTILIB_EXCEPTIONS += *mthumb-interwork*/*mcpu=arm7*
+# # We have to match all the arm cpu variants which do not have the
+# # multiply instruction and treat them as if the user had specified
+# # -mcpu=arm7.  Note that in the following the ? is interpreted as
+# # an = for the purposes of matching command line options.
+# # FIXME: There ought to be a better way to do this.
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm7d
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm7di
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm70
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm700
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm700i
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm710
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm710c
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm7100
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm7500
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm7500fe
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm6
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm60
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm600
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm610
+# MULTILIB_MATCHES    += mcpu?arm7=mcpu?arm620
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# Currently there is a bug somewhere in GCC's alias analysis
+# or scheduling code that is breaking _fpmul_parts in libgcc1.c.
+# Disabling function inlining is a workaround for this problem.
+TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
Index: gcc/config/arm/uclinux-elf.h
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/gcc/gcc/config/arm/uclinux-elf.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- gcc/config/arm/uclinux-elf.h	2001/12/06 14:08:05	1.1.1.1
+++ gcc/config/arm/uclinux-elf.h	2001/12/20 14:02:57	1.2
@@ -30,3 +30,18 @@
 
 #undef  TARGET_DEFAULT
 #define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS | ARM_FLAG_SINGLE_PIC_BASE)
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS \
+        { "marm", "mlittle-endian", "mhard-float", "mapcs-32",      \
+            "mno-thumb-interwork", "fno-pic", "msingle-pic-base" }
+
+/* Redefine these - linux-elf.h tries to link crt[1in].o, 
+   uClib requires crt0.o. also, we don't need crt(begin|end).o */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC  "crt0%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC    ""
+

Index: Makefile
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/elf2flt/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- Makefile	2001/12/06 14:21:02	1.1.1.1
+++ Makefile	2001/12/20 13:57:45	1.2
@@ -1,3 +1,5 @@
+# Because of a problem with the newer libbfd.a (2.11.2), we have a 2.10 one
+# locally. Ugly as hell, but...
 
 # PREFIX = /home/public/gcc/build-binutils/m68k-elf
 # PREFIX = /home/new-wave/tools
@@ -6,8 +8,8 @@
 CC = gcc
 CFLAGS = -O2 -g -DDEBUG -static -I$(PREFIX)/include $(EXTRA_CFLAGS)
 
-M68K_BFD = ${PREFIX}/bfd/libbfd.a
-M68K_IBERTY = ${PREFIX}/libiberty/libiberty.a
+M68K_BFD = libbfd.a
+M68K_IBERTY = libiberty.a
 
 LBFD = $(M68K_BFD) $(M68K_IBERTY)
 
Index: elf2flt.ld
===================================================================
RCS file: /home/acter/Software/cvsroot/TOOLS/elf2flt/elf2flt.ld,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- elf2flt.ld	2001/12/20 09:13:38	1.1.1.2
+++ elf2flt.ld	2001/12/20 15:09:46	1.4
@@ -87,6 +87,11 @@
 				_end = . ;
 				end = . ;
         } > flatmem
+        .debug_arranges 0 : { *(.debug_arranges) }
+        .debug_pubnames 0 : { *(.debug_pubnames) }
+        .debug_info 0 : { *(.debug_info) }
+        .debug_abbrev 0 : { *(.debug_abbrev) }
+        .debug_line 0 : { *(.debug_line) }
 
 		.junk :
 		{


This message resent by the uclinux-dev@uclinux.org list server http://www.uClinux.org/


This archive was generated by hypermail 2.1.4 : Thu Sep 19 2002 - 13:20:38 EDT