Gstep.c revision 17bf4d0af84466787d06f90c832dc93d3cd8843a
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 746058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); 756058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 766058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (unw_is_signal_frame (cursor)) 776058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm { 786058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm unw_word_t ucontext = c->dwarf.cfa; 796058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 806058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm Debug(1, "signal frame, skip over trampoline\n"); 81a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 826058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; 836058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm c->sigcontext_addr = c->dwarf.cfa; 84a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 856058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); 866058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rbp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); 876058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm rip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); 88a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 896058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); 906058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm if (ret < 0) 9117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 9217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 9317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 9417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 9517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 9617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); 9717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); 9817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); 9917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); 10017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); 10117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); 10217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); 10317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); 10417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); 10517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); 10617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); 10717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); 10817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); 10917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); 11017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); 11117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); 1126058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm } 1136058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm else 1146058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm { 11517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm unw_word_t rbp; 1166058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm 11717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); 11817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (ret < 0) 11917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 12017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 12117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 12217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 12317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 12417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (!rbp) 12517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 12617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm /* Looks like we may have reached the end of the call-chain. */ 12717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rbp_loc = DWARF_NULL_LOC; 12817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rsp_loc = DWARF_NULL_LOC; 12917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rip_loc = DWARF_NULL_LOC; 13017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 13117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm else 13217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 13317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (1, "[RBP=0x%Lx] = 0x%Lx (cfa = 0x%Lx)\n", 13417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RBP]), 13517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) rbp, 13617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm (unsigned long long) c->dwarf.cfa); 13717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 13817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rbp_loc = c->dwarf.loc[RBP]; 13917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rsp_loc = DWARF_NULL_LOC; 14017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm rip_loc = DWARF_LOC (c->dwarf.cfa + 8, 0); 14117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.cfa += 8; 14217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 14317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 14417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm /* Mark all registers unsaved */ 14517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 14617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm c->dwarf.loc[i] = DWARF_NULL_LOC; 1476058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm } 148a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 149a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RBP] = rbp_loc; 150a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RSP] = rsp_loc; 151a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.loc[RIP] = rip_loc; 152a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.ret_addr_column = RIP; 153a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock 154a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) 155a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock { 156a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); 157a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock if (ret < 0) 15817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm { 15917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 16017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 16117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm } 162a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock } 163a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock else 164a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock c->dwarf.ip = 0; 16517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm 16617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa) 16717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return -UNW_EBADFRAME; 168a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock } 16917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm ret = (c->dwarf.ip == 0) ? 0 : 1; 17017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm Debug (2, "returning %d\n", ret); 17117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm return ret; 172a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock} 173