summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorArun Sharma <aruns@google.com>2007-04-05 20:40:41 -0600
committerDavid Mosberger-Tang <davidm@koala.mostang.com>2007-04-05 20:40:41 -0600
commit31440e9796bb34146372df52ed59c4f68ea5839d (patch)
treeeef2132189043bd559289b5fae2c6cf397982743 /src
parent55fe524775b47f16589e3fc8f28ccffe5e88a048 (diff)
downloadlibunwind-31440e9796bb34146372df52ed59c4f68ea5839d.tar.gz
Make libunwind pass C++ exceptions correctly
When libunwind is linked with a C++ program that throws exceptions, the exception that's thrown is passed in %rax. However, libc's setcontext clears %rax, causing problems. This patch implements a setcontext that doesn't clobber rax. TBD: Add dwarf CFI annotations Signed-off-by: Arun Sharma <arun.sharma@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/x86_64/Gresume.c2
-rw-r--r--src/x86_64/gen-offsets.c73
-rw-r--r--src/x86_64/setcontext.S79
3 files changed, 151 insertions, 3 deletions
diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c
index 2fc51aab..4edc4da6 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);
- setcontext (uc);
+ _x86_64_setcontext (uc);
}
#else
# warning Implement me!
diff --git a/src/x86_64/gen-offsets.c b/src/x86_64/gen-offsets.c
new file mode 100644
index 00000000..343716db
--- /dev/null
+++ b/src/x86_64/gen-offsets.c
@@ -0,0 +1,73 @@
+#include <ucontext.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#define REG_OFFSET(reg) (offsetof(struct ucontext, uc_mcontext.gregs[REG_##reg]))
+
+# define REG_R8 0
+# define REG_R9 1
+# define REG_R10 2
+# define REG_R11 3
+# define REG_R12 4
+# define REG_R13 5
+# define REG_R14 6
+# define REG_R15 7
+# define REG_RDI 8
+# define REG_RSI 9
+# define REG_RBP 10
+# define REG_RBX 11
+# define REG_RDX 12
+# define REG_RAX 13
+# define REG_RCX 14
+# define REG_RSP 15
+# define REG_RIP 16
+
+char *regs[] = { "RAX",
+ "RBX",
+ "RCX",
+ "RDX",
+ "RDI",
+ "RSI",
+ "RSP",
+ "RBP",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "RIP",
+ };
+
+main()
+{
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[0], REG_OFFSET(RAX));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[1], REG_OFFSET(RBX));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[2], REG_OFFSET(RCX));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[3], REG_OFFSET(RDX));
+
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[4], REG_OFFSET(RDI));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[5], REG_OFFSET(RSI));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[6], REG_OFFSET(RSP));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[7], REG_OFFSET(RBP));
+
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[8], REG_OFFSET(R8));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[9], REG_OFFSET(R9));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[10], REG_OFFSET(R10));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[11], REG_OFFSET(R11));
+
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[12], REG_OFFSET(R12));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[13], REG_OFFSET(R13));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[14], REG_OFFSET(R14));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[15], REG_OFFSET(R15));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[15], REG_OFFSET(R15));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[15], REG_OFFSET(R15));
+ printf("#define REG_OFFSET_%s\t%d\n" , regs[16], REG_OFFSET(RIP));
+
+ printf("#define REG_OFFSET_FPREGS_PTR\t%d\n" , offsetof(struct ucontext, uc_mcontext.fpregs));
+ printf("#define FPREG_OFFSET_MXCR\t%d\n" , offsetof(struct _libc_fpstate, mxcsr));
+}
+
+
diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S
index d164d8db..d1578e1d 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -1,4 +1,79 @@
- .global _UI_setcontext
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2007 Google, Inc
+ Contributed by Arun Sharma <arun.sharma@google.com>
-_UI_setcontext:
+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. */
+
+#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
+
+ .global _x86_64_setcontext
+
+_x86_64_setcontext:
+
+ /* restore fp state */
+ mov REG_OFFSET_FPREGS_PTR(%rdi),%r8
+ fldenv (%r8)
+ ldmxcsr FPREG_OFFSET_MXCR(%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
+
+ /* push the return address on the stack */
+ mov REG_OFFSET_RIP(%rdi),%rcx
+ push %rcx
+
+ mov REG_OFFSET_RCX(%rdi),%rcx
+ mov REG_OFFSET_RDI(%rdi),%rdi
retq
+