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"
29a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock#include <signal.h>
30c64723835c0c855fde5bec3d7528db64fe539015Konstantin Belousov
31aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma/* Recognise PLT entries such as:
32aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma     3bdf0: ff 25 e2 49 13 00 jmpq   *0x1349e2(%rip)
33aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma     3bdf6: 68 ae 03 00 00    pushq  $0x3ae
34aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma     3bdfb: e9 00 c5 ff ff    jmpq   38300 <_init+0x18> */
35aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharmastatic int
36aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharmais_plt_entry (struct dwarf_cursor *c)
37aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma{
38aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  unw_word_t w0, w1;
39aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  unw_accessors_t *a;
40aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  int ret;
41aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma
42aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  a = unw_get_accessors (c->as);
43aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0
44aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma      || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0)
45aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma    return 0;
46aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma
47aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  ret = (((w0 & 0xffff) == 0x25ff)
48aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	 && (((w0 >> 48) & 0xff) == 0x68)
49aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	 && (((w1 >> 24) & 0xff) == 0xe9));
50aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma
51aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret);
52aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  return ret;
53aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma}
54aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma
55a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockPROTECTED int
56a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbockunw_step (unw_cursor_t *cursor)
57a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock{
58a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock  struct cursor *c = (struct cursor *) cursor;
59a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock  int ret, i;
60a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock
619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if CONSERVATIVE_CHECKS
629e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  int val = c->validate;
639e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  c->validate = 1;
649e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
659e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
66aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma  Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n",
67aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	 c, c->dwarf.ip, c->dwarf.cfa);
6817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
696058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm  /* Try DWARF-based unwinding... */
70dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura  c->sigcontext_format = X86_64_SCF_NONE;
716058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm  ret = dwarf_step (&c->dwarf);
72a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock
739e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#if CONSERVATIVE_CHECKS
749e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  c->validate = val;
759e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#endif
769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
7717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm  if (ret < 0 && ret != -UNW_ENOINFO)
7817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm    {
7917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm      Debug (2, "returning %d\n", ret);
8017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm      return ret;
8117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm    }
826058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm
836058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm  if (likely (ret >= 0))
84a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock    {
856058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm      /* x86_64 ABI specifies that end of call-chain is marked with a
866058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	 NULL RBP.  */
876058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm      if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
881a6ea3da607d35c03733b9db26b64b71cdbfcfa7Konstantin Belousov	{
891a6ea3da607d35c03733b9db26b64b71cdbfcfa7Konstantin Belousov	  c->dwarf.ip = 0;
901a6ea3da607d35c03733b9db26b64b71cdbfcfa7Konstantin Belousov	  ret = 0;
911a6ea3da607d35c03733b9db26b64b71cdbfcfa7Konstantin Belousov	}
92a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock    }
93a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock  else
94a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock    {
9517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm      /* DWARF failed.  There isn't much of a usable frame-chain on x86-64,
9617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	 but we do need to handle two special-cases:
9717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
9817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  (i) signal trampoline: Old kernels and older libcs don't
9917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      export the vDSO needed to get proper unwind info for the
10017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      trampoline.  Recognize that case by looking at the code
10117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      and filling in things by hand.
10217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
10317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  (ii) PLT (shared-library) call-stubs: PLT stubs are invoked
10417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      via CALLQ.  Try this for all non-signal trampoline
10517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      code.  */
10617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
10717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm      unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa;
108a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock      struct dwarf_loc rbp_loc, rsp_loc, rip_loc;
109a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock
110649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma      /* We could get here because of missing/bad unwind information.
111649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma         Validate all addresses before dereferencing. */
112649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma      c->validate = 1;
113649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma
1146058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm      Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
1156058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm
116ccc0ae665baa67ae3df8595ab7bb0ef8cbc0e5c4Konstantin Belousov      if (unw_is_signal_frame (cursor))
1176058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	{
1188e53e62db913470952b8eb541834b876f7a6882cArun Sharma          ret = unw_handle_signal_frame(cursor);
1196058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	  if (ret < 0)
12017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    {
1218e53e62db913470952b8eb541834b876f7a6882cArun Sharma	      Debug (2, "returning 0\n");
1228e53e62db913470952b8eb541834b876f7a6882cArun Sharma	      return 0;
12317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    }
1246058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	}
125aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma      else if (is_plt_entry (&c->dwarf))
126aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	{
1279e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura          /* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */
128aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	  Debug (2, "found plt entry\n");
1299e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura          c->frame_info.cfa_reg_offset = 8;
1309e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura          c->frame_info.cfa_reg_rsp = -1;
1319e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura          c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD;
132aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma          c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0);
133aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma          c->dwarf.cfa += 8;
134aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma	}
135d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura      else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
136d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura        {
137d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura	  for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
138d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura	    c->dwarf.loc[i] = DWARF_NULL_LOC;
139d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura	}
1406058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm      else
1416058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	{
14217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  unw_word_t rbp;
1436058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm
14417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
14517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  if (ret < 0)
14617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    {
147d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura	      Debug (2, "returning %d [RBP=0x%lx]\n", ret,
148d4fbc8326a91d246af29ff17131a12ed7ae87140Lassi Tuura		     DWARF_GET_LOC (c->dwarf.loc[RBP]));
14917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      return ret;
15017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    }
15117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
15217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  if (!rbp)
15317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    {
15417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      /* Looks like we may have reached the end of the call-chain.  */
15517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      rbp_loc = DWARF_NULL_LOC;
15617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      rsp_loc = DWARF_NULL_LOC;
15717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      rip_loc = DWARF_NULL_LOC;
15817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    }
15917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  else
16017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    {
1619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      unw_word_t rbp1 = 0;
16206d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma	      rbp_loc = DWARF_LOC(rbp, 0);
16317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      rsp_loc = DWARF_NULL_LOC;
16406d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma	      rip_loc = DWARF_LOC (rbp + 8, 0);
16506d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma	      ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1);
1669e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n",
1679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		     (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]),
1689e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		     rbp, c->dwarf.cfa, rbp1);
1699e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1709e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      /* Heuristic to determine incorrect guess.  For RBP to be a
1719e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	         valid frame it needs to be above current CFA, but don't
1729e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		 let it go more than a little.  Note that we can't deduce
1739e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		 anything about new RBP (rbp1) since it may not be a frame
1749e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		 pointer in the frame above.  Just check we get the value. */
1759e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura              if (ret < 0
1769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		  || rbp <= c->dwarf.cfa
1779e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		  || (rbp - c->dwarf.cfa) > 0x4000)
1789e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	        {
1799e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura                  rip_loc = DWARF_NULL_LOC;
1809e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura                  rbp_loc = DWARF_NULL_LOC;
1819e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura		}
1829e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
1839e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura              c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED;
1849e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura              c->frame_info.cfa_reg_rsp = 0;
1859e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura              c->frame_info.cfa_reg_offset = 16;
1869e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura              c->frame_info.rbp_cfa_offset = -16;
1878297866bd4dbe239fc778ac5a971aca9b80325d7Arun Sharma	      c->dwarf.cfa += 16;
18817bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    }
18917bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
19017bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  /* Mark all registers unsaved */
19117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	  for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
19217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    c->dwarf.loc[i] = DWARF_NULL_LOC;
1938e53e62db913470952b8eb541834b876f7a6882cArun Sharma
1948e53e62db913470952b8eb541834b876f7a6882cArun Sharma          c->dwarf.loc[RBP] = rbp_loc;
1958e53e62db913470952b8eb541834b876f7a6882cArun Sharma          c->dwarf.loc[RSP] = rsp_loc;
1968e53e62db913470952b8eb541834b876f7a6882cArun Sharma          c->dwarf.loc[RIP] = rip_loc;
1976058013abe5b60291211458b0b71b87fad053ab9homeip.net!davidm	}
198a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock
199a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock      c->dwarf.ret_addr_column = RIP;
200a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock
201d0cbc51955b900749e1ae1f51d7c45d51d3bbd23Konstantin Belousov      if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
202d0cbc51955b900749e1ae1f51d7c45d51d3bbd23Konstantin Belousov        {
203d0cbc51955b900749e1ae1f51d7c45d51d3bbd23Konstantin Belousov	  ret = 0;
204adae66d2e24f3779272acfdff6941f29ed61950aTommi Rantala	  Debug (2, "NULL %%rbp loc, returning %d\n", ret);
205d0cbc51955b900749e1ae1f51d7c45d51d3bbd23Konstantin Belousov	  return ret;
206d0cbc51955b900749e1ae1f51d7c45d51d3bbd23Konstantin Belousov        }
207aa3bb307a30a5b78bf1ae4ac843ae53e354736f5Arun Sharma      if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP]))
208a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock	{
209a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip);
21006d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma	  Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n",
21106d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma		     (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]),
21206d2ffa41abd7a13a0580492fb2ae76dc0f728e6Arun Sharma		     (unsigned long long) c->dwarf.ip);
213a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock	  if (ret < 0)
21417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    {
21517bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      Debug (2, "returning %d\n", ret);
21617bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	      return ret;
21717bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	    }
218dd297ea92e7cea8050effdb5ac9998933a28da6eArun Sharma	  ret = 1;
219a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock	}
220a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock      else
221a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock	c->dwarf.ip = 0;
22217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm
22317bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm      if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa)
22417bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm	return -UNW_EBADFRAME;
225a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock    }
226f1f90e79544429ebc9b9be4587691cd12a4aa855Pavel Chupin  /* ANDROID support update. */
227f1f90e79544429ebc9b9be4587691cd12a4aa855Pavel Chupin  /* Adjust the pc to the instruction before. */
228f1f90e79544429ebc9b9be4587691cd12a4aa855Pavel Chupin  if (c->dwarf.ip)
229f1f90e79544429ebc9b9be4587691cd12a4aa855Pavel Chupin    c->dwarf.ip--;
230f1f90e79544429ebc9b9be4587691cd12a4aa855Pavel Chupin  /* End of ANDROID update. */
23117bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm  Debug (2, "returning %d\n", ret);
23217bf4d0af84466787d06f90c832dc93d3cd8843amostang.com!davidm  return ret;
233a766efd844260866e0d216f6eeef87f4593f60b2ibm.com!masbock}
234