summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@nslu2-linux.org>2005-09-22 19:44:38 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2005-09-22 19:44:38 +0000
commit4ab3322bcc988a6a0c0c1d2236d73e20b01dcf2e (patch)
treecb8ec7dcda091bcbce203d551fb80f2e4132be3e /packages
parentcd49c7be0f05ac20ec76176f921936b00e1b2e8f (diff)
uclibc_0.9.28: fix thumb support to allow thumb uclibc
This, together with the fixes in gcc and binutils, allows a system to be build with thumb libgcc and libuClibc (etc). ucslugc is changed to release 2 and to use thumb compilation of these modules.
Diffstat (limited to 'packages')
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch153
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-call-via-rx.patch207
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch85
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-resolve.patch130
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch48
-rw-r--r--packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch45
-rw-r--r--packages/uclibc/uclibc_0.9.28.bb16
7 files changed, 644 insertions, 40 deletions
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch b/packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch
new file mode 100644
index 0000000000..35e53caa5c
--- /dev/null
+++ b/packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch
@@ -0,0 +1,153 @@
+# WARNING: nasty hack. Because sysnum.h produces thumb syscall
+# numbers when compiled in thumb mode the arm assembler (which is arm
+# even in thumb mode) needs to write the OS syscall base back into
+# the swi calls. This is done here just by orring in the correct
+# value. This is a hack - it might be better to add a define to
+# sysnum.h to force it to output arm (not thumb) values on demand -
+# but this hack is fairly safe (rmk would have to change the syscall
+# base, this seems unlikely).
+#
+# The patch also fixes up the .align directives to '2' (i.e. a multiple
+# of 4) not '4' (a multiple of 16 - apparently an error since it seems
+# to be unnecessary, there is no advantage here in cache line alignment).
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/__longjmp.S uClibc-0.9.28/libc/sysdeps/linux/arm/__longjmp.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/__longjmp.S 2005-09-18 18:41:36.870986621 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/__longjmp.S 2005-09-18 19:01:26.741860474 -0700
+@@ -25,7 +25,7 @@
+
+ .global __longjmp
+ .type __longjmp,%function
+-.align 4
++.align 2
+ __longjmp:
+ mov ip, r0 /* save jmp_buf pointer */
+
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/bsd-_setjmp.S uClibc-0.9.28/libc/sysdeps/linux/arm/bsd-_setjmp.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/bsd-_setjmp.S 2005-09-18 18:41:36.870986621 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/bsd-_setjmp.S 2005-09-18 19:01:31.982190228 -0700
+@@ -27,7 +27,7 @@
+
+ .global _setjmp
+ .type _setjmp,%function
+-.align 4
++.align 2
+ _setjmp:
+ mov r1, #0
+ #ifdef __PIC__
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/bsd-setjmp.S uClibc-0.9.28/libc/sysdeps/linux/arm/bsd-setjmp.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/bsd-setjmp.S 2005-09-18 18:41:36.870986621 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/bsd-setjmp.S 2005-09-18 19:01:40.166705247 -0700
+@@ -27,7 +27,7 @@
+
+ .global setjmp
+ .type setjmp,%function
+-.align 4
++.align 2
+ setjmp:
+ mov r1, #1
+ #ifdef __PIC__
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/clone.S uClibc-0.9.28/libc/sysdeps/linux/arm/clone.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/clone.S 2005-09-18 18:41:36.870986621 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/clone.S 2005-09-18 19:01:45.427036258 -0700
+@@ -30,7 +30,7 @@
+ .text
+ .global __clone
+ .type __clone,%function
+-.align 4
++.align 2
+ __clone:
+ @ sanity check args
+ cmp r0, #0
+@@ -48,7 +48,7 @@
+ @ get flags
+ mov r0, r2
+ @ new sp is already in r1
+- swi __NR_clone
++ swi (__NR_clone | 0x900000)
+ movs a1, a1
+ blt __error
+ #if defined(__THUMB_INTERWORK__)
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/mmap64.S uClibc-0.9.28/libc/sysdeps/linux/arm/mmap64.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/mmap64.S 2005-09-18 18:41:36.874986873 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/mmap64.S 2005-09-18 19:02:03.692185612 -0700
+@@ -27,7 +27,7 @@
+ .text
+ .global mmap64
+ .type mmap64,%function
+-.align 4
++.align 2
+ mmap64:
+ stmfd sp!, {r4, r5, lr}
+ ldr r5, [sp, $16]
+@@ -40,7 +40,7 @@
+ movs ip, ip, lsr $12
+ bne .Linval @ check for overflow
+ mov ip, r0
+- swi __NR_mmap2
++ swi (__NR_mmap2 | 0x900000)
+ cmn r0, $4096
+ ldmccfd sp!, {r4, r5, pc}
+ cmn r0, $ENOSYS
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/setjmp.S uClibc-0.9.28/libc/sysdeps/linux/arm/setjmp.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/setjmp.S 2005-09-18 18:41:36.874986873 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/setjmp.S 2005-09-18 19:02:08.956516875 -0700
+@@ -24,7 +24,7 @@
+
+ .global __sigsetjmp
+ .type __sigsetjmp,%function
+-.align 4
++.align 2
+ __sigsetjmp:
+ /* Save registers */
+ #if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/sigrestorer.S uClibc-0.9.28/libc/sysdeps/linux/arm/sigrestorer.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/sigrestorer.S 2005-09-18 18:41:36.874986873 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/sigrestorer.S 2005-09-18 19:02:18.041088531 -0700
+@@ -24,17 +24,17 @@
+
+ .global __default_sa_restorer
+ .type __default_sa_restorer,%function
+-.align 4
++.align 2
+ __default_sa_restorer:
+- swi __NR_sigreturn
++ swi (__NR_sigreturn | 0x900000)
+
+
+ #ifdef __NR_rt_sigreturn
+
+ .global __default_rt_sa_restorer
+ .type __default_rt_sa_restorer,%function
+-.align 4
++.align 2
+ __default_rt_sa_restorer:
+- swi __NR_rt_sigreturn
++ swi (__NR_rt_sigreturn | 0x900000)
+
+ #endif
+diff -u uClibc-0.9.28/libc/sysdeps/linux/arm/orig/vfork.S uClibc-0.9.28/libc/sysdeps/linux/arm/vfork.S
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/orig/vfork.S 2005-09-18 18:41:36.874986873 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/vfork.S 2005-09-18 19:02:23.561435905 -0700
+@@ -28,11 +28,11 @@
+ .text
+ .global vfork
+ .type vfork,%function
+-.align 4
++.align 2
+ vfork:
+
+ #ifdef __NR_vfork
+- swi __NR_vfork
++ swi (__NR_vfork | 0x900000)
+ cmn r0, #4096
+ #if defined(__THUMB_INTERWORK__)
+ bxcc lr
+@@ -47,7 +47,7 @@
+ #endif
+
+ /* If we don't have vfork, use fork. */
+- swi __NR_fork
++ swi (__NR_fork | 0x900000)
+ cmn r0, #4096
+
+ /* Syscal worked. Return to child/parent */
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-call-via-rx.patch b/packages/uclibc/uclibc-0.9.28/thumb-call-via-rx.patch
new file mode 100644
index 0000000000..eae54f37e5
--- /dev/null
+++ b/packages/uclibc/uclibc-0.9.28/thumb-call-via-rx.patch
@@ -0,0 +1,207 @@
+# 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
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch b/packages/uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch
index 86713a7678..44191695e7 100644
--- a/packages/uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch
+++ b/packages/uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch
@@ -15,15 +15,15 @@
# so this is safe. See gcc lib1asmfuncs for a more exact test.
#
--- uClibc-0.9.28/.pc/thumb-mov-pc-bx.patch/ldso/ldso/arm/dl-startup.h 2005-08-17 15:49:41.000000000 -0700
-+++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2005-09-08 09:34:22.918316874 -0700
-@@ -8,6 +8,7 @@
++++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2005-09-16 23:38:34.266546180 -0700
+@@ -4,6 +4,7 @@
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+
++#if defined(__arm__)
+ asm(
" .text\n"
" .globl _start\n"
- " .type _start,%function\n"
-+ " .arm\n"
- "_start:\n"
- " @ at start time, all the args are on the stack\n"
- " mov r0, sp\n"
@@ -40,7 +41,11 @@
" ldr r0, .L_FINI_PROC\n"
" ldr r0, [sl, r0]\n"
@@ -36,6 +36,77 @@
".L_GET_GOT:\n"
" .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
".L_SKIP_ARGS:\n"
+@@ -51,6 +56,70 @@
+ " .size _start,.-_start\n"
+ ".previous\n"
+ );
++#else
++asm(
++ " .text\n"
++ " .arm\n"
++ " .globl _start\n"
++ " .type _start,%function\n"
++ "_start:\n"
++ " @ dumb: can't persuade the linker to make the start address\n"
++ " @ odd, so use an arm function and change to thumb (_dl_start\n"
++ " @ is thumb)\n"
++ " adr r0, __dl_thumb_start+1\n"
++ " bx r0\n"
++ "\n\n"
++ " .thumb\n"
++ " .globl __dl_thumb_start\n"
++ " .thumb_func\n"
++ " .type __dl_thumb_start,%function\n"
++ "__dl_thumb_start:\n"
++ " @ at start time, all the args are on the stack\n"
++ " mov r0, sp\n"
++ " bl _dl_start\n"
++ " @ returns user entry point in r0\n"
++ " mov r6, r0\n"
++ " @ we are PIC code, so get global offset table\n"
++ " ldr r7, .L_GET_GOT\n"
++ ".L_GOT_GOT:\n"
++ " add r7, pc\n"
++ " @ See if we were run as a command with the executable file\n"
++ " @ name as an extra leading argument.\n"
++ " ldr r4, .L_SKIP_ARGS\n"
++ " ldr r4, [r7, r4]\n"
++ " @ get the original arg count\n"
++ " ldr r1, [sp]\n"
++ " @ subtract _dl_skip_args from it\n"
++ " sub r1, r1, r4\n"
++ " @ adjust the stack pointer to skip them\n"
++ " lsl r4, r4, #2\n"
++ " add sp, r4\n"
++ " @ get the argv address\n"
++ " add r2, sp, #4\n"
++ " @ store the new argc in the new stack location\n"
++ " str r1, [sp]\n"
++ " @ compute envp\n"
++ " lsl r3, r1, #2\n"
++ " add r3, r3, r2\n"
++ " add r3, #4\n"
++ "\n\n"
++ " @ load the finalizer function\n"
++ " ldr r0, .L_FINI_PROC\n"
++ " ldr r0, [r7, r0]\n"
++ " @ jump to the user_s entry point\n"
++ " bx r6\n"
++ "\n\n"
++ ".L_GET_GOT:\n"
++ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
++ ".L_SKIP_ARGS:\n"
++ " .word _dl_skip_args(GOTOFF)\n"
++ ".L_FINI_PROC:\n"
++ " .word _dl_fini(GOT)\n"
++ "\n\n"
++ " .size _start,.-_start\n"
++ ".previous\n"
++);
++#endif
+
+
+ /* Get a pointer to the argv array. On many platforms this can be just
--- uClibc-0.9.28/.pc/thumb-mov-pc-bx.patch/ldso/ldso/arm/dl-sysdep.h 2005-08-17 15:49:41.000000000 -0700
+++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2005-09-07 20:10:35.923583424 -0700
@@ -85,7 +85,19 @@
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch b/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch
index 9d1db384ab..0a99a7d9bc 100644
--- a/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch
+++ b/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch
@@ -5,7 +5,7 @@
# count (faster in caller and callee, and slightly easier to understand).
#
--- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/arm/elfinterp.c 2005-08-17 15:49:41.000000000 -0700
-+++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2005-09-07 20:10:36.231602806 -0700
++++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2005-09-17 12:55:26.379172744 -0700
@@ -55,7 +55,7 @@
rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL];
@@ -15,9 +15,19 @@
reloc_type = ELF32_R_TYPE(this_reloc->r_info);
symtab_index = ELF32_R_SYM(this_reloc->r_info);
+@@ -84,7 +84,9 @@
+ _dl_exit(1);
+ };
+ #if defined (__SUPPORT_LD_DEBUG__)
++#if !defined __SUPPORT_LD_DEBUG_EARLY__
+ if ((unsigned long) got_addr < 0x40000000)
++#endif
+ {
+ if (_dl_debug_bindings)
+ {
--- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/arm/resolve.S 2005-08-17 15:49:41.000000000 -0700
-+++ uClibc-0.9.28/ldso/ldso/arm/resolve.S 2005-09-08 09:54:03.536608499 -0700
-@@ -1,43 +1,121 @@
++++ uClibc-0.9.28/ldso/ldso/arm/resolve.S 2005-09-17 11:02:27.860627464 -0700
+@@ -1,43 +1,163 @@
/*
- * This function is _not_ called directly. It is jumped to (so no return
- * address is on the stack) when attempting to use a symbol that has not yet
@@ -127,16 +137,19 @@
+ * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see
+ * dl-startup.c).
*/
-
+-
-#define sl r10
-#define fp r11
-#define ip r12
--
++#include <sys/syscall.h>
+
.text
++.align 4 @ 16 byte boundary and there are 32 bytes below (arm case)
++#if !defined(__thumb__)
++.arm
.globl _dl_linux_resolve
.type _dl_linux_resolve,%function
-.align 4;
-+.align 4 @ 16 byte boundary and there are 32 bytes below
_dl_linux_resolve:
- stmdb sp!, {r0, r1, r2, r3, sl, fp}
@@ -169,18 +182,59 @@
+#else
+ mov pc, ip
+#endif
++.size _dl_linux_resolve, .-_dl_linux_resolve
++#else
++ @ In the thumb case _dl_linux_resolver is thumb. If a bl is used
++ @ from arm code the linker will insert a stub call which, with
++ @ binutils 2.16, is not PIC. Since this code is accessed by an
++ @ ldr pc the reasonable fix is to make _dl_linux_resolve thumb too.
++.thumb
++.globl _dl_linux_resolve
++.thumb_func
++.type _dl_linux_resolve,%function
++
++_dl_linux_resolve:
++ @ _dl_linux_resolver is a standard subroutine call, therefore it
++ @ preserves everything except r0-r3 (a1-a4), ip and lr. This
++ @ function must branch to the real function, and that expects
++ @ r0-r3 and lr to be as they were before the whole PLT stuff -
++ @ ip can be trashed.
++ push {r0-r3}
++ mov r1, lr @ &GOT_TABLE[2]
++ sub r0, r1, #4
++ mov r2, ip @ &GOT[n]
++ ldr r0, [r0] @ r0 := GOT_TABLE[1]
++ @ for the function call r1 := n-3
++ sub r1, r2
++ asr r1, r1, #2
++ mvn r1, r1 @ exactly as in the arm code above
++
++ bl _dl_linux_resolver
++
++ @ r0 contains the branch address, the return address is above
++ @ the saved r0..r3
++ mov ip, r0
++ ldr r1, [sp, #16]
++ mov lr, r1
++ pop {r0-r3}
++ add sp, #4
++ bx ip
++
.size _dl_linux_resolve, .-_dl_linux_resolve
---- uClibc/ldso/ldso/dl-hash.c 2005-09-08 13:54:30.124416436 -0700
-+++ uClibc/ldso/ldso/dl-hash.c 2005-09-08 14:17:44.828179610 -0700
-@@ -186,11 +186,19 @@
++#endif
+--- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/dl-hash.c 2005-08-17 15:49:41.000000000 -0700
++++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2005-09-21 18:56:31.181689732 -0700
+@@ -182,28 +182,52 @@
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
+
+ for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
++ char *result;
+ sym = &symtab[si];
- if (type_class & (sym->st_shndx == SHN_UNDEF))
+- if (type_class & (sym->st_shndx == SHN_UNDEF))
++ if (sym->st_shndx == SHN_UNDEF)
continue;
- if (_dl_strcmp(strtab + sym->st_name, name) != 0)
-- continue;
- if (sym->st_value == 0)
- continue;
-- if (ELF_ST_TYPE(sym->st_info) > STT_FUNC)
+ if (ELF_ST_TYPE(sym->st_info) > STT_FUNC
+#if defined(__arm__) || defined(__thumb__)
+ /* On ARM (only) STT_ARM_TFUNC is a function
@@ -190,26 +244,46 @@
+ && ELF_ST_TYPE(sym->st_info) != STT_ARM_TFUNC
+#endif
+ )
-+ continue;
+ continue;
+- if (sym->st_value == 0)
+ if (_dl_strcmp(strtab + sym->st_name, name) != 0)
continue;
+- if (ELF_ST_TYPE(sym->st_info) > STT_FUNC)
++#if 0
++ /* I don't know how to write this test - need to test shndx
++ * to see if it is the PLT for this module.
++ */
++ if ((type_class & ELF_RTYPE_CLASS_PLT) && some test)
+ continue;
++#endif
- switch (ELF_ST_BIND(sym->st_info)) {
-@@ -203,7 +211,17 @@
- break;
- #endif
- case STB_GLOBAL:
+#if defined(__arm__) || defined(__thumb__)
-+ /* On ARM the caller needs to know that STT_ARM_TFUNC
-+ * is a thumb function call, this is now indicated by
-+ * setting the low bit of the value (and newer binutils
-+ * will do this and record STT_FUNC).
-+ */
-+ return (char*)tpnt->loadaddr + (sym->st_value |
-+ (ELF_ST_TYPE(sym->st_info) == STT_ARM_TFUNC));
++ /* On ARM the caller needs to know that STT_ARM_TFUNC
++ * is a thumb function call, this is now indicated by
++ * setting the low bit of the value (and newer binutils
++ * will do this and record STT_FUNC).
++ */
++ result = (char*)tpnt->loadaddr + (sym->st_value |
++ (ELF_ST_TYPE(sym->st_info) == STT_ARM_TFUNC));
+#else
- return (char*)tpnt->loadaddr + sym->st_value;
++ result = (char*)tpnt->loadaddr + sym->st_value;
+#endif
+ switch (ELF_ST_BIND(sym->st_info)) {
+ case STB_WEAK:
+-#if 0
+-/* Perhaps we should support old style weak symbol handling
+- * per what glibc does when you export LD_DYNAMIC_WEAK */
++ /* Record for use later if we can't find a global. */
+ if (!weak_result)
+- weak_result = (char *)tpnt->loadaddr + sym->st_value;
++ weak_result = result;
+ break;
+-#endif
++
+ case STB_GLOBAL:
+- return (char*)tpnt->loadaddr + sym->st_value;
++ return result;
++
default: /* Local symbols not handled here */
break;
}
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch b/packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch
new file mode 100644
index 0000000000..330ceb6869
--- /dev/null
+++ b/packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch
@@ -0,0 +1,48 @@
+# This is a work round for a fairly serious GCC compiler bug - when
+# the syscall assembler overwrites r7 (required on thumb) the
+# compiler fails to protect the register when it is using it as a
+# frame pointer.
+#
+--- uClibc-0.9.28/libc/sysdeps/linux/arm/bits/syscalls.h 2005-09-12 17:51:26.062205918 -0700
++++ uClibc-0.9.28/libc/sysdeps/linux/arm/bits/syscalls.h 2005-09-12 18:16:15.507930828 -0700
+@@ -111,6 +111,11 @@
+ } \
+ (int) _sys_result; })
+ #else
++#if 0
++/* This doesn't work because GCC uses r7 as a frame pointer in
++ * some cases and doesn't notice that the _r7 value changes
++ * it, resulting in mysterious crashes after the SWI.
++ */
+ #define INTERNAL_SYSCALL(name, err, nr, args...) \
+ ({ unsigned int _sys_result; \
+ { \
+@@ -124,6 +129,28 @@
+ _sys_result = _a1; \
+ } \
+ (int) _sys_result; })
++#else
++/* So hide the use of r7 from the compiler, this would be a lot
++ * easier but for the fact that the syscalls can exceed 255.
++ * For the moment the LOAD_ARG_7 is sacrificed.
++ */
++#define INTERNAL_SYSCALL(name, err, nr, args...) \
++ ({ unsigned int _sys_result; \
++ { \
++ register int _a1 asm ("a1"); \
++ LOAD_ARGS_##nr (args) \
++ register int _v3 asm ("v3") = (int) (SYS_ify(name)); \
++ asm volatile ("push {r7}\n" \
++ "\tmov r7, v3\n" \
++ "\tswi 0 @ syscall " #name "\n" \
++ "\tpop {r7}" \
++ : "=r" (_a1) \
++ : "r" (_v3) ASM_ARGS_##nr \
++ : "memory"); \
++ _sys_result = _a1; \
++ } \
++ (int) _sys_result; })
++#endif
+ #endif
+
+ #undef INTERNAL_SYSCALL_ERROR_P
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch b/packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch
new file mode 100644
index 0000000000..599691ecee
--- /dev/null
+++ b/packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch
@@ -0,0 +1,45 @@
+--- uClibc-0.9.28/extra/scripts/gen_bits_syscall_h.sh.orig 2005-09-18 02:20:04.441119651 -0700
++++ uClibc-0.9.28/extra/scripts/gen_bits_syscall_h.sh 2005-09-18 03:17:58.287715035 -0700
+@@ -11,6 +11,37 @@
+ UNISTD_H_PATH=$TOPDIR/include/asm/unistd.h
+ INCLUDE_OPTS="-I$TOPDIR/include"
+
++# This test is added to avoid mangling the (variable) syscall base value on
++# ARM
++if echo "#if defined __arm__ || defined __thumb__
++xyzzy
++#endif" | $CC -E $INCLUDE_OPTS - | grep xyzzy >/dev/null
++then
++ echo '/* WARNING!!! AUTO-GENERATED FILE!!! DO NOT EDIT!!! */
++#ifndef _BITS_SYSNUM_H
++#define _BITS_SYSNUM_H
++
++#ifndef _SYSCALL_H
++# error "Never use <bits/sysnum.h> directly; include <sys/syscall.h> instead."
++#endif'
++ # arm case, assume unistd.h conforms to the one in 2.6.x, if not
++ # go into a corner and sulk (fix this script) The sed rune below
++ # expects items of the form UCLIBC_foo at the start of the line
++ # for each syscall number, the arm syscalls all start with lower
++ # case alpha and the all-important __NR_SYSCALL_BASE does not...
++ sed -n -e '/__sys2/Q' -e '/^[ ]*#include/,${
++ s/^[ ]*#include.*$//
++ h
++ s/^[ ]*#define[ ]*__NR_\([a-z][A-Za-z0-9_]*\)[ ]*\(.*\)[ ]*$/#undef __NR_\1\
++#define SYS_\1 __NR_\1/p
++ g
++ p
++ }' $UNISTD_H_PATH
++ # i.e. this relies on the __sys2 definition coming after the last
++ # sys number define (and #include preceding all useful definitions)
++ echo '#endif'
++else
++# non-arm case
+ ( echo "#include \"$UNISTD_H_PATH\"" ;
+ $CC -E -dN $INCLUDE_OPTS $UNISTD_H_PATH | # needed to strip out any kernel-internal defines
+ sed -ne 's/^[ ]*#define[ ]*__NR_\([A-Za-z0-9_]*\).*/UCLIBC_\1 __NR_\1/gp'
+@@ -29,3 +60,4 @@
+ echo ;
+ echo "#endif" ;
+ )
++fi
diff --git a/packages/uclibc/uclibc_0.9.28.bb b/packages/uclibc/uclibc_0.9.28.bb
index 8805f9ff2b..9214b64c0b 100644
--- a/packages/uclibc/uclibc_0.9.28.bb
+++ b/packages/uclibc/uclibc_0.9.28.bb
@@ -1,5 +1,5 @@
DEFAULT_PREFERENCE = "1"
-PR = "r2"
+PR = "r3"
include uclibc.inc
@@ -12,9 +12,6 @@ SRC_URI += "http://www.uclibc.org/downloads/uClibc-${PV}.tar.bz2"
S = "${WORKDIR}/uClibc-${PV}"
-# At present the thumb implementation is non-functional
-ARM_INSTRUCTION_SET = ""
-
#*** PATCHES ***
#
# The nokernelheadercheck patch removes the check on the include
@@ -29,4 +26,13 @@ SRC_URI += " file://thumb-defined-arm-or-thumb.patch;patch=1"
#
# Thumb interworking support
SRC_URI += " file://thumb-mov-pc-bx.patch;patch=1"
-SRC_URI += " file://thumb-resolve.patch;patch=1"
+SRC_URI += " file://thumb-swi-r7.patch;patch=1"
+SRC_URI += " file://thumb-sysnum-h.patch;patch=1"
+SRC_URI += " file://thumb-asm-swi.patch;patch=1"
+SRC_URI += " file://thumb-call-via-rx.patch;patch=1"
+#
+# This is a core change and is controversial, maybe even wrong
+# on some architectures
+THUMB_INTERWORK_RESOLVE_PATCH = ""
+THUMB_INTERWORK_RESOLVE_PATCH_thumb-interwork = " file://thumb-resolve.patch;patch=1"
+SRC_URI += " ${THUMB_INTERWORK_RESOLVE_PATCH}"