1d4e76214Sopenharmony_ci/* libunwind - a platform-independent unwind library 2d4e76214Sopenharmony_ci Copyright (C) 2008 CodeSourcery 3d4e76214Sopenharmony_ci Copyright 2011 Linaro Limited 4d4e76214Sopenharmony_ci Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com> 5d4e76214Sopenharmony_ci 6d4e76214Sopenharmony_ciThis file is part of libunwind. 7d4e76214Sopenharmony_ci 8d4e76214Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining 9d4e76214Sopenharmony_cia copy of this software and associated documentation files (the 10d4e76214Sopenharmony_ci"Software"), to deal in the Software without restriction, including 11d4e76214Sopenharmony_ciwithout limitation the rights to use, copy, modify, merge, publish, 12d4e76214Sopenharmony_cidistribute, sublicense, and/or sell copies of the Software, and to 13d4e76214Sopenharmony_cipermit persons to whom the Software is furnished to do so, subject to 14d4e76214Sopenharmony_cithe following conditions: 15d4e76214Sopenharmony_ci 16d4e76214Sopenharmony_ciThe above copyright notice and this permission notice shall be 17d4e76214Sopenharmony_ciincluded in all copies or substantial portions of the Software. 18d4e76214Sopenharmony_ci 19d4e76214Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20d4e76214Sopenharmony_ciEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21d4e76214Sopenharmony_ciMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22d4e76214Sopenharmony_ciNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23d4e76214Sopenharmony_ciLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24d4e76214Sopenharmony_ciOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25d4e76214Sopenharmony_ciWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 26d4e76214Sopenharmony_ci 27d4e76214Sopenharmony_ci#include "unwind_i.h" 28d4e76214Sopenharmony_ci#include "offsets.h" 29d4e76214Sopenharmony_ci 30d4e76214Sopenharmony_cistatic int 31d4e76214Sopenharmony_cish_handle_signal_frame (unw_cursor_t *cursor) 32d4e76214Sopenharmony_ci{ 33d4e76214Sopenharmony_ci struct cursor *c = (struct cursor *) cursor; 34d4e76214Sopenharmony_ci int ret; 35d4e76214Sopenharmony_ci unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; 36d4e76214Sopenharmony_ci struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); 37d4e76214Sopenharmony_ci 38d4e76214Sopenharmony_ci if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) 39d4e76214Sopenharmony_ci return -UNW_EUNSPEC; 40d4e76214Sopenharmony_ci 41d4e76214Sopenharmony_ci ret = unw_is_signal_frame (cursor); 42d4e76214Sopenharmony_ci Debug(1, "unw_is_signal_frame()=%d\n", ret); 43d4e76214Sopenharmony_ci 44d4e76214Sopenharmony_ci /* Save the SP and PC to be able to return execution at this point 45d4e76214Sopenharmony_ci later in time (unw_resume). */ 46d4e76214Sopenharmony_ci c->sigcontext_sp = c->dwarf.cfa; 47d4e76214Sopenharmony_ci c->sigcontext_pc = c->dwarf.ip; 48d4e76214Sopenharmony_ci 49d4e76214Sopenharmony_ci if (ret == 1) 50d4e76214Sopenharmony_ci { 51d4e76214Sopenharmony_ci /* Handle non-RT signal frame. */ 52d4e76214Sopenharmony_ci c->sigcontext_format = SH_SCF_LINUX_SIGFRAME; 53d4e76214Sopenharmony_ci sc_addr = sp_addr; 54d4e76214Sopenharmony_ci } 55d4e76214Sopenharmony_ci else if (ret == 2) 56d4e76214Sopenharmony_ci { 57d4e76214Sopenharmony_ci /* Handle RT signal frame. */ 58d4e76214Sopenharmony_ci c->sigcontext_format = SH_SCF_LINUX_RT_SIGFRAME; 59d4e76214Sopenharmony_ci sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; 60d4e76214Sopenharmony_ci } 61d4e76214Sopenharmony_ci else 62d4e76214Sopenharmony_ci return -UNW_EUNSPEC; 63d4e76214Sopenharmony_ci 64d4e76214Sopenharmony_ci c->sigcontext_addr = sc_addr; 65d4e76214Sopenharmony_ci 66d4e76214Sopenharmony_ci /* Update the dwarf cursor. 67d4e76214Sopenharmony_ci Set the location of the registers to the corresponding addresses of the 68d4e76214Sopenharmony_ci uc_mcontext / sigcontext structure contents. */ 69d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); 70d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); 71d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); 72d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); 73d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); 74d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); 75d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); 76d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); 77d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); 78d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); 79d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); 80d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); 81d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); 82d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); 83d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); 84d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); 85d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_PR] = DWARF_LOC (sc_addr + LINUX_SC_PR_OFF, 0); 86d4e76214Sopenharmony_ci c->dwarf.loc[UNW_SH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); 87d4e76214Sopenharmony_ci 88d4e76214Sopenharmony_ci /* Set SP/CFA and PC/IP. */ 89d4e76214Sopenharmony_ci dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_R15], &c->dwarf.cfa); 90d4e76214Sopenharmony_ci dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip); 91d4e76214Sopenharmony_ci 92d4e76214Sopenharmony_ci c->dwarf.pi_valid = 0; 93d4e76214Sopenharmony_ci 94d4e76214Sopenharmony_ci return 1; 95d4e76214Sopenharmony_ci} 96d4e76214Sopenharmony_ci 97d4e76214Sopenharmony_ciint 98d4e76214Sopenharmony_ciunw_step (unw_cursor_t *cursor) 99d4e76214Sopenharmony_ci{ 100d4e76214Sopenharmony_ci struct cursor *c = (struct cursor *) cursor; 101d4e76214Sopenharmony_ci int ret; 102d4e76214Sopenharmony_ci 103d4e76214Sopenharmony_ci Debug (1, "(cursor=%p)\n", c); 104d4e76214Sopenharmony_ci 105d4e76214Sopenharmony_ci if (unw_is_signal_frame (cursor) > 0) 106d4e76214Sopenharmony_ci return sh_handle_signal_frame (cursor); 107d4e76214Sopenharmony_ci 108d4e76214Sopenharmony_ci ret = dwarf_step (&c->dwarf); 109d4e76214Sopenharmony_ci 110d4e76214Sopenharmony_ci if (unlikely (ret == -UNW_ESTOPUNWIND)) 111d4e76214Sopenharmony_ci return ret; 112d4e76214Sopenharmony_ci 113d4e76214Sopenharmony_ci if (unlikely (ret < 0)) 114d4e76214Sopenharmony_ci return 0; 115d4e76214Sopenharmony_ci 116d4e76214Sopenharmony_ci return (c->dwarf.ip == 0) ? 0 : 1; 117d4e76214Sopenharmony_ci} 118