1ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux/* libunwind - a platform-independent unwind library 2ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Copyright (C) 2008 CodeSourcery 3ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Copyright (C) 2011-2013 Linaro Limited 4ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com> 5ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 6ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThis file is part of libunwind. 7ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 8ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPermission is hereby granted, free of charge, to any person obtaining 9ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxa copy of this software and associated documentation files (the 10ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux"Software"), to deal in the Software without restriction, including 11ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxwithout limitation the rights to use, copy, modify, merge, publish, 12ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdistribute, sublicense, and/or sell copies of the Software, and to 13ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxpermit persons to whom the Software is furnished to do so, subject to 14ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxthe following conditions: 15ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 16ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThe above copyright notice and this permission notice shall be 17ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxincluded in all copies or substantial portions of the Software. 18ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 19ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 26ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 27ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "unwind_i.h" 28ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "offsets.h" 29ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 30ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPROTECTED int 31ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxunw_handle_signal_frame (unw_cursor_t *cursor) 32ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{ 33ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux struct cursor *c = (struct cursor *) cursor; 34ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux int ret; 35ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; 36ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); 37ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 38ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) 39ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return -UNW_EUNSPEC; 40ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 41ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux ret = unw_is_signal_frame (cursor); 42ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Debug(1, "unw_is_signal_frame()=%d\n", ret); 43ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 44ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux /* Save the SP and PC to be able to return execution at this point 45ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux later in time (unw_resume). */ 46ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->sigcontext_sp = c->dwarf.cfa; 47ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->sigcontext_pc = c->dwarf.ip; 48ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 49ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux if (ret) 50ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux { 51ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME; 52ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; 53ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux } 54ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux else 55ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return -UNW_EUNSPEC; 56ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 57ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->sigcontext_addr = sc_addr; 58ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 59ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux /* Update the dwarf cursor. 60ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Set the location of the registers to the corresponding addresses of the 61ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux uc_mcontext / sigcontext structure contents. */ 62ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0); 63ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0); 64ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0); 65ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0); 66ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0); 67ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0); 68ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0); 69ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0); 70ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0); 71ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0); 72ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0); 73ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0); 74ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0); 75ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0); 76ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0); 77ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0); 78ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0); 79ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0); 80ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0); 81ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0); 82ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0); 83ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0); 84ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0); 85ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0); 86ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0); 87ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0); 88ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0); 89ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0); 90ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0); 91ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0); 92ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0); 93ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); 94ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); 95ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0); 96ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 97ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux /* Set SP/CFA and PC/IP. */ 98ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); 99ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); 100ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 101ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c->dwarf.pi_valid = 0; 102ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 103ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return 1; 104ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux} 105ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 106ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPROTECTED int 107ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxunw_step (unw_cursor_t *cursor) 108ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{ 109ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux struct cursor *c = (struct cursor *) cursor; 1104868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris int ret = -UNW_ENOINFO; 111ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 112ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n", 113ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux c, c->dwarf.ip, c->dwarf.cfa); 114ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 115ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris unw_word_t old_ip = c->dwarf.ip; 116ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris unw_word_t old_cfa = c->dwarf.cfa; 117ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris 118ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux /* Check if this is a signal frame. */ 119ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux if (unw_is_signal_frame (cursor)) 1204868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris /* ANDROID support update. */ 1214868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris ret = unw_handle_signal_frame (cursor); 1224868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris /* End ANDROID update. */ 1234868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris 1244868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris /* ANDROID support update. */ 1254868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris if (ret < 0) 1264868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris { 1274868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris ret = dwarf_step (&c->dwarf); 1284868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris Debug(1, "dwarf_step()=%d\n", ret); 1294868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris } 130ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 1314868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris if (ret < 0 && c->dwarf.frame == 0) 1324868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris { 1334868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris /* If this is the first frame, the code may be executing garbage 1344868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris * in the middle of nowhere. In this case, try using the lr as 1354868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris * the pc. 1364868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris */ 1374868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris unw_word_t lr; 1384868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_AARCH64_X30], &lr) >= 0) 1394868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris { 1404868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris if (lr != c->dwarf.ip) 1414868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris { 1424868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris ret = 1; 1434868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris c->dwarf.ip = lr; 1444868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris } 1454868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris } 1464868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris } 1474868ff1ab2b82a52a1abb48bcf6dcbf795d3c4dbChristopher Ferris /* End ANDROID update. */ 148ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 14960c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris if (ret >= 0) 15060c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris { 15160c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris if (c->dwarf.ip >= 4) 15260c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris c->dwarf.ip -= 4; 153ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris /* If the decode yields the exact same ip/cfa as before, then indicate 154ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris the unwind is complete. */ 155ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa) 156ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris { 157ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", 158ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris __FUNCTION__, (long) c->dwarf.ip); 159ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris return -UNW_EBADFRAME; 160ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris } 161ba74ff681be3b1e9fab247c15b30887b8237449eChristopher Ferris c->dwarf.frame++; 16260c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris } 16360c0e104182996ce3739e3377d1f8f3f706853caChristopher Ferris 164ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux if (unlikely (ret == -UNW_ESTOPUNWIND)) 165ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return ret; 166ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 167ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux if (unlikely (ret < 0)) 168ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return 0; 169ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux 170ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux return (c->dwarf.ip == 0) ? 0 : 1; 171ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux} 172