18e53e62db913470952b8eb541834b876f7a6882cArun Sharma/* libunwind - a platform-independent unwind library 28e53e62db913470952b8eb541834b876f7a6882cArun Sharma Copyright (C) 2002-2003 Hewlett-Packard Co 38e53e62db913470952b8eb541834b876f7a6882cArun Sharma Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 48e53e62db913470952b8eb541834b876f7a6882cArun Sharma 58e53e62db913470952b8eb541834b876f7a6882cArun Sharma Modified for x86_64 by Max Asbock <masbock@us.ibm.com> 68e53e62db913470952b8eb541834b876f7a6882cArun Sharma 78e53e62db913470952b8eb541834b876f7a6882cArun SharmaThis file is part of libunwind. 88e53e62db913470952b8eb541834b876f7a6882cArun Sharma 98e53e62db913470952b8eb541834b876f7a6882cArun SharmaPermission is hereby granted, free of charge, to any person obtaining 108e53e62db913470952b8eb541834b876f7a6882cArun Sharmaa copy of this software and associated documentation files (the 118e53e62db913470952b8eb541834b876f7a6882cArun Sharma"Software"), to deal in the Software without restriction, including 128e53e62db913470952b8eb541834b876f7a6882cArun Sharmawithout limitation the rights to use, copy, modify, merge, publish, 138e53e62db913470952b8eb541834b876f7a6882cArun Sharmadistribute, sublicense, and/or sell copies of the Software, and to 148e53e62db913470952b8eb541834b876f7a6882cArun Sharmapermit persons to whom the Software is furnished to do so, subject to 158e53e62db913470952b8eb541834b876f7a6882cArun Sharmathe following conditions: 168e53e62db913470952b8eb541834b876f7a6882cArun Sharma 178e53e62db913470952b8eb541834b876f7a6882cArun SharmaThe above copyright notice and this permission notice shall be 188e53e62db913470952b8eb541834b876f7a6882cArun Sharmaincluded in all copies or substantial portions of the Software. 198e53e62db913470952b8eb541834b876f7a6882cArun Sharma 208e53e62db913470952b8eb541834b876f7a6882cArun SharmaTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 218e53e62db913470952b8eb541834b876f7a6882cArun SharmaEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 228e53e62db913470952b8eb541834b876f7a6882cArun SharmaMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 238e53e62db913470952b8eb541834b876f7a6882cArun SharmaNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 248e53e62db913470952b8eb541834b876f7a6882cArun SharmaLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 258e53e62db913470952b8eb541834b876f7a6882cArun SharmaOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 268e53e62db913470952b8eb541834b876f7a6882cArun SharmaWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 278e53e62db913470952b8eb541834b876f7a6882cArun Sharma 288e53e62db913470952b8eb541834b876f7a6882cArun Sharma#include "unwind_i.h" 298e53e62db913470952b8eb541834b876f7a6882cArun Sharma#include "ucontext_i.h" 308e53e62db913470952b8eb541834b876f7a6882cArun Sharma 31979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov#include <sys/syscall.h> 32979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov 33dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi TuuraHIDDEN void 34dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuuratdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info) 35dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura{ 36dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura struct cursor *c = (struct cursor *) dw; 37dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura assert(! need_unwind_info || dw->pi_valid); 38dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura assert(! need_unwind_info || dw->pi.unwind_info); 39dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura if (dw->pi_valid 40dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura && dw->pi.unwind_info 41dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame) 42dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; 43dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura else 44dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_format = X86_64_SCF_NONE; 45dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 469e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura Debug(5, "fetch frame ip=0x%lx cfa=0x%lx format=%d\n", 479e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura dw->ip, dw->cfa, c->sigcontext_format); 48dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura} 49dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 50dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi TuuraHIDDEN void 51dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuuratdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs) 52dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura{ 53dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura struct cursor *c = (struct cursor *) dw; 54dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura rs->signal_frame = c->sigcontext_format; 55dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 569e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n", 579e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura dw->ip, dw->cfa, c->sigcontext_format); 58dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura} 59dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 60dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi TuuraHIDDEN void 61dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuuratdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs) 62dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura{ 63dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura struct cursor *c = (struct cursor *) dw; 64dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_format = rs->signal_frame; 65dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME) 669e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura { 679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN; 681010880548589685a27b8f63ef54a3ea78e052fcArun Sharma /* Offset from cfa to ucontext_t in signal frame. */ 691010880548589685a27b8f63ef54a3ea78e052fcArun Sharma c->frame_info.cfa_reg_offset = 0; 70dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_addr = dw->cfa; 719e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura } 72dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura else 73dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_addr = 0; 74dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 759e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n", 769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr, 779e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME 789e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura ? c->frame_info.cfa_reg_offset : 0)); 79dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura} 80dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 818e53e62db913470952b8eb541834b876f7a6882cArun SharmaPROTECTED int 828e53e62db913470952b8eb541834b876f7a6882cArun Sharmaunw_is_signal_frame (unw_cursor_t *cursor) 838e53e62db913470952b8eb541834b876f7a6882cArun Sharma{ 848e53e62db913470952b8eb541834b876f7a6882cArun Sharma struct cursor *c = (struct cursor *) cursor; 85dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura return c->sigcontext_format != X86_64_SCF_NONE; 868e53e62db913470952b8eb541834b876f7a6882cArun Sharma} 878e53e62db913470952b8eb541834b876f7a6882cArun Sharma 888e53e62db913470952b8eb541834b876f7a6882cArun SharmaPROTECTED int 898e53e62db913470952b8eb541834b876f7a6882cArun Sharmaunw_handle_signal_frame (unw_cursor_t *cursor) 908e53e62db913470952b8eb541834b876f7a6882cArun Sharma{ 91fdc534ccb05d1e6c0438345d292203343a811701Arun Sharma#if UNW_DEBUG /* To silence compiler warnings */ 92dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /* Should not get here because we now use kernel-provided dwarf 93dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura information for the signal trampoline and dwarf_step() works. 949e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura Hence unw_step() should never call this function. Maybe 95dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura restore old non-dwarf signal handling here, but then the 96dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura gating on unw_is_signal_frame() needs to be removed. */ 97aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma struct cursor *c = (struct cursor *) cursor; 98dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", 99dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); 100fdc534ccb05d1e6c0438345d292203343a811701Arun Sharma#endif 1019e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura return -UNW_EBADFRAME; 1028e53e62db913470952b8eb541834b876f7a6882cArun Sharma} 1030dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov 1040dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#ifndef UNW_REMOTE_ONLY 105caa6095aec43541bdbca1ad58d6f65b3de53a1efArun SharmaHIDDEN void * 1060dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousovx86_64_r_uc_addr (ucontext_t *uc, int reg) 1070dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov{ 108ae5c1f2adf4da04235d87d024d4d942c01b2b447Lassi Tuura /* NOTE: common_init() in init.h inlines these for fast path access. */ 1090dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov void *addr; 1100dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov 1110dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov switch (reg) 1120dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov { 1130dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; 1140dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; 1150dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; 1160dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break; 1170dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break; 1180dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break; 1190dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break; 1200dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break; 1210dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break; 1220dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break; 1230dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break; 1240dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break; 1250dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break; 1260dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break; 1270dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; 1280dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; 1290dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; 1300dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov 1310dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov default: 1320dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov addr = NULL; 1330dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov } 1340dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov return addr; 1350dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov} 136979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov 137979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov/* sigreturn() is a no-op on x86_64 glibc. */ 138979af4502fe19b0d98459633731d004a4a010a0eKonstantin BelousovHIDDEN NORETURN void 139979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousovx86_64_sigreturn (unw_cursor_t *cursor) 140979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov{ 141979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov struct cursor *c = (struct cursor *) cursor; 142979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; 143979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov 144979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", 145979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov (unsigned long long) c->dwarf.ip, sc); 146979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov __asm__ __volatile__ ("mov %0, %%rsp;" 147979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov "mov %1, %%rax;" 148979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov "syscall" 149979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov :: "r"(sc), "i"(SYS_rt_sigreturn) 150979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov : "memory"); 1511d9c5a356d72993d8e9f5ac70811a723ea156403Arun Sharma abort(); 152979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov} 153979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov 1540dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#endif 155