X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fx86_64%2FGstep.c;h=84b37280e55291132989efb7ca43b21e55ba00e7;hb=c3646297060ae1629ff1d1b10f648267f0495a0f;hp=9fa0967be5e97a706edc6ca8e160e4ab8356b83b;hpb=0349587920c255c479240518d9c04581977144eb;p=platform%2Fupstream%2Flibunwind.git diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 9fa0967..84b3728 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -1,6 +1,6 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang + Contributed by David Mosberger-Tang Modified for x86_64 by Max Asbock @@ -45,8 +45,8 @@ is_plt_entry (struct dwarf_cursor *c) return 0; ret = (((w0 & 0xffff) == 0x25ff) - && (((w0 >> 48) & 0xff) == 0x68) - && (((w1 >> 24) & 0xff) == 0xe9)); + && (((w0 >> 48) & 0xff) == 0x68) + && (((w1 >> 24) & 0xff) == 0xe9)); Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); return ret; @@ -64,7 +64,7 @@ unw_step (unw_cursor_t *cursor) #endif Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", - c, c->dwarf.ip, c->dwarf.cfa); + c, c->dwarf.ip, c->dwarf.cfa); /* Try DWARF-based unwinding... */ c->sigcontext_format = X86_64_SCF_NONE; @@ -83,26 +83,27 @@ unw_step (unw_cursor_t *cursor) if (likely (ret >= 0)) { /* x86_64 ABI specifies that end of call-chain is marked with a - NULL RBP. */ - if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) - { - c->dwarf.ip = 0; - ret = 0; - } + NULL RBP or undefined return address */ + if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]) + || DWARF_IS_NULL_LOC(c->dwarf.loc[c->dwarf.ret_addr_column])) + { + c->dwarf.ip = 0; + ret = 0; + } } else { /* DWARF failed. There isn't much of a usable frame-chain on x86-64, - but we do need to handle two special-cases: + but we do need to handle two special-cases: - (i) signal trampoline: Old kernels and older libcs don't - export the vDSO needed to get proper unwind info for the - trampoline. Recognize that case by looking at the code - and filling in things by hand. + (i) signal trampoline: Old kernels and older libcs don't + export the vDSO needed to get proper unwind info for the + trampoline. Recognize that case by looking at the code + and filling in things by hand. - (ii) PLT (shared-library) call-stubs: PLT stubs are invoked - via CALLQ. Try this for all non-signal trampoline - code. */ + (ii) PLT (shared-library) call-stubs: PLT stubs are invoked + via CALLQ. Try this for all non-signal trampoline + code. */ unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa; struct dwarf_loc rbp_loc, rsp_loc, rip_loc; @@ -114,114 +115,115 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); if (unw_is_signal_frame (cursor)) - { + { ret = unw_handle_signal_frame(cursor); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - } + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + } else if (is_plt_entry (&c->dwarf)) - { + { /* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */ - Debug (2, "found plt entry\n"); + Debug (2, "found plt entry\n"); c->frame_info.cfa_reg_offset = 8; c->frame_info.cfa_reg_rsp = -1; c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD; c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); c->dwarf.cfa += 8; - } + } else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + } else - { - unw_word_t rbp; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); - if (ret < 0) - { - Debug (2, "returning %d [RBP=0x%lx]\n", ret, - DWARF_GET_LOC (c->dwarf.loc[RBP])); - return ret; - } - - if (!rbp) - { - /* Looks like we may have reached the end of the call-chain. */ - rbp_loc = DWARF_NULL_LOC; - rsp_loc = DWARF_NULL_LOC; - rip_loc = DWARF_NULL_LOC; - } - else - { - unw_word_t rbp1 = 0; - rbp_loc = DWARF_LOC(rbp, 0); - rsp_loc = DWARF_NULL_LOC; - rip_loc = DWARF_LOC (rbp + 8, 0); - ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); - Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", - (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]), - rbp, c->dwarf.cfa, rbp1); - - /* Heuristic to determine incorrect guess. For RBP to be a - valid frame it needs to be above current CFA, but don't - let it go more than a little. Note that we can't deduce - anything about new RBP (rbp1) since it may not be a frame - pointer in the frame above. Just check we get the value. */ + { + unw_word_t rbp; + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); + if (ret < 0) + { + Debug (2, "returning %d [RBP=0x%lx]\n", ret, + DWARF_GET_LOC (c->dwarf.loc[RBP])); + return ret; + } + + if (!rbp) + { + /* Looks like we may have reached the end of the call-chain. */ + rbp_loc = DWARF_NULL_LOC; + rsp_loc = DWARF_NULL_LOC; + rip_loc = DWARF_NULL_LOC; + } + else + { + unw_word_t rbp1 = 0; + rbp_loc = DWARF_LOC(rbp, 0); + rsp_loc = DWARF_NULL_LOC; + rip_loc = DWARF_LOC (rbp + 8, 0); + ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); + Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", + (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]), + rbp, c->dwarf.cfa, rbp1); + + /* Heuristic to determine incorrect guess. For RBP to be a + valid frame it needs to be above current CFA, but don't + let it go more than a little. Note that we can't deduce + anything about new RBP (rbp1) since it may not be a frame + pointer in the frame above. Just check we get the value. */ if (ret < 0 - || rbp <= c->dwarf.cfa - || (rbp - c->dwarf.cfa) > 0x4000) - { + || rbp < c->dwarf.cfa + || (rbp - c->dwarf.cfa) > 0x4000) + { rip_loc = DWARF_NULL_LOC; rbp_loc = DWARF_NULL_LOC; - } + } c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED; c->frame_info.cfa_reg_rsp = 0; c->frame_info.cfa_reg_offset = 16; c->frame_info.rbp_cfa_offset = -16; - c->dwarf.cfa += 16; - } + c->dwarf.cfa += 16; + } - /* Mark all registers unsaved */ - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; + /* Mark all registers unsaved */ + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; c->dwarf.loc[RBP] = rbp_loc; c->dwarf.loc[RSP] = rsp_loc; c->dwarf.loc[RIP] = rip_loc; - } + c->dwarf.use_prev_instr = 1; + } c->dwarf.ret_addr_column = RIP; if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { - ret = 0; - Debug (2, "NULL %%rbp loc, returning %d\n", ret); - return ret; + ret = 0; + Debug (2, "NULL %%rbp loc, returning %d\n", ret); + return ret; } if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) - { - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); - Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", - (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), - (unsigned long long) c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - ret = 1; - } + { + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", + (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), + (unsigned long long) c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + ret = 1; + } else - c->dwarf.ip = 0; + c->dwarf.ip = 0; if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa) - return -UNW_EBADFRAME; + return -UNW_EBADFRAME; } Debug (2, "returning %d\n", ret); return ret;