>From 53aad475518f35da7430aa86abf4f94dae7c5d30 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 28 Apr 2012 09:35:34 -0400 Subject: [PATCH] glibc: Backport ARM implementation of ucontext from upstream glibc-ports. --- glibc-ports-arm-implement-context-routines.patch | 451 ++++++++++++++++++++++ glibc.spec | 5 + 2 files changed, 456 insertions(+) create mode 100644 glibc-ports-arm-implement-context-routines.patch diff --git a/glibc-ports-arm-implement-context-routines.patch b/glibc-ports-arm-implement-context-routines.patch new file mode 100644 index 0000000..635dad8 --- /dev/null +++ b/glibc-ports-arm-implement-context-routines.patch @@ -0,0 +1,451 @@ +From 402a76b62dded0ee93cfec0471aaeccb989196d2 Mon Sep 17 00:00:00 2001 +From: Michael Hope +Date: Mon, 5 Mar 2012 17:58:13 -0500 +Subject: [PATCH] ARM: Implement *context routines. + + * sysdeps/unix/sysv/linux/arm/eabi/getcontext.S: New file. + * sysdeps/unix/sysv/linux/arm/eabi/makecontext.c: New file. + * sysdeps/unix/sysv/linux/arm/eabi/setcontext.S: New file. + * sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S: New file. + * sysdeps/unix/sysv/linux/arm/ucontext_i.sym: New file. + * sysdeps/unix/sysv/linux/arm/Makefile (gen-as-const-headers): Add + ucontext_i.sym. +--- + sysdeps/unix/sysv/linux/arm/Makefile | 4 + + sysdeps/unix/sysv/linux/arm/eabi/getcontext.S | 113 ++++++++++++++++++++++++ + sysdeps/unix/sysv/linux/arm/eabi/makecontext.c | 73 +++++++++++++++ + sysdeps/unix/sysv/linux/arm/eabi/setcontext.S | 101 +++++++++++++++++++++ + sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S | 63 +++++++++++++ + sysdeps/unix/sysv/linux/arm/ucontext_i.sym | 30 +++++++ + 7 files changed, 394 insertions(+) + create mode 100644 sysdeps/unix/sysv/linux/arm/eabi/getcontext.S + create mode 100644 sysdeps/unix/sysv/linux/arm/eabi/makecontext.c + create mode 100644 sysdeps/unix/sysv/linux/arm/eabi/setcontext.S + create mode 100644 sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S + create mode 100644 sysdeps/unix/sysv/linux/arm/ucontext_i.sym + +diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile +index d91b968..a981736 100644 +--- a/sysdeps/unix/sysv/linux/arm/Makefile ++++ b/sysdeps/unix/sysv/linux/arm/Makefile +@@ -20,3 +20,7 @@ endif + ifeq ($(subdir),resource) + sysdep_routines += oldgetrlimit64 + endif ++ ++ifeq ($(subdir),stdlib) ++gen-as-const-headers += ucontext_i.sym ++endif +diff --git a/sysdeps/unix/sysv/linux/arm/eabi/getcontext.S b/sysdeps/unix/sysv/linux/arm/eabi/getcontext.S +new file mode 100644 +index 0000000..435eb12 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/eabi/getcontext.S +@@ -0,0 +1,113 @@ ++/* Copyright (C) 2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include "ucontext_i.h" ++ ++ .syntax unified ++ .text ++ ++/* int getcontext (ucontext_t *ucp) */ ++ ++ENTRY(__getcontext) ++ /* No need to save r0-r3, d0-d7, or d16-d31. */ ++ add r1, r0, #MCONTEXT_ARM_R4 ++ stmia r1, {r4-r11} ++ ++ /* Save R13 separately as Thumb can't STM it. */ ++ str r13, [r0, #MCONTEXT_ARM_SP] ++ str r14, [r0, #MCONTEXT_ARM_LR] ++ /* Return to LR */ ++ str r14, [r0, #MCONTEXT_ARM_PC] ++ /* Return zero */ ++ mov r2, #0 ++ str r2, [r0, #MCONTEXT_ARM_R0] ++ ++ /* Save ucontext_t * across the next call. */ ++ mov r4, r0 ++ ++ /* __sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */ ++ mov r0, #SIG_BLOCK ++ mov r1, #0 ++ add r2, r4, #UCONTEXT_SIGMASK ++ bl PLTJMP(__sigprocmask) ++ ++ /* Store FP regs. Much of the FP code is copied from arm/eabi/setjmp.S. */ ++ ++#ifdef PIC ++ ldr r2, 1f ++ ldr r1, Lrtld_global_ro ++0: add r2, pc, r2 ++ ldr r2, [r2, r1] ++ ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] ++#else ++ ldr r2, Lhwcap ++ ldr r2, [r2, #0] ++#endif ++ ++ add r0, r4, #UCONTEXT_REGSPACE ++ ++ tst r2, #HWCAP_ARM_VFP ++ beq Lno_vfp ++ ++ /* Store the VFP registers. ++ Don't use VFP instructions directly because this code ++ is used in non-VFP multilibs. */ ++ /* Following instruction is vstmia r0!, {d8-d15}. */ ++ stc p11, cr8, [r0], #64 ++ /* Store the floating-point status register. */ ++ /* Following instruction is vmrs r1, fpscr. */ ++ mrc p10, 7, r1, cr1, cr0, 0 ++ str r1, [r0], #4 ++Lno_vfp: ++ ++ tst r2, #HWCAP_ARM_IWMMXT ++ beq Lno_iwmmxt ++ ++ /* Save the call-preserved iWMMXt registers. */ ++ /* Following instructions are wstrd wr10, [r0], #8 (etc.) */ ++ stcl p1, cr10, [r0], #8 ++ stcl p1, cr11, [r0], #8 ++ stcl p1, cr12, [r0], #8 ++ stcl p1, cr13, [r0], #8 ++ stcl p1, cr14, [r0], #8 ++ stcl p1, cr15, [r0], #8 ++Lno_iwmmxt: ++ ++ /* Restore the clobbered R4 and LR. */ ++ ldr r14, [r4, #MCONTEXT_ARM_LR] ++ ldr r4, [r4, #MCONTEXT_ARM_R4] ++ ++ mov r0, #0 ++ ++ DO_RET(r14) ++ ++END(__getcontext) ++ ++#ifdef PIC ++1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 ++Lrtld_global_ro: ++ .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) ++#else ++Lhwcap: ++ .long C_SYMBOL_NAME(_dl_hwcap) ++#endif ++ ++ ++weak_alias(__getcontext, getcontext) +diff --git a/sysdeps/unix/sysv/linux/arm/eabi/makecontext.c b/sysdeps/unix/sysv/linux/arm/eabi/makecontext.c +new file mode 100644 +index 0000000..d6ae6f0 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/eabi/makecontext.c +@@ -0,0 +1,73 @@ ++/* Copyright (C) 2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++/* Number of arguments that go in registers. */ ++#define NREG_ARGS 4 ++ ++/* Take a context previously prepared via getcontext() and set to ++ call func() with the given int only args. */ ++void ++__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) ++{ ++ extern void __startcontext (void); ++ unsigned long *funcstack; ++ va_list vl; ++ unsigned long *regptr; ++ unsigned int reg; ++ int misaligned; ++ ++ /* Start at the top of stack. */ ++ funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); ++ ++ /* Ensure the stack stays eight byte aligned. */ ++ misaligned = ((unsigned long) funcstack & 4) != 0; ++ ++ if ((argc > NREG_ARGS) && (argc & 1) != 0) ++ misaligned = !misaligned; ++ ++ if (misaligned) ++ funcstack -= 1; ++ ++ va_start (vl, argc); ++ ++ /* Reserve space for the on-stack arguments. */ ++ if (argc > NREG_ARGS) ++ funcstack -= (argc - NREG_ARGS); ++ ++ ucp->uc_mcontext.arm_sp = (unsigned long) funcstack; ++ ucp->uc_mcontext.arm_pc = (unsigned long) func; ++ ++ /* Exit to startcontext() with the next context in R4 */ ++ ucp->uc_mcontext.arm_r4 = (unsigned long) ucp->uc_link; ++ ucp->uc_mcontext.arm_lr = (unsigned long) __startcontext; ++ ++ /* The first four arguments go into registers. */ ++ regptr = &(ucp->uc_mcontext.arm_r0); ++ ++ for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++) ++ *regptr++ = va_arg (vl, unsigned long); ++ ++ /* And the remainder on the stack. */ ++ for (; reg < argc; reg++) ++ *funcstack++ = va_arg (vl, unsigned long); ++ ++ va_end (vl); ++} ++weak_alias (__makecontext, makecontext) +diff --git a/sysdeps/unix/sysv/linux/arm/eabi/setcontext.S b/sysdeps/unix/sysv/linux/arm/eabi/setcontext.S +new file mode 100644 +index 0000000..78003f5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/eabi/setcontext.S +@@ -0,0 +1,101 @@ ++/* Copyright (C) 2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include "ucontext_i.h" ++ ++ .syntax unified ++ .text ++ ++/* int setcontext (const ucontext_t *ucp) */ ++ ++ENTRY(__setcontext) ++ mov r4, r0 ++ add r0, r0, #UCONTEXT_REGSPACE ++ ++ /* Restore the VFP registers. Copied from arm/eabi/__longjmp.S. */ ++#ifdef PIC ++ ldr r2, 1f ++ ldr r1, Lrtld_global_ro ++0: add r2, pc, r2 ++ ldr r2, [r2, r1] ++ ldr r2, [r2, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET] ++#else ++ ldr r2, Lhwcap ++ ldr r2, [r2, #0] ++#endif ++ ++ tst r2, #HWCAP_ARM_VFP ++ beq Lno_vfp_sc ++ ++ /* Following instruction is vldmia r0!, {d8-d15}. */ ++ ldc p11, cr8, [r0], #64 ++ /* Restore the floating-point status register. */ ++ ldr r1, [r0], #4 ++ /* Following instruction is fmxr fpscr, r1. */ ++ mcr p10, 7, r1, cr1, cr0, 0 ++Lno_vfp_sc: ++ tst r2, #HWCAP_ARM_IWMMXT ++ beq Lno_iwmmxt_sc ++ ++ /* Restore the call-preserved iWMMXt registers. */ ++ /* Following instructions are wldrd wr10, [r0], #8 (etc.) */ ++ ldcl p1, cr10, [r0], #8 ++ ldcl p1, cr11, [r0], #8 ++ ldcl p1, cr12, [r0], #8 ++ ldcl p1, cr13, [r0], #8 ++ ldcl p1, cr14, [r0], #8 ++ ldcl p1, cr15, [r0], #8 ++Lno_iwmmxt_sc: ++ ++ /* Now bring back the signal status. */ ++ mov r0, #SIG_SETMASK ++ add r1, r4, #UCONTEXT_SIGMASK ++ mov r2, #0 ++ bl PLTJMP(__sigprocmask) ++ ++ /* Loading r0-r3 makes makecontext easier. */ ++ add r14, r4, #MCONTEXT_ARM_R0 ++ ldmia r14, {r0-r12} ++ ldr r13, [r14, #(MCONTEXT_ARM_SP - MCONTEXT_ARM_R0)] ++ add r14, r14, #(MCONTEXT_ARM_LR - MCONTEXT_ARM_R0) ++ ldmia r14, {r14, pc} ++ ++END(setcontext) ++weak_alias(__setcontext, setcontext) ++ ++ /* Called when a makecontext() context returns. Start the ++ context in R4 or fall through to exit(). */ ++ENTRY(__startcontext) ++ movs r0, r4 ++ bne PLTJMP(__setcontext) ++ ++ @ New context was 0 - exit ++ b PLTJMP(_exit) ++END(__startcontext) ++ ++#ifdef PIC ++1: .long _GLOBAL_OFFSET_TABLE_ - 0b - 8 ++Lrtld_global_ro: ++ .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) ++#else ++Lhwcap: ++ .long C_SYMBOL_NAME(_dl_hwcap) ++#endif ++ +diff --git a/sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S b/sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S +new file mode 100644 +index 0000000..09492d0 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/eabi/swapcontext.S +@@ -0,0 +1,63 @@ ++/* Copyright (C) 2012 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#include "ucontext_i.h" ++ ++ .syntax unified ++ .text ++ ++/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ ++ ++ENTRY(swapcontext) ++ ++ /* Have getcontext() do most of the work then fix up ++ LR afterwards. Save R3 to keep the stack aligned. */ ++ push {r0,r1,r3,r14} ++ cfi_adjust_cfa_offset (16) ++ cfi_rel_offset (r0,0) ++ cfi_rel_offset (r1,4) ++ cfi_rel_offset (r3,8) ++ cfi_rel_offset (r14,12) ++ ++ bl __getcontext ++ mov r4, r0 ++ ++ pop {r0,r1,r3,r14} ++ cfi_adjust_cfa_offset (-16) ++ cfi_restore (r0) ++ cfi_restore (r1) ++ cfi_restore (r3) ++ cfi_restore (r14) ++ ++ /* Exit if getcontext() failed. */ ++ cmp r4, #0 ++ itt ne ++ movne r0, r4 ++ RETINSTR(ne, r14) ++ ++ /* Fix up LR and the PC. */ ++ str r13,[r0, #MCONTEXT_ARM_SP] ++ str r14,[r0, #MCONTEXT_ARM_LR] ++ str r14,[r0, #MCONTEXT_ARM_PC] ++ ++ /* And swap using swapcontext(). */ ++ mov r0, r1 ++ b __setcontext ++ ++END(swapcontext) +diff --git a/sysdeps/unix/sysv/linux/arm/ucontext_i.sym b/sysdeps/unix/sysv/linux/arm/ucontext_i.sym +new file mode 100644 +index 0000000..306292f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/ucontext_i.sym +@@ -0,0 +1,30 @@ ++#include ++#include ++#include ++#include ++ ++SIG_BLOCK ++SIG_SETMASK ++ ++-- Offsets of the fields in the ucontext_t structure. ++#define ucontext(member) offsetof (ucontext_t, member) ++#define mcontext(member) ucontext (uc_mcontext.member) ++ ++UCONTEXT_FLAGS ucontext (uc_flags) ++UCONTEXT_LINK ucontext (uc_link) ++UCONTEXT_STACK ucontext (uc_stack) ++UCONTEXT_MCONTEXT ucontext (uc_mcontext) ++UCONTEXT_SIGMASK ucontext (uc_sigmask) ++ ++UCONTEXT_REGSPACE ucontext (uc_regspace) ++ ++MCONTEXT_TRAP_NO mcontext (trap_no) ++MCONTEXT_ERROR_CODE mcontext (error_code) ++MCONTEXT_OLDMASK mcontext (oldmask) ++MCONTEXT_ARM_R0 mcontext (arm_r0) ++MCONTEXT_ARM_R4 mcontext (arm_r4) ++MCONTEXT_ARM_SP mcontext (arm_sp) ++MCONTEXT_ARM_LR mcontext (arm_lr) ++MCONTEXT_ARM_PC mcontext (arm_pc) ++MCONTEXT_ARM_CPSR mcontext (arm_cpsr) ++MCONTEXT_FAULT_ADDRESS mcontext (fault_address) +-- +1.7.10 + diff --git a/glibc.spec b/glibc.spec index fe9cf75..c5c2bfe 100644 --- a/glibc.spec +++ b/glibc.spec @@ -112,6 +112,7 @@ Patch1042: %{name}-rh801650-1.patch Patch1043: %{name}-rh801650-2.patch Patch1046: %{name}-rh806403.patch Patch1048: %{name}-rh804792.patch +Patch1049: %{name}-ports-arm-implement-context-routines.patch # # Patches submitted, but not yet approved upstream. @@ -455,6 +456,10 @@ rm -rf %{glibcportsdir} %patch2051 -p1 %patch2052 -p1 +pushd ../%{glibcportsdir} +%patch1049 -p1 +popd + # A lot of programs still misuse memcpy when they have to use # memmove. The memcpy implementation below is not tolerant at # all. -- 1.7.10