# Put the call_via_rx code into each executable - call_via_ip cannot
# possibly work if called through the PLT!  ldso requires this code
# too as it is not linked with the crt stuff and thumb ldso does
# make calls via a register.
#
# The patch puts the code into crti.S so that it is linked into
# every normally built application (if thumb or interworking is
# selected).  This is only 30 extra bytes and it works - the previous
# code did not because nothing both implemented and exported the
# APIs (they were in libgcc, but not in the version script).
#
# crti.S and crtn.S is also brought up to date with GCC 3.4.4 - this
# is essential for thumb support because the .init and .fini sections
# must use arm or thumb code to match the compilation of the libraries.
#
# Note that code which pushes stuff into .init or .fini must be
# compiled with or without -mthumb to match the uclibc compilation -
# and gcc itself (which does do this) must therefore be compiled to
# match.
#
--- uClibc-0.9.28/.pc/thumb-call-via-rx.patch/libc/sysdeps/linux/arm/crti.S	2005-08-17 15:49:41.000000000 -0700
+++ uClibc-0.9.28/libc/sysdeps/linux/arm/crti.S	2005-09-21 19:15:19.996721584 -0700
@@ -1,26 +1,86 @@
 	.file	"initfini.c"
 	
 	.section .init
-	.align	2
 	.global	_init
 	.type	_init, %function
+#if defined __thumb__
+	.align	1
+	.thumb
+	.thumb_func
 _init:
-	@ args = 0, pretend = 0, frame = 0
-	@ frame_needed = 0, uses_anonymous_args = 0
-	str	lr, [sp, #-4]!
-	
-	.align 2
-	
-	
-	.section .fini
+	push	{r4-r7, lr}
+#else
 	.align	2
+	.arm
+_init:
+	@ gcc 3.3.2 didn't create a stack frame, gcc 3.4.4 does -
+	@ presumably 3.4.4 can put stuff into .init which requires
+	@ the arguments to be saved.  This code is copied from 3.4.4
+	mov	ip, sp
+	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+	sub	fp, ip, #4
+#endif
+
+
+	.section .fini
 	.global	_fini
 	.type	_fini, %function
+#if defined __thumb__
+	.align	1
+	.thumb
+	.thumb_func
 _fini:
-	@ args = 0, pretend = 0, frame = 0
-	@ frame_needed = 0, uses_anonymous_args = 0
-	str	lr, [sp, #-4]!
-	.align 2
-	
-	
+	push	{r4-r7, lr}
+#else
+	.align	2
+	.arm
+_fini:
+	mov	ip, sp
+	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+	sub	fp, ip, #4
+#endif
+
+
+#if (defined __thumb__ || defined __THUMB_INTERWORK__) && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
+	@ To support thumb code it is currently necessary to have the _call_via_rX
+	@ functions exposed to the linker for any program or shared library.  PLT
+	@ references are inadequate - the PLT zaps ip and therefore breaks _call_via_ip
+	@ (and the compiler does generate this).  It is simpler to put all the
+	@ required code in here - it only amounts to 60 bytes overhead.
+	@NOTE: it would be better to have the compiler generate this stuff as
+	@ required...
+	.section	".text"
+	.align 0
+	.force_thumb
+
+.macro call_via register
+	.global _call_via_\register
+	.type	_call_via_\register, %function
+	.weak	_call_via_\register
+	.hidden	_call_via_\register
+	.thumb_func
+_call_via_\register:
+	bx	\register
+	nop
+	.size	_call_via_\register, . - _call_via_\register
+.endm
+
+	@ and calls for the 15 general purpose registers (2 bytes each).
+	call_via r0
+	call_via r1
+	call_via r2
+	call_via r3
+	call_via r4
+	call_via r5
+	call_via r6
+	call_via r7
+	call_via r8
+	call_via r9
+	call_via sl
+	call_via fp
+	call_via ip
+	call_via sp
+	call_via lr
+#endif
+
 	.ident	"GCC: (GNU) 3.3.2 20031005 (Debian prerelease)"
--- uClibc-0.9.28/libc/sysdeps/linux/arm/crtn.S.orig	2005-09-20 16:39:20.010925582 -0700
+++ uClibc-0.9.28/libc/sysdeps/linux/arm/crtn.S	2005-09-20 17:00:51.700206464 -0700
@@ -1,17 +1,34 @@
 	.file	"initfini.c"
 	
 	.section .init
-	.align	2
 	.global	_init
 	.type	_init, %function
-	ldr	pc, [sp], #4
+#if defined __thumb__
+	.align	1
+	.thumb
+	@ this will not work on ARMv4T, but lots of stuff
+	@ in here won't work there anyway...
+	pop	{r4-r7, pc}
+#else
+	.align	2
+	.arm
+	ldmdb	fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
+#endif
 	.size	_init, .-_init
 	
 	.section .fini
-	.align	2
 	.global	_fini
 	.type	_fini, %function
-	ldr	pc, [sp], #4
+#if defined __thumb__
+	.align	1
+	.thumb
+	pop	{r4-r7, pc}
+#else
+	.align	2
+	.arm
+	ldmdb	fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
+#endif
 	.size	_fini, .-_fini
 	
+	@ In fact this is modified to 3.4.4
 	.ident	"GCC: (GNU) 3.3.2 20031005 (Debian prerelease)"
--- uClibc-0.9.28/.pc/thumb-call-via-rx.patch/ldso/ldso/arm/dl-syscalls.h	2005-08-17 15:49:41.000000000 -0700
+++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h	2005-09-21 19:17:01.143086323 -0700
@@ -4,3 +4,39 @@
 #define __set_errno(X) {(_dl_errno) = (X);}
 #include "sys/syscall.h"
 
+/* _call_via_rX calls are used in thumb ldso because of calls via
+ * function pointers, but ldso is not linked with anything which
+ * provides them, so define them here (only required for thumb).
+ */
+#if defined(__thumb__)
+asm(
+	".macro call_via register\n"
+	"	.global	_call_via_\\register\n"
+	"	.hidden	_call_via_\\register\n"
+	"	.type	_call_via_\\register, %function\n"
+	"	.thumb_func\n"
+	"_call_via_\\register:\n"
+	"	bx	\\register\n"
+	"	.size	_call_via_\\register, . - _call_via_\\register\n"
+	".endm\n"
+
+	".text\n"
+	".thumb\n"
+	".align 1\n"
+	"	call_via r0\n"
+	"	call_via r1\n"
+	"	call_via r2\n"
+	"	call_via r3\n"
+	"	call_via r4\n"
+	"	call_via r5\n"
+	"	call_via r6\n"
+	"	call_via r7\n"
+	"	call_via r8\n"
+	"	call_via r9\n"
+	"	call_via r10\n"
+	"	call_via r11\n"
+	"	call_via r12\n"
+	"	call_via r13\n"
+	"	call_via r14\n"
+);
+#endif