summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)"