1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# This patch changes all cases where the ARM assembler mov pc,rx
# instructions are used to ensure that the thumb/arm interwork change of
# process more works - in essence mov pc,rx needs to become bx rc.
#
# The ldr pc or ldm rx, {pc} instructions are not changed - this is
# fine on ARM >=v5 but will fail to restore thumb mode on ARM v4T,
# i.e. this code will not provide support for thumb on ARM v4T.
#
# One mov pc is left in resolve.S, this is fixed in a different patch -
# thumb-resolve.patch
#
# The changes are protected by __THUMB_INTERWORK__ - the original
# mov instruction will work on newer architectures and is required on
# arch v4 (not v4t) and earlier - those which did not support thumb -
# 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 @@
" .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"
" @ jump to the user_s entry point\n"
+#if defined(__THUMB_INTERWORK__)
+ " bx r6\n"
+#else
" mov pc, r6\n"
+#endif
".L_GET_GOT:\n"
" .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
".L_SKIP_ARGS:\n"
--- 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 @@
extern void __dl_start asm ("_dl_start");
Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
Elf32_Addr pcrel_addr;
+#if !defined(__thumb__)
+ /* On thumb this has to be two instructions because
+ * the offset is negative.
+ */
asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
+#else
+ /* This is dumb, gcc should support a thumb adrl
+ * but it doesn't, so this is the same thing the
+ * hard way. If this code moves too far from _dl_start
+ * it will fail.
+ */
+ asm ("adr\t%0, 1f\n1:\tsub\t%0, #1b-_dl_start\n" : "=r" (pcrel_addr));
+#endif
return pcrel_addr - got_addr;
}
--- uClibc-0.9.28/.pc/thumb-mov-pc-bx.patch/libc/sysdeps/linux/arm/clone.S 2005-08-17 15:49:41.000000000 -0700
+++ uClibc-0.9.28/libc/sysdeps/linux/arm/clone.S 2005-09-08 09:36:24.801986529 -0700
@@ -51,7 +51,11 @@
swi __NR_clone
movs a1, a1
blt __error
- movne pc, lr
+#if defined(__THUMB_INTERWORK__)
+ bxne lr
+#else
+ movne pc, lr
+#endif
@ pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
--- uClibc-0.9.28/.pc/thumb-mov-pc-bx.patch/libc/sysdeps/linux/arm/vfork.S 2005-08-17 15:49:41.000000000 -0700
+++ uClibc-0.9.28/libc/sysdeps/linux/arm/vfork.S 2005-09-08 09:51:13.377901086 -0700
@@ -34,7 +34,11 @@
#ifdef __NR_vfork
swi __NR_vfork
cmn r0, #4096
+#if defined(__THUMB_INTERWORK__)
+ bxcc lr
+#else
movcc pc, lr
+#endif
/* Check if vfork even exists. */
ldr r1, =-ENOSYS
@@ -47,7 +51,11 @@
cmn r0, #4096
/* Syscal worked. Return to child/parent */
- movcc pc, lr
+#if defined(__THUMB_INTERWORK__)
+ bxcc lr
+#else
+ movcc pc, lr
+#endif
__error:
b __syscall_error
|