diff options
-rw-r--r-- | ldso/ldso/arm/dl-syscalls.h | 35 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/crti.S | 90 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/crtn.S | 25 |
3 files changed, 131 insertions, 19 deletions
diff --git a/ldso/ldso/arm/dl-syscalls.h b/ldso/ldso/arm/dl-syscalls.h index 4b42a57e0..ecbe96a1c 100644 --- a/ldso/ldso/arm/dl-syscalls.h +++ b/ldso/ldso/arm/dl-syscalls.h @@ -4,4 +4,39 @@ extern int _dl_errno; #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} +/* _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/libc/sysdeps/linux/arm/crti.S b/libc/sysdeps/linux/arm/crti.S index 0cacb1f10..4835b8331 100644 --- a/libc/sysdeps/linux/arm/crti.S +++ b/libc/sysdeps/linux/arm/crti.S @@ -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)" diff --git a/libc/sysdeps/linux/arm/crtn.S b/libc/sysdeps/linux/arm/crtn.S index 851898de0..7a1ca1ab1 100644 --- a/libc/sysdeps/linux/arm/crtn.S +++ b/libc/sysdeps/linux/arm/crtn.S @@ -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)" |