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>
diff --git a/include/libunwind-x86_64.h b/include/libunwind-x86_64.h
index a87b57e..e337351 100644
--- a/include/libunwind-x86_64.h
+++ b/include/libunwind-x86_64.h
@@ -97,22 +97,18 @@
 /* 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 7de3026..e1fa3cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -254,7 +254,7 @@
 	$(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 @@
 	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 b400040..0a73441 100644
--- a/src/x86_64/Gresume.c
+++ b/src/x86_64/Gresume.c
@@ -71,7 +71,7 @@
     {
       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 0000000..48a52d0
--- /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 56ead69..0000000
--- 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 9eeb1b8..6b06a7b 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -23,38 +23,45 @@
 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 dfd93bc..459c56a 100644
--- a/src/x86_64/ucontext_i.h
+++ b/src/x86_64/ucontext_i.h
@@ -39,3 +39,6 @@
 #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 d6f5122..b7285b1 100644
--- a/tests/check-namespace.sh.in
+++ b/tests/check-namespace.sh.in
@@ -121,6 +121,7 @@
 	    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