Gstep.c revision 649f1fb3449a65dd0626a709432d8b02a7c56bbc
1a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock/* libunwind - a platform-independent unwind library 217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Copyright (C) 2002-2004 Hewlett-Packard Co 3a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 4a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 5a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock Modified for x86_64 by Max Asbock <masbock@us.ibm.com> 6a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 7a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockThis file is part of libunwind. 8a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 9a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockPermission is hereby granted, free of charge, to any person obtaining 10a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbocka copy of this software and associated documentation files (the 11a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock"Software"), to deal in the Software without restriction, including 12a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockwithout limitation the rights to use, copy, modify, merge, publish, 13a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockdistribute, sublicense, and/or sell copies of the Software, and to 14a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockpermit persons to whom the Software is furnished to do so, subject to 15a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockthe following conditions: 16a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 17a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockThe above copyright notice and this permission notice shall be 18a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockincluded in all copies or substantial portions of the Software. 19a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 20a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 27a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 28a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock#include "unwind_i.h" 2951ef1210e84bfba2bfaa64432424d0668dbc95d8homeip.net!davidm#include "ucontext_i.h" 30a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock#include <signal.h> 31a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 32a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockPROTECTED int 33a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockunw_step (unw_cursor_t *cursor) 34a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock{ 35a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock struct cursor *c = (struct cursor *) cursor; 36a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock int ret, i; 37a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 3817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (1, "(cursor=%p, ip=0x%016llx)\n", 3917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c, (unsigned long long) c->dwarf.ip); 4017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 416058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm /* Try DWARF-based unwinding... */ 426058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm ret = dwarf_step (&c->dwarf); 43a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 4417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (ret < 0 && ret != -UNW_ENOINFO) 4517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 4617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 4717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 4817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 496058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 506058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (likely (ret >= 0)) 51a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock { 526058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm /* x86_64 ABI specifies that end of call-chain is marked with a 536058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm NULL RBP. */ 546058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) 556058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm c->dwarf.ip = 0; 56a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock } 57a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock else 58a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock { 5917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm /* DWARF failed. There isn't much of a usable frame-chain on x86-64, 6017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm but we do need to handle two special-cases: 6117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 6217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (i) signal trampoline: Old kernels and older libcs don't 6317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm export the vDSO needed to get proper unwind info for the 6417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm trampoline. Recognize that case by looking at the code 6517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm and filling in things by hand. 6617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 6717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (ii) PLT (shared-library) call-stubs: PLT stubs are invoked 6817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm via CALLQ. Try this for all non-signal trampoline 6917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm code. */ 7017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 7117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa; 72a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock struct dwarf_loc rbp_loc, rsp_loc, rip_loc; 73a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 74649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma /* We could get here because of missing/bad unwind information. 75649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma Validate all addresses before dereferencing. */ 76649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma c->validate = 1; 77649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma 786058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); 796058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 806058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (unw_is_signal_frame (cursor)) 816058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm { 826058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm unw_word_t ucontext = c->dwarf.cfa; 836058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 846058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm Debug(1, "signal frame, skip over trampoline\n"); 85a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 866058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; 876058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm c->sigcontext_addr = c->dwarf.cfa; 88a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 896058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); 906058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rbp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); 916058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); 92a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 936058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); 946058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (ret < 0) 9517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 9617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 9717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 9817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 9917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 10017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); 10117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); 10217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); 10317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); 10417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); 10517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); 10617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); 10717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); 10817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); 10917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); 11017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); 11117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); 11217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); 11317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); 11417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); 11517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); 1166058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm } 1176058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm else 1186058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm { 11917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm unw_word_t rbp; 1206058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 12117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); 12217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (ret < 0) 12317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 12417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 12517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 12617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 12717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 12817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (!rbp) 12917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 13017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm /* Looks like we may have reached the end of the call-chain. */ 13117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rbp_loc = DWARF_NULL_LOC; 13217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rsp_loc = DWARF_NULL_LOC; 13317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rip_loc = DWARF_NULL_LOC; 13417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 13517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm else 13617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 13706d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma unw_word_t rbp1; 13817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (1, "[RBP=0x%Lx] = 0x%Lx (cfa = 0x%Lx)\n", 13917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RBP]), 14017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) rbp, 14117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) c->dwarf.cfa); 14217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 14306d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma rbp_loc = DWARF_LOC(rbp, 0); 14417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rsp_loc = DWARF_NULL_LOC; 14506d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma rip_loc = DWARF_LOC (rbp + 8, 0); 14606d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma /* Heuristic to recognize a bogus frame pointer */ 14706d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); 1488297866bd4dbe239fc778ac5a971aca9b80325d7Arun Sharma if (ret || ((rbp1 - rbp) > 0x4000)) 14906d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma rbp_loc = DWARF_NULL_LOC; 1508297866bd4dbe239fc778ac5a971aca9b80325d7Arun Sharma c->dwarf.cfa += 16; 15117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 15217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 15317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm /* Mark all registers unsaved */ 15417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 15517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[i] = DWARF_NULL_LOC; 1566058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm } 157a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 158a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RBP] = rbp_loc; 159a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RSP] = rsp_loc; 160a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RIP] = rip_loc; 161a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.ret_addr_column = RIP; 162a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 163a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) 164a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock { 165a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); 16606d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", 16706d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), 16806d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma (unsigned long long) c->dwarf.ip); 169a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock if (ret < 0) 17017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 17117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 17217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 17317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 174a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock } 175a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock else 176a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.ip = 0; 17717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 17817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa) 17917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return -UNW_EBADFRAME; 180a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock } 18117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm ret = (c->dwarf.ip == 0) ? 0 : 1; 18217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 18317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 184a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock} 185