summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2006-11-10 20:37:45 +0000
committerEric Andersen <andersen@codepoet.org>2006-11-10 20:37:45 +0000
commit90c3c3ed5eec1062168d1ac0beb41044a9de7c58 (patch)
tree1ae4dd623f6b09dadc59b318e7958d71c07a6446
parentf7dfb7453d8c0a66ba0de0446d1dcfc5afc29118 (diff)
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.
-rw-r--r--ldso/ldso/arm/dl-syscalls.h35
-rw-r--r--libc/sysdeps/linux/arm/crti.S90
-rw-r--r--libc/sysdeps/linux/arm/crtn.S25
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)"