mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-28 22:03:42 +01:00
e2962af9d3
Since the fast unwinding code path doesn't need the full context, a faster target dependent getcontext is implemented. Signed-off-by: Lassi Tuura <lat@cern.ch>
134 lines
4.3 KiB
ArmAsm
134 lines
4.3 KiB
ArmAsm
/* libunwind - a platform-independent unwind library
|
|
Copyright (C) 2008 Google, Inc
|
|
Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
|
|
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
|
|
|
|
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:
|
|
.cfi_startproc
|
|
|
|
/* 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)
|
|
|
|
#if defined __linux__
|
|
/* 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)
|
|
#elif defined __FreeBSD__
|
|
fxsave UC_MCONTEXT_FPSTATE(%rdi)
|
|
movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
|
|
movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi)
|
|
/* Save rflags and segment registers, so that sigreturn(2)
|
|
does not complain. */
|
|
pushfq
|
|
.cfi_adjust_cfa_offset 8
|
|
popq UC_MCONTEXT_RFLAGS(%rdi)
|
|
.cfi_adjust_cfa_offset -8
|
|
movl $0, UC_MCONTEXT_FLAGS(%rdi)
|
|
movw %cs, UC_MCONTEXT_CS(%rdi)
|
|
movw %ss, UC_MCONTEXT_SS(%rdi)
|
|
#if 0
|
|
/* Setting the flags to 0 above disables restore of segment
|
|
registers from the context */
|
|
movw %ds, UC_MCONTEXT_DS(%rdi)
|
|
movw %es, UC_MCONTEXT_ES(%rdi)
|
|
movw %fs, UC_MCONTEXT_FS(%rdi)
|
|
movw %gs, UC_MCONTEXT_GS(%rdi)
|
|
#endif
|
|
movq $UC_MCONTEXT_MC_LEN_VAL, UC_MCONTEXT_MC_LEN(%rdi)
|
|
#else
|
|
#error Port me
|
|
#endif
|
|
|
|
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
|
|
.cfi_endproc
|
|
.size _Ux86_64_getcontext, . - _Ux86_64_getcontext
|
|
|
|
/* int _Ux86_64_getcontext_trace (ucontext_t *ucp)
|
|
|
|
Saves limited machine context in UCP necessary for libunwind.
|
|
Unlike _Ux86_64_getcontext, saves only the parts needed for
|
|
fast trace. If fast trace fails, caller will have to get the
|
|
full context.
|
|
*/
|
|
|
|
.global _Ux86_64_getcontext_trace
|
|
.hidden _Ux86_64_getcontext_trace
|
|
.type _Ux86_64_getcontext_trace, @function
|
|
_Ux86_64_getcontext_trace:
|
|
.cfi_startproc
|
|
|
|
/* Save only RBP, RBX, RSP, RIP - exclude this call. */
|
|
movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi)
|
|
movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
|
|
|
|
leaq 8(%rsp), %rax
|
|
movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
|
|
|
|
movq 0(%rsp), %rax
|
|
movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi)
|
|
|
|
xorq %rax, %rax
|
|
retq
|
|
.cfi_endproc
|
|
.size _Ux86_64_getcontext_trace, . - _Ux86_64_getcontext_trace
|
|
|
|
/* We do not need executable stack. */
|
|
.section .note.GNU-stack,"",@progbits
|