13842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* libunwind - a platform-independent unwind library 23842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz Copyright (C) 2008 CodeSourcery 33842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 43842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzThis file is part of libunwind. 53842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 63842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzPermission is hereby granted, free of charge, to any person obtaining 73842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitza copy of this software and associated documentation files (the 83842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz"Software"), to deal in the Software without restriction, including 93842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzwithout limitation the rights to use, copy, modify, merge, publish, 103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzdistribute, sublicense, and/or sell copies of the Software, and to 113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzpermit persons to whom the Software is furnished to do so, subject to 123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzthe following conditions: 133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 143842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzThe above copyright notice and this permission notice shall be 153842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzincluded in all copies or substantial portions of the Software. 163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 173842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 183842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 203842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 213842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 223842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 233842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 243842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include "unwind_i.h" 263842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include "offsets.h" 273842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 283842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzPROTECTED int 298c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazkerunw_handle_signal_frame (unw_cursor_t *cursor) 303842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz{ 313842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz struct cursor *c = (struct cursor *) cursor; 328c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; 338c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker unw_word_t ra, fp; 343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz int ret; 353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 368c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker /* FIXME (simon): Save the SP and PC to be able to return execution 378c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker at this point later in time (unw_resume). */ 388c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker // c->sigcontext_sp = c->dwarf.cfa; 398c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker // c->sigcontext_pc = c->dwarf.ip; 408c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 418c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker switch (unw_is_signal_frame (cursor)) { 428c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker case 1: 438c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + 448c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker LINUX_UC_MCONTEXT_OFF; 458c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker break; 468c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker case 2: 47b02a66eca4d44c8901c7a0c447abbf2cab2ef891Faraz Shahbazker sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; 488c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker break; 498c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker default: 508c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker return -UNW_EUNSPEC; 518c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker } 528c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 538c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker if (tdep_big_endian(c->dwarf.as)) 548c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker sc_addr += 4; 558c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 568c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->sigcontext_addr = sc_addr; 578c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 588c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker /* Update the dwarf cursor. */ 598c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); 608c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); 618c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); 628c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); 638c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); 648c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); 658c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); 668c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); 678c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); 688c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); 698c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); 708c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); 718c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); 728c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); 738c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); 748c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); 758c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); 768c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); 778c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); 788c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); 798c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); 808c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); 818c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); 828c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); 838c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); 848c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); 858c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); 868c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); 878c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); 888c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); 898c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); 908c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); 918c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); 928c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 938c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker /* Set SP/CFA and PC/IP. */ 948c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa); 958c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker //dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R31], &c->dwarf.ip); 968c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 978c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), 988c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker &c->dwarf.ip)) < 0) 998c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker return ret; 1008c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 1018c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), 1028c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker &ra)) < 0) 1038c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker return ret; 1048c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), 1058c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker &fp)) < 0) 1068c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker return ret; 1078c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 1088c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", 1098c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker (unsigned long long)c->dwarf.ip, (unsigned long long)ra, 1108c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); 1118c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 1128c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.pi_valid = 0; 1138c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker c->dwarf.use_prev_instr = 0; 1148c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 1158c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker return 1; 1168c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker} 1178c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker 1188c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz ShahbazkerPROTECTED int 1198c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazkerunw_step (unw_cursor_t *cursor) 1208c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker{ 1218c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker struct cursor *c = (struct cursor *) cursor; 1228c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker int ret; 1233842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 124ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris unw_word_t old_ip = c->dwarf.ip; 125ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris unw_word_t old_cfa = c->dwarf.cfa; 126ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris 1278c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker ret = unw_handle_signal_frame (cursor); 1288c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker if (ret < 0) 1298c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker /* Not a signal frame, try DWARF-based unwinding. */ 1308c380e9d596cc9dbc39423e0d8ae5ee51da6be2bFaraz Shahbazker ret = dwarf_step (&c->dwarf); 1313842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 1323842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (unlikely (ret == -UNW_ESTOPUNWIND)) 1333842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz return ret; 1343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 1353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* Dwarf unwinding didn't work, stop. */ 1363842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (unlikely (ret < 0)) 1373842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz return 0; 1383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 139ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris /* If the decode yields the exact same ip/cfa as before, then indicate 140ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris the unwind is complete. */ 141ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa) 142ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris { 143ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", 144ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris __FUNCTION__, (long) c->dwarf.ip); 145ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris return -UNW_EBADFRAME; 146ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris } 147ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris 1483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz return (c->dwarf.ip == 0) ? 0 : 1; 1493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz} 150