Home | History | Annotate | Download | only in ppc32
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2006-2007 IBM
      3    Contributed by
      4      Corey Ashford <cjashfor (at) us.ibm.com>
      5      Jose Flavio Aguilar Paulino <jflavio (at) br.ibm.com> <joseflavio (at) gmail.com>
      6 
      7 This file is part of libunwind.
      8 
      9 Permission is hereby granted, free of charge, to any person obtaining
     10 a copy of this software and associated documentation files (the
     11 "Software"), to deal in the Software without restriction, including
     12 without limitation the rights to use, copy, modify, merge, publish,
     13 distribute, sublicense, and/or sell copies of the Software, and to
     14 permit persons to whom the Software is furnished to do so, subject to
     15 the following conditions:
     16 
     17 The above copyright notice and this permission notice shall be
     18 included in all copies or substantial portions of the Software.
     19 
     20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     27 
     28 #include "unwind_i.h"
     29 #include "ucontext_i.h"
     30 #include <signal.h>
     31 
     32 /* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is
     33    defined there only when __KERNEL__ is defined.  We reproduce it here for
     34    our use at the user level in order to locate the ucontext record, which
     35    appears to be at this offset relative to the stack pointer when in the
     36    context of the signal handler return trampoline code -
     37    __kernel_sigtramp_rt64.  */
     38 #define __SIGNAL_FRAMESIZE 128
     39 
     40 /* This definition comes from the document "64-bit PowerPC ELF Application
     41    Binary Interface Supplement 1.9", section 3.2.2.
     42    http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */
     43 
     44 typedef struct
     45 {
     46   long unsigned back_chain;
     47   long unsigned lr_save;
     48   /* many more fields here, but they are unused by this code */
     49 } stack_frame_t;
     50 
     51 
     52 PROTECTED int
     53 unw_step (unw_cursor_t * cursor)
     54 {
     55   struct cursor *c = (struct cursor *) cursor;
     56   stack_frame_t dummy;
     57   unw_word_t back_chain_offset, lr_save_offset;
     58   struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc;
     59   int ret;
     60 
     61   Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);
     62 
     63   if (c->dwarf.ip == 0)
     64     {
     65       /* Unless the cursor or stack is corrupt or uninitialized,
     66          we've most likely hit the top of the stack */
     67       return 0;
     68     }
     69 
     70   /* Try DWARF-based unwinding... */
     71 
     72   ret = dwarf_step (&c->dwarf);
     73 
     74   if (ret < 0 && ret != -UNW_ENOINFO)
     75     {
     76       Debug (2, "returning %d\n", ret);
     77       return ret;
     78     }
     79 
     80   if (unlikely (ret < 0))
     81     {
     82       if (likely (!unw_is_signal_frame (cursor)))
     83 	{
     84 	  /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
     85 	     produces the mandatory level of traceback record in the code, but
     86 	     I get the impression that this is transitory, that eventually gcc
     87 	     will not produce any traceback records at all.  So, for now, we
     88 	     won't bother to try to find and use these records.
     89 
     90 	     We can, however, attempt to unwind the frame by using the callback
     91 	     chain.  This is very crude, however, and won't be able to unwind
     92 	     any registers besides the IP, SP, and LR . */
     93 
     94 	  back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
     95 	  lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);
     96 
     97 	  back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);
     98 
     99 	  if ((ret =
    100 	       dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
    101 	    {
    102 	      Debug (2,
    103 		 "Unable to retrieve CFA from back chain in stack frame - %d\n",
    104 		 ret);
    105 	      return ret;
    106 	    }
    107 	  if (c->dwarf.cfa == 0)
    108 	    /* Unless the cursor or stack is corrupt or uninitialized we've most
    109 	       likely hit the top of the stack */
    110 	    return 0;
    111 
    112 	  lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);
    113 
    114 	  if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
    115 	    {
    116 	      Debug (2,
    117 		 "Unable to retrieve IP from lr save in stack frame - %d\n",
    118 		 ret);
    119 	      return ret;
    120 	    }
    121 	  ret = 1;
    122 	}
    123       else
    124 	{
    125           /* Find the sigcontext record by taking the CFA and adjusting by
    126              the dummy signal frame size.
    127 
    128              Note that there isn't any way to determined if SA_SIGINFO was
    129              set in the sa_flags parameter to sigaction when the signal
    130              handler was established.  If it was not set, the ucontext
    131              record is not required to be on the stack, in which case the
    132              following code will likely cause a seg fault or other crash
    133              condition.  */
    134 
    135 	  unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE;
    136 
    137 	  Debug (1, "signal frame, skip over trampoline\n");
    138 
    139 	  c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME;
    140 	  c->sigcontext_addr = ucontext;
    141 
    142 	  sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
    143 	  ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
    144 
    145 	  ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa);
    146 	  if (ret < 0)
    147 	    {
    148 	      Debug (2, "returning %d\n", ret);
    149 	      return ret;
    150 	    }
    151 	  ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip);
    152 	  if (ret < 0)
    153 	    {
    154 	      Debug (2, "returning %d\n", ret);
    155 	      return ret;
    156 	    }
    157 
    158 	  /* Instead of just restoring the non-volatile registers, do all
    159 	     of the registers for now.  This will incur a performance hit,
    160 	     but it's rare enough not to cause too much of a problem, and
    161 	     might be useful in some cases.  */
    162 	  c->dwarf.loc[UNW_PPC32_R0] =
    163 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
    164 	  c->dwarf.loc[UNW_PPC32_R1] =
    165 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
    166 	  c->dwarf.loc[UNW_PPC32_R2] =
    167 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
    168 	  c->dwarf.loc[UNW_PPC32_R3] =
    169 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
    170 	  c->dwarf.loc[UNW_PPC32_R4] =
    171 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
    172 	  c->dwarf.loc[UNW_PPC32_R5] =
    173 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
    174 	  c->dwarf.loc[UNW_PPC32_R6] =
    175 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
    176 	  c->dwarf.loc[UNW_PPC32_R7] =
    177 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
    178 	  c->dwarf.loc[UNW_PPC32_R8] =
    179 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
    180 	  c->dwarf.loc[UNW_PPC32_R9] =
    181 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
    182 	  c->dwarf.loc[UNW_PPC32_R10] =
    183 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
    184 	  c->dwarf.loc[UNW_PPC32_R11] =
    185 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
    186 	  c->dwarf.loc[UNW_PPC32_R12] =
    187 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
    188 	  c->dwarf.loc[UNW_PPC32_R13] =
    189 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
    190 	  c->dwarf.loc[UNW_PPC32_R14] =
    191 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
    192 	  c->dwarf.loc[UNW_PPC32_R15] =
    193 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
    194 	  c->dwarf.loc[UNW_PPC32_R16] =
    195 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
    196 	  c->dwarf.loc[UNW_PPC32_R17] =
    197 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
    198 	  c->dwarf.loc[UNW_PPC32_R18] =
    199 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
    200 	  c->dwarf.loc[UNW_PPC32_R19] =
    201 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
    202 	  c->dwarf.loc[UNW_PPC32_R20] =
    203 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
    204 	  c->dwarf.loc[UNW_PPC32_R21] =
    205 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
    206 	  c->dwarf.loc[UNW_PPC32_R22] =
    207 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
    208 	  c->dwarf.loc[UNW_PPC32_R23] =
    209 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
    210 	  c->dwarf.loc[UNW_PPC32_R24] =
    211 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
    212 	  c->dwarf.loc[UNW_PPC32_R25] =
    213 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
    214 	  c->dwarf.loc[UNW_PPC32_R26] =
    215 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
    216 	  c->dwarf.loc[UNW_PPC32_R27] =
    217 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
    218 	  c->dwarf.loc[UNW_PPC32_R28] =
    219 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
    220 	  c->dwarf.loc[UNW_PPC32_R29] =
    221 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
    222 	  c->dwarf.loc[UNW_PPC32_R30] =
    223 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
    224 	  c->dwarf.loc[UNW_PPC32_R31] =
    225 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);
    226 
    227 	  c->dwarf.loc[UNW_PPC32_LR] =
    228 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
    229 	  c->dwarf.loc[UNW_PPC32_CTR] =
    230 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
    231 
    232 	  /* This CR0 assignment is probably wrong.  There are 8 dwarf columns
    233 	     assigned to the CR registers, but only one CR register in the
    234 	     mcontext structure */
    235 	  c->dwarf.loc[UNW_PPC32_CCR] =
    236 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
    237 	  c->dwarf.loc[UNW_PPC32_XER] =
    238 	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
    239 
    240 	  c->dwarf.loc[UNW_PPC32_F0] =
    241 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
    242 	  c->dwarf.loc[UNW_PPC32_F1] =
    243 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
    244 	  c->dwarf.loc[UNW_PPC32_F2] =
    245 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
    246 	  c->dwarf.loc[UNW_PPC32_F3] =
    247 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
    248 	  c->dwarf.loc[UNW_PPC32_F4] =
    249 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
    250 	  c->dwarf.loc[UNW_PPC32_F5] =
    251 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
    252 	  c->dwarf.loc[UNW_PPC32_F6] =
    253 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
    254 	  c->dwarf.loc[UNW_PPC32_F7] =
    255 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
    256 	  c->dwarf.loc[UNW_PPC32_F8] =
    257 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
    258 	  c->dwarf.loc[UNW_PPC32_F9] =
    259 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
    260 	  c->dwarf.loc[UNW_PPC32_F10] =
    261 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
    262 	  c->dwarf.loc[UNW_PPC32_F11] =
    263 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
    264 	  c->dwarf.loc[UNW_PPC32_F12] =
    265 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
    266 	  c->dwarf.loc[UNW_PPC32_F13] =
    267 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
    268 	  c->dwarf.loc[UNW_PPC32_F14] =
    269 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
    270 	  c->dwarf.loc[UNW_PPC32_F15] =
    271 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
    272 	  c->dwarf.loc[UNW_PPC32_F16] =
    273 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
    274 	  c->dwarf.loc[UNW_PPC32_F17] =
    275 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
    276 	  c->dwarf.loc[UNW_PPC32_F18] =
    277 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
    278 	  c->dwarf.loc[UNW_PPC32_F19] =
    279 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
    280 	  c->dwarf.loc[UNW_PPC32_F20] =
    281 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
    282 	  c->dwarf.loc[UNW_PPC32_F21] =
    283 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
    284 	  c->dwarf.loc[UNW_PPC32_F22] =
    285 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
    286 	  c->dwarf.loc[UNW_PPC32_F23] =
    287 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
    288 	  c->dwarf.loc[UNW_PPC32_F24] =
    289 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
    290 	  c->dwarf.loc[UNW_PPC32_F25] =
    291 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
    292 	  c->dwarf.loc[UNW_PPC32_F26] =
    293 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
    294 	  c->dwarf.loc[UNW_PPC32_F27] =
    295 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
    296 	  c->dwarf.loc[UNW_PPC32_F28] =
    297 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
    298 	  c->dwarf.loc[UNW_PPC32_F29] =
    299 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
    300 	  c->dwarf.loc[UNW_PPC32_F30] =
    301 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
    302 	  c->dwarf.loc[UNW_PPC32_F31] =
    303 	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
    304 
    305 	  ret = 1;
    306 	}
    307     }
    308   return ret;
    309 }
    310