From 4ab3322bcc988a6a0c0c1d2236d73e20b01dcf2e Mon Sep 17 00:00:00 2001 From: John Bowler Date: Thu, 22 Sep 2005 19:44:38 +0000 Subject: 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. --- packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch | 153 +++++++++++++++ .../uclibc/uclibc-0.9.28/thumb-call-via-rx.patch | 207 +++++++++++++++++++++ .../uclibc/uclibc-0.9.28/thumb-mov-pc-bx.patch | 85 ++++++++- packages/uclibc/uclibc-0.9.28/thumb-resolve.patch | 130 ++++++++++--- packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch | 48 +++++ packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch | 45 +++++ packages/uclibc/uclibc_0.9.28.bb | 16 +- 7 files changed, 644 insertions(+), 40 deletions(-) create mode 100644 packages/uclibc/uclibc-0.9.28/thumb-asm-swi.patch create mode 100644 packages/uclibc/uclibc-0.9.28/thumb-call-via-rx.patch create mode 100644 packages/uclibc/uclibc-0.9.28/thumb-swi-r7.patch create mode 100644 packages/uclibc/uclibc-0.9.28/thumb-sysnum-h.patch (limited to 'packages') 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 + */ + ++#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 + .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 directly; include 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}" -- cgit v1.2.3