From ae7eebb839491b9d313923e38414b83c1fddcbf4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 13 Apr 2010 14:11:39 +0300 Subject: [PATCH] Separate getcontext implementation for x86 --- src/Makefile.am | 6 +- .../{getcontext.S => getcontext-freebsd.S} | 42 +---------- src/x86/getcontext-linux.S | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 43 deletions(-) rename src/x86/{getcontext.S => getcontext-freebsd.S} (67%) create mode 100644 src/x86/getcontext-linux.S diff --git a/src/Makefile.am b/src/Makefile.am index 1c94e161..be547710 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -230,7 +230,7 @@ libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ x86/Lget_proc_info.c x86/Lregs.c \ - x86/Lresume.c x86/Lstep.c x86/getcontext.S + x86/Lresume.c x86/Lstep.c # The list of files that go into libunwind-x86: libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ @@ -351,6 +351,7 @@ if OS_LINUX libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) libunwind_la_SOURCES_x86_os = x86/Gos-linux.c + libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c @@ -365,6 +366,7 @@ if OS_FREEBSD libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd) libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local) libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c + libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c @@ -424,7 +426,7 @@ endif else if ARCH_X86 lib_LTLIBRARIES_arch = libunwind-x86.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) + libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os) libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86) libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) if !REMOTE_ONLY diff --git a/src/x86/getcontext.S b/src/x86/getcontext-freebsd.S similarity index 67% rename from src/x86/getcontext.S rename to src/x86/getcontext-freebsd.S index f97fff45..42478d29 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext-freebsd.S @@ -1,6 +1,4 @@ /* libunwind - a platform-independent unwind library - Copyright (C) 2009 Google, Inc - Contributed by Paul Pluzhnikov Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. @@ -26,46 +24,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "offsets.h" -/* int _Ux86_getcontext (ucontext_t *ucp) - - Saves the machine context in UCP necessary for libunwind. - Unlike the libc implementation, we don't save the signal mask - and hence avoid the cost of a system call per unwind. - -*/ - .global _Ux86_getcontext .type _Ux86_getcontext, @function _Ux86_getcontext: -#if defined __linux__ - mov 4(%esp),%eax /* ucontext_t* */ - - /* EAX is not preserved. */ - movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) - - movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) - movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) - movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) - movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) - movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) - - movl (%esp), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) - - leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) - - /* glibc getcontext saves FS, but not GS */ - xorl %ecx, %ecx - movw %fs, %cx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) - - leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) - fnstenv (%ecx) - fldenv (%ecx) -#elif defined __FreeBSD__ pushl %eax mov 8(%esp),%eax /* ucontext_t* */ popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) @@ -110,9 +71,8 @@ _Ux86_getcontext: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) -#endif - xor %eax, %eax + xorl %eax, %eax ret .size _Ux86_getcontext, . - _Ux86_getcontext diff --git a/src/x86/getcontext-linux.S b/src/x86/getcontext-linux.S new file mode 100644 index 00000000..a0714cd1 --- /dev/null +++ b/src/x86/getcontext-linux.S @@ -0,0 +1,72 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2009 Google, Inc + Contributed by Paul Pluzhnikov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + +/* int _Ux86_getcontext (ucontext_t *ucp) + + Saves the machine context in UCP necessary for libunwind. + Unlike the libc implementation, we don't save the signal mask + and hence avoid the cost of a system call per unwind. + +*/ + + .global _Ux86_getcontext + .type _Ux86_getcontext, @function +_Ux86_getcontext: + mov 4(%esp),%eax /* ucontext_t* */ + + /* EAX is not preserved. */ + movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) + + movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) + movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) + movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) + movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) + movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) + + movl (%esp), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) + + /* glibc getcontext saves FS, but not GS */ + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) + + leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) + fnstenv (%ecx) + fldenv (%ecx) + + xor %eax, %eax + ret + .size _Ux86_getcontext, . - _Ux86_getcontext + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits