From 90c3c3ed5eec1062168d1ac0beb41044a9de7c58 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Fri, 10 Nov 2006 20:37:45 +0000 Subject: arm thumb: 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. --- libc/sysdeps/linux/arm/crti.S | 90 +++++++++++++++++++++++++++++++++++-------- libc/sysdeps/linux/arm/crtn.S | 25 ++++++++++-- 2 files changed, 96 insertions(+), 19 deletions(-) (limited to 'libc') 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)" -- cgit v1.2.3