mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-31 14:01:18 +08:00
arm: Introduce and use GET_TLS
Factor out the sequence needed to call kuser_get_tls, as we can't play subtract into pc games in thumb mode. Prepare for hard-tp, pulling the save of LR into the macro.
This commit is contained in:
parent
3ae44082ab
commit
5232b909bf
@ -1,5 +1,18 @@
|
||||
2013-03-06 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sysdeps/arm/sysdep.h (GET_TLS): New macro.
|
||||
* sysdeps/arm/dl-tlsdesc.S (_dl_tlsdesc_undefweak): Use it.
|
||||
(_dl_tlsdesc_dynamic): Likewise.
|
||||
* sysdeps/unix/arm/sysdep.S (__syscall_error): Likewise.
|
||||
* sysdeps/unix/sysv/linux/arm/sysdep.h (GET_TLS): New macro.
|
||||
* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Likewise.
|
||||
* sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S (SAVE_PID): Likewise.
|
||||
* sysdeps/unix/sysv/linux/arm/nptl/vfork.S (SAVE_PID): Likewise.
|
||||
* sysdeps/unix/sysv/linux/arm/nptl/sysdep-cancel.h (SINGLE_THREAD_P):
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/arm/aeabi_read_tp.S (__aeabi_read_tp):
|
||||
Add thumb2 alternative.
|
||||
|
||||
* sysdeps/arm/sysdep.h (NEGOFF_ADJ_BASE): New macro.
|
||||
(NEGOFF_ADJ_BASE2, NEGOFF_OFF1, NEGOFF_OFF2): New macros.
|
||||
* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Use them.
|
||||
|
@ -50,18 +50,9 @@ _dl_tlsdesc_return:
|
||||
.fnstart
|
||||
.align 2
|
||||
_dl_tlsdesc_undefweak:
|
||||
@ Are we allowed a misaligned stack pointer calling read_tp?
|
||||
.save {lr}
|
||||
stmdb sp!, {lr}
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (lr,0)
|
||||
bl __aeabi_read_tp
|
||||
GET_TLS (r1)
|
||||
rsb r0, r0, #0
|
||||
ldmia sp!, {lr}
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (lr)
|
||||
BX (lr)
|
||||
|
||||
cfi_endproc
|
||||
.fnend
|
||||
.size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
|
||||
@ -106,7 +97,7 @@ _dl_tlsdesc_dynamic:
|
||||
cfi_rel_offset (r4,8)
|
||||
cfi_rel_offset (lr,12)
|
||||
ldr r1, [r0] /* td */
|
||||
bl __aeabi_read_tp
|
||||
GET_TLS (lr)
|
||||
mov r4, r0 /* r4 = tp */
|
||||
ldr r0, [r0]
|
||||
ldr r2, [r1, #8] /* gen_count */
|
||||
|
@ -150,6 +150,25 @@
|
||||
# define NEGOFF_OFF1(R, OFF) [R, $OFF]
|
||||
# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
|
||||
# endif
|
||||
|
||||
/* Helper to get the TLS base pointer. The interface is that TMP is a
|
||||
register that may be used to hold the LR, if necessary. TMP may be
|
||||
LR itself to indicate that LR need not be saved. The base pointer
|
||||
is returned in R0. Only R0 and TMP are modified.
|
||||
|
||||
At this generic level we have no tricks to pull. Call the ABI routine. */
|
||||
# define GET_TLS(TMP) \
|
||||
push { r1, r2, r3, lr }; \
|
||||
cfi_remember_state; \
|
||||
cfi_adjust_cfa_offset (16); \
|
||||
cfi_rel_offset (r1, 0); \
|
||||
cfi_rel_offset (r2, 4); \
|
||||
cfi_rel_offset (r3, 8); \
|
||||
cfi_rel_offset (lr, 12); \
|
||||
bl __aeabi_read_tp; \
|
||||
pop { r1, r2, r3, lr }; \
|
||||
cfi_restore_state
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/* This number is the offset from the pc at the current location. */
|
||||
|
@ -37,14 +37,8 @@ __syscall_error:
|
||||
#endif
|
||||
|
||||
#ifndef IS_IN_rtld
|
||||
mov ip, lr
|
||||
cfi_register (lr, ip)
|
||||
mov r1, r0
|
||||
|
||||
mov r0, #0xffff0fff
|
||||
mov lr, pc
|
||||
sub pc, r0, #31
|
||||
|
||||
mov r1, r0
|
||||
GET_TLS (r2)
|
||||
ldr r2, 1f
|
||||
#ifdef __thumb__
|
||||
2: add r2, r2, pc
|
||||
@ -54,7 +48,7 @@ __syscall_error:
|
||||
#endif
|
||||
str r1, [r0, r2]
|
||||
mvn r0, #0
|
||||
DO_RET(ip)
|
||||
DO_RET(lr)
|
||||
|
||||
1: .word errno(gottpoff) + (. - 2b - PC_OFS)
|
||||
#elif RTLD_PRIVATE_ERRNO
|
||||
|
@ -41,6 +41,12 @@
|
||||
|
||||
.hidden __aeabi_read_tp
|
||||
ENTRY (__aeabi_read_tp)
|
||||
#ifdef __thumb2__
|
||||
movw r0, #0x0fe0
|
||||
movt r0, #0xffff
|
||||
bx r0
|
||||
#else
|
||||
mov r0, #0xffff0fff
|
||||
sub pc, r0, #31
|
||||
#endif
|
||||
END (__aeabi_read_tp)
|
||||
|
@ -74,9 +74,7 @@ PSEUDO_END (__clone)
|
||||
#ifdef RESET_PID
|
||||
tst ip, #CLONE_THREAD
|
||||
bne 3f
|
||||
mov r0, #0xffff0fff
|
||||
mov lr, pc
|
||||
sub pc, r0, #31
|
||||
GET_TLS (lr)
|
||||
mov r1, r0
|
||||
tst ip, #CLONE_VM
|
||||
ldr r7, =SYS_ify(getpid)
|
||||
|
@ -19,15 +19,7 @@
|
||||
|
||||
/* Save the PID value. */
|
||||
#define SAVE_PID \
|
||||
str lr, [sp, #-4]!; /* Save LR. */ \
|
||||
cfi_adjust_cfa_offset (4); \
|
||||
cfi_rel_offset (lr, 0); \
|
||||
mov r0, #0xffff0fff; /* Point to the high page. */ \
|
||||
mov lr, pc; /* Save our return address. */ \
|
||||
sub pc, r0, #31; /* Jump to the TLS entry. */ \
|
||||
ldr lr, [sp], #4; /* Restore LR. */ \
|
||||
cfi_adjust_cfa_offset (-4); \
|
||||
cfi_restore (lr); \
|
||||
GET_TLS (r2); \
|
||||
NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2. */ \
|
||||
ldr r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID. */ \
|
||||
rsb r0, r3, #0; /* Negate it. */ \
|
||||
|
@ -216,7 +216,7 @@ extern int __local_multiple_threads attribute_hidden;
|
||||
stmfd sp!, {r0, lr}; \
|
||||
cfi_adjust_cfa_offset (8); \
|
||||
cfi_rel_offset (lr, 4); \
|
||||
bl __aeabi_read_tp; \
|
||||
GET_TLS (lr); \
|
||||
NEGOFF_ADJ_BASE (r0, MULTIPLE_THREADS_OFFSET); \
|
||||
ldr ip, NEGOFF_OFF1 (r0, MULTIPLE_THREADS_OFFSET); \
|
||||
ldmfd sp!, {r0, lr}; \
|
||||
|
@ -19,15 +19,7 @@
|
||||
|
||||
/* Save the PID value. */
|
||||
#define SAVE_PID \
|
||||
str lr, [sp, #-4]!; /* Save LR. */ \
|
||||
cfi_adjust_cfa_offset (4); \
|
||||
cfi_rel_offset (lr, 0); \
|
||||
mov r0, #0xffff0fff; /* Point to the high page. */ \
|
||||
mov lr, pc; /* Save our return address. */ \
|
||||
sub pc, r0, #31; /* Jump to the TLS entry. */ \
|
||||
ldr lr, [sp], #4; /* Restore LR. */ \
|
||||
cfi_adjust_cfa_offset (-4); \
|
||||
cfi_restore (lr); \
|
||||
GET_TLS (r2); \
|
||||
NEGOFF_ADJ_BASE2 (r2, r0, PID_OFFSET); /* Save the TLS addr in r2. */ \
|
||||
ldr r3, NEGOFF_OFF1 (r2, PID_OFFSET); /* Load the saved PID. */ \
|
||||
rsbs r0, r3, #0; /* Negate it. */ \
|
||||
|
@ -45,6 +45,36 @@
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
|
||||
/* Internal macro calling the linux kernel kuser_get_tls helper.
|
||||
Note that in thumb mode, a constant pool break is often out of range, so
|
||||
we always expand the constant inline. */
|
||||
#ifdef __thumb2__
|
||||
# define GET_TLS_BODY \
|
||||
movw r0, #0x0fe0; \
|
||||
movt r0, #0xffff; \
|
||||
blx r0
|
||||
#else
|
||||
# define GET_TLS_BODY \
|
||||
mov r0, #0xffff0fff; /* Point to the high page. */ \
|
||||
mov lr, pc; /* Save our return address. */ \
|
||||
sub pc, r0, #31 /* Jump to the TLS entry. */
|
||||
#endif
|
||||
|
||||
/* Helper to get the TLS base pointer. Save LR in TMP, return in R0,
|
||||
and no other registers clobbered. TMP may be LR itself to indicate
|
||||
that no save is necessary. */
|
||||
#undef GET_TLS
|
||||
#define GET_TLS(TMP) \
|
||||
.ifnc TMP, lr; \
|
||||
mov TMP, lr; \
|
||||
cfi_register (lr, TMP); \
|
||||
GET_TLS_BODY; \
|
||||
mov lr, TMP; \
|
||||
cfi_restore (lr); \
|
||||
.else; \
|
||||
GET_TLS_BODY; \
|
||||
.endif
|
||||
|
||||
/* Linux uses a negative return value to indicate syscall errors,
|
||||
unlike most Unices, which use the condition codes' carry flag.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user