summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Sharma <arun.sharma@google.com>2008-06-16 14:42:16 -0600
committerDavid Mosberger-Tang <davidm@koala.mostang.com>2008-06-16 14:42:16 -0600
commitef29eade44fc2aa7e49811a8bd76e941b369b914 (patch)
treee880ab82577d1edcd5eb404ff4a4806cc74460d0
parent649f1fb3449a65dd0626a709432d8b02a7c56bbc (diff)
downloadlibunwind-ef29eade44fc2aa7e49811a8bd76e941b369b914.tar.gz
This patch eliminates one system call per unwind by not using the
getcontext in libc. Also cleanup the namespace (check-name-space passes on x86_64 now). Replace uses of offsets.h with ucontext_i.h. Rename _x86_64_setcontext to _Ux86_64_setcontext. TBD: Add CFI annotations for get/setcontext. Signed-off-by: Paul Pluzhnikov <ppluzhnikov@google.com> Signed-off-by: Arun Sharma <arun.sharma@google.com>
-rw-r--r--include/libunwind-x86_64.h12
-rw-r--r--src/Makefile.am4
-rw-r--r--src/x86_64/Gresume.c2
-rw-r--r--src/x86_64/getcontext.S77
-rw-r--r--src/x86_64/offsets.h29
-rw-r--r--src/x86_64/setcontext.S49
-rw-r--r--src/x86_64/ucontext_i.h3
-rw-r--r--tests/check-namespace.sh.in1
8 files changed, 116 insertions, 61 deletions
diff --git a/include/libunwind-x86_64.h b/include/libunwind-x86_64.h
index a87b57ec..e3373516 100644
--- a/include/libunwind-x86_64.h
+++ b/include/libunwind-x86_64.h
@@ -97,22 +97,18 @@ unw_tdep_save_loc_t;
/* On x86_64, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
-/* XXX this is not ideal: an application should not be prevented from
- using the "getcontext" name just because it's using libunwind. We
- can't just use __getcontext() either, because that isn't exported
- by glibc... */
-#define unw_tdep_getcontext(uc) (getcontext (uc), 0)
-
-#include "libunwind-dynamic.h"
-
typedef struct
{
/* no x86-64-specific auxiliary proc-info */
}
unw_tdep_proc_info_t;
+#include "libunwind-dynamic.h"
#include "libunwind-common.h"
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+extern int unw_tdep_getcontext (unw_tdep_context_t *);
+
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
extern int unw_tdep_is_fpreg (int);
diff --git a/src/Makefile.am b/src/Makefile.am
index 7de30269..e1fa3cdb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -254,7 +254,7 @@ libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \
$(dwarf_SOURCES_common) \
elf64.c elf64.h \
x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h \
- x86_64/is_fpreg.c x86_64/regname.c x86_64/offsets.h
+ x86_64/is_fpreg.c x86_64/regname.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
@@ -265,7 +265,7 @@ libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \
x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \
x86_64/Lis_signal_frame.c x86_64/Lget_proc_info.c x86_64/Lregs.c \
- x86_64/Lresume.c x86_64/Lstep.c
+ x86_64/Lresume.c x86_64/Lstep.c x86_64/getcontext.S
# The list of files that go into libunwind-x86_64:
libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \
diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c
index b4000401..0a734417 100644
--- a/src/x86_64/Gresume.c
+++ b/src/x86_64/Gresume.c
@@ -71,7 +71,7 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
Debug (8, "resuming at ip=%llx via setcontext()\n",
(unsigned long long) c->dwarf.ip);
- _x86_64_setcontext (uc);
+ _Ux86_64_setcontext (uc);
}
#else
# warning Implement me!
diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S
new file mode 100644
index 00000000..48a52d05
--- /dev/null
+++ b/src/x86_64/getcontext.S
@@ -0,0 +1,77 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+
+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 "ucontext_i.h"
+
+/* int _Ux86_64_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_64_getcontext
+ .type _Ux86_64_getcontext, @function
+_Ux86_64_getcontext:
+
+ /* Callee saved: RBX, RBP, R12-R15 */
+ movq %r12, UC_MCONTEXT_GREGS_R12(%rdi)
+ movq %r13, UC_MCONTEXT_GREGS_R13(%rdi)
+ movq %r14, UC_MCONTEXT_GREGS_R14(%rdi)
+ movq %r15, UC_MCONTEXT_GREGS_R15(%rdi)
+ movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi)
+ movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
+
+ /* Save argument registers (not strictly needed, but setcontext
+ restores them, so don't restore garbage). */
+ movq %r8, UC_MCONTEXT_GREGS_R8(%rdi)
+ movq %r9, UC_MCONTEXT_GREGS_R9(%rdi)
+ movq %rdi, UC_MCONTEXT_GREGS_RDI(%rdi)
+ movq %rsi, UC_MCONTEXT_GREGS_RSI(%rdi)
+ movq %rdx, UC_MCONTEXT_GREGS_RDX(%rdi)
+ movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi)
+ movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi)
+
+ /* Save fp state (not needed, except for setcontext not
+ restoring garbage). */
+ leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8
+ movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi)
+ fnstenv (%r8)
+ stmxcsr FPREGS_OFFSET_MXCSR(%r8)
+
+ leaq 8(%rsp), %rax /* exclude this call. */
+ movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
+
+ movq 0(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi)
+
+ xorq %rax, %rax
+ retq
+
+#ifdef __linux__
+ /* We do not need executable stack. */
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/src/x86_64/offsets.h b/src/x86_64/offsets.h
deleted file mode 100644
index 56ead697..00000000
--- a/src/x86_64/offsets.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This used to be a generated file. But then it breaks cross compilation.
- * So use the method used by other architectures.
- */
-#ifndef OFFSETS_H
-#define OFFSETS_H
-
-#define REG_OFFSET_RAX 144
-#define REG_OFFSET_RBX 128
-#define REG_OFFSET_RCX 152
-#define REG_OFFSET_RDX 136
-#define REG_OFFSET_RDI 104
-#define REG_OFFSET_RSI 112
-#define REG_OFFSET_RSP 160
-#define REG_OFFSET_RBP 120
-#define REG_OFFSET_R8 40
-#define REG_OFFSET_R9 48
-#define REG_OFFSET_R10 56
-#define REG_OFFSET_R11 64
-#define REG_OFFSET_R12 72
-#define REG_OFFSET_R13 80
-#define REG_OFFSET_R14 88
-#define REG_OFFSET_R15 96
-#define REG_OFFSET_R15 96
-#define REG_OFFSET_R15 96
-#define REG_OFFSET_RIP 168
-#define REG_OFFSET_FPREGS_PTR 224
-#define FPREG_OFFSET_MXCR 24
-
-#endif /* OFFSETS_H */
diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S
index 9eeb1b84..6b06a7bb 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -23,38 +23,45 @@ 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"
+#include "ucontext_i.h"
- .global _x86_64_setcontext
-_x86_64_setcontext:
+/* int _Ux86_64_setcontext (const ucontext_t *ucp)
+
+ Restores the machine context provided.
+ Unlike the libc implementation, doesn't clobber %rax
+
+*/
+ .global _Ux86_64_setcontext
+
+_Ux86_64_setcontext:
/* restore fp state */
- mov REG_OFFSET_FPREGS_PTR(%rdi),%r8
+ mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
fldenv (%r8)
- ldmxcsr FPREG_OFFSET_MXCR(%r8)
+ ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
/* restore the rest of the state */
- mov REG_OFFSET_R8(%rdi),%r8
- mov REG_OFFSET_R9(%rdi),%r9
- mov REG_OFFSET_RBX(%rdi),%rbx
- mov REG_OFFSET_RBP(%rdi),%rbp
- mov REG_OFFSET_R12(%rdi),%r12
- mov REG_OFFSET_R13(%rdi),%r13
- mov REG_OFFSET_R14(%rdi),%r14
- mov REG_OFFSET_R15(%rdi),%r15
- mov REG_OFFSET_RSI(%rdi),%rsi
- mov REG_OFFSET_RDX(%rdi),%rdx
- mov REG_OFFSET_RAX(%rdi),%rax
- mov REG_OFFSET_RCX(%rdi),%rcx
- mov REG_OFFSET_RSP(%rdi),%rsp
+ mov UC_MCONTEXT_GREGS_R8(%rdi),%r8
+ mov UC_MCONTEXT_GREGS_R9(%rdi),%r9
+ mov UC_MCONTEXT_GREGS_RBX(%rdi),%rbx
+ mov UC_MCONTEXT_GREGS_RBP(%rdi),%rbp
+ mov UC_MCONTEXT_GREGS_R12(%rdi),%r12
+ mov UC_MCONTEXT_GREGS_R13(%rdi),%r13
+ mov UC_MCONTEXT_GREGS_R14(%rdi),%r14
+ mov UC_MCONTEXT_GREGS_R15(%rdi),%r15
+ mov UC_MCONTEXT_GREGS_RSI(%rdi),%rsi
+ mov UC_MCONTEXT_GREGS_RDX(%rdi),%rdx
+ mov UC_MCONTEXT_GREGS_RAX(%rdi),%rax
+ mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
+ mov UC_MCONTEXT_GREGS_RSP(%rdi),%rsp
/* push the return address on the stack */
- mov REG_OFFSET_RIP(%rdi),%rcx
+ mov UC_MCONTEXT_GREGS_RIP(%rdi),%rcx
push %rcx
- mov REG_OFFSET_RCX(%rdi),%rcx
- mov REG_OFFSET_RDI(%rdi),%rdi
+ mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx
+ mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi
retq
#ifdef __linux__
diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h
index dfd93bc1..459c56a2 100644
--- a/src/x86_64/ucontext_i.h
+++ b/src/x86_64/ucontext_i.h
@@ -39,3 +39,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define UC_MCONTEXT_GREGS_RCX 0x98
#define UC_MCONTEXT_GREGS_RSP 0xa0
#define UC_MCONTEXT_GREGS_RIP 0xa8
+#define UC_MCONTEXT_FPREGS_PTR 0x1a8
+#define UC_MCONTEXT_FPREGS_MEM 0xe0
+#define FPREGS_OFFSET_MXCSR 0x18
diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in
index d6f51223..b7285b1d 100644
--- a/tests/check-namespace.sh.in
+++ b/tests/check-namespace.sh.in
@@ -121,6 +121,7 @@ check_local_unw_abi () {
match _U${plat}_get_elf_image
match _U${plat}_is_fpreg
match _UL${plat}_dwarf_search_unwind_table
+ match _U${plat}_setcontext
;;
*)
match _U${plat}_is_fpreg