LCOV - code coverage report
Current view: top level - libdwfl - frame_unwind.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 207 330 62.7 %
Date: 2017-01-05 09:15:16 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Get previous frame state for an existing frame state.
       2             :    Copyright (C) 2013, 2014, 2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             : 
       5             :    This file is free software; you can redistribute it and/or modify
       6             :    it under the terms of either
       7             : 
       8             :      * the GNU Lesser General Public License as published by the Free
       9             :        Software Foundation; either version 3 of the License, or (at
      10             :        your option) any later version
      11             : 
      12             :    or
      13             : 
      14             :      * the GNU General Public License as published by the Free
      15             :        Software Foundation; either version 2 of the License, or (at
      16             :        your option) any later version
      17             : 
      18             :    or both in parallel, as here.
      19             : 
      20             :    elfutils is distributed in the hope that it will be useful, but
      21             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23             :    General Public License for more details.
      24             : 
      25             :    You should have received copies of the GNU General Public License and
      26             :    the GNU Lesser General Public License along with this program.  If
      27             :    not, see <http://www.gnu.org/licenses/>.  */
      28             : 
      29             : #ifdef HAVE_CONFIG_H
      30             : # include <config.h>
      31             : #endif
      32             : 
      33             : #include "cfi.h"
      34             : #include <stdlib.h>
      35             : #include "libdwflP.h"
      36             : #include "../libdw/dwarf.h"
      37             : #include <sys/ptrace.h>
      38             : #include <system.h>
      39             : 
      40             : /* Maximum number of DWARF expression stack slots before returning an error.  */
      41             : #define DWARF_EXPR_STACK_MAX 0x100
      42             : 
      43             : /* Maximum number of DWARF expression executed operations before returning an
      44             :    error.  */
      45             : #define DWARF_EXPR_STEPS_MAX 0x1000
      46             : 
      47             : bool
      48             : internal_function
      49        2914 : __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
      50             : {
      51        2914 :   Ebl *ebl = state->thread->process->ebl;
      52        2914 :   if (! ebl_dwarf_to_regno (ebl, &regno))
      53             :     return false;
      54        2910 :   if (regno >= ebl_frame_nregs (ebl))
      55             :     return false;
      56        5820 :   if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
      57        2910 :        & ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
      58             :     return false;
      59        1526 :   if (val)
      60        1526 :     *val = state->regs[regno];
      61             :   return true;
      62             : }
      63             : 
      64             : bool
      65             : internal_function
      66        2071 : __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val)
      67             : {
      68        2071 :   Ebl *ebl = state->thread->process->ebl;
      69        2071 :   if (! ebl_dwarf_to_regno (ebl, &regno))
      70             :     return false;
      71        2067 :   if (regno >= ebl_frame_nregs (ebl))
      72             :     return false;
      73             :   /* For example i386 user_regs_struct has signed fields.  */
      74        2067 :   if (ebl_get_elfclass (ebl) == ELFCLASS32)
      75         549 :     val &= 0xffffffff;
      76        4134 :   state->regs_set[regno / sizeof (*state->regs_set) / 8] |=
      77        2067 :                 ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)));
      78        2067 :   state->regs[regno] = val;
      79        2067 :   return true;
      80             : }
      81             : 
      82             : static bool
      83             : state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
      84             : {
      85        2220 :   if (! __libdwfl_frame_reg_get (state, regno, val))
      86             :     {
      87         818 :       __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
      88             :       return false;
      89             :     }
      90             :   return true;
      91             : }
      92             : 
      93             : static int
      94             : bra_compar (const void *key_voidp, const void *elem_voidp)
      95             : {
      96         468 :   Dwarf_Word offset = (uintptr_t) key_voidp;
      97         468 :   const Dwarf_Op *op = elem_voidp;
      98         468 :   return (offset > op->offset) - (offset < op->offset);
      99             : }
     100             : 
     101             : struct eval_stack {
     102             :   Dwarf_Addr *addrs;
     103             :   size_t used;
     104             :   size_t allocated;
     105             : };
     106             : 
     107             : static bool
     108        1995 : do_push (struct eval_stack *stack, Dwarf_Addr val)
     109             : {
     110        1995 :   if (stack->used >= DWARF_EXPR_STACK_MAX)
     111             :     {
     112           0 :       __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     113           0 :       return false;
     114             :     }
     115        1995 :   if (stack->used == stack->allocated)
     116             :     {
     117        1232 :       stack->allocated = MAX (stack->allocated * 2, 32);
     118             :       Dwarf_Addr *new_addrs;
     119        1232 :       new_addrs = realloc (stack->addrs,
     120             :                            stack->allocated * sizeof (*stack->addrs));
     121        1232 :       if (new_addrs == NULL)
     122             :         {
     123           0 :           __libdwfl_seterrno (DWFL_E_NOMEM);
     124           0 :           return false;
     125             :         }
     126        1232 :       stack->addrs = new_addrs;
     127             :     }
     128        1995 :   stack->addrs[stack->used++] = val;
     129        1995 :   return true;
     130             : }
     131             : 
     132             : static bool
     133             : do_pop (struct eval_stack *stack, Dwarf_Addr *val)
     134             : {
     135        1991 :   if (stack->used == 0)
     136             :     {
     137           0 :       __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     138             :       return false;
     139             :     }
     140        1991 :   *val = stack->addrs[--stack->used];
     141             :   return true;
     142             : }
     143             : 
     144             : /* If FRAME is NULL is are computing CFI frame base.  In such case another
     145             :    DW_OP_call_frame_cfa is no longer permitted.  */
     146             : 
     147             : static bool
     148        1232 : expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
     149             :            size_t nops, Dwarf_Addr *result, Dwarf_Addr bias)
     150             : {
     151        1232 :   Dwfl_Process *process = state->thread->process;
     152        1232 :   if (nops == 0)
     153             :     {
     154           0 :       __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     155           0 :       return false;
     156             :     }
     157        1232 :   struct eval_stack stack =
     158             :     {
     159             :       .addrs = NULL,
     160             :       .used = 0,
     161             :       .allocated = 0
     162             :     };
     163             : 
     164             : #define pop(x) do_pop(&stack, x)
     165             : #define push(x) do_push(&stack, x)
     166             : 
     167             :   Dwarf_Addr val1, val2;
     168        1232 :   bool is_location = false;
     169        1232 :   size_t steps_count = 0;
     170        3371 :   for (const Dwarf_Op *op = ops; op < ops + nops; op++)
     171             :     {
     172        2139 :       if (++steps_count > DWARF_EXPR_STEPS_MAX)
     173             :         {
     174           0 :           __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     175           0 :           return false;
     176             :         }
     177        2139 :       switch (op->atom)
     178             :       {
     179             :         /* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op:  */
     180             :         case DW_OP_lit0 ... DW_OP_lit31:
     181         114 :           if (! push (op->atom - DW_OP_lit0))
     182             :             {
     183           0 :               free (stack.addrs);
     184           0 :               return false;
     185             :             }
     186        2139 :           break;
     187             :         case DW_OP_addr:
     188           0 :           if (! push (op->number + bias))
     189             :             {
     190           0 :               free (stack.addrs);
     191           0 :               return false;
     192             :             }
     193             :           break;
     194             :         case DW_OP_GNU_encoded_addr:
     195             :           /* Missing support in the rest of elfutils.  */
     196           0 :           __libdwfl_seterrno (DWFL_E_UNSUPPORTED_DWARF);
     197           0 :           return false;
     198             :         case DW_OP_const1u:
     199             :         case DW_OP_const1s:
     200             :         case DW_OP_const2u:
     201             :         case DW_OP_const2s:
     202             :         case DW_OP_const4u:
     203             :         case DW_OP_const4s:
     204             :         case DW_OP_const8u:
     205             :         case DW_OP_const8s:
     206             :         case DW_OP_constu:
     207             :         case DW_OP_consts:
     208          35 :           if (! push (op->number))
     209             :             {
     210           0 :               free (stack.addrs);
     211           0 :               return false;
     212             :             }
     213             :           break;
     214             :         case DW_OP_reg0 ... DW_OP_reg31:
     215           0 :           if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1)
     216           0 :               || ! push (val1))
     217             :             {
     218           0 :               free (stack.addrs);
     219           0 :               return false;
     220             :             }
     221             :           break;
     222             :         case DW_OP_regx:
     223         144 :           if (! state_get_reg (state, op->number, &val1) || ! push (val1))
     224             :             {
     225           0 :               free (stack.addrs);
     226           0 :               return false;
     227             :             }
     228             :           break;
     229             :         case DW_OP_breg0 ... DW_OP_breg31:
     230          20 :           if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1))
     231             :             {
     232           0 :               free (stack.addrs);
     233           0 :               return false;
     234             :             }
     235          10 :           val1 += op->number;
     236          10 :           if (! push (val1))
     237             :             {
     238           0 :               free (stack.addrs);
     239           0 :               return false;
     240             :             }
     241             :           break;
     242             :         case DW_OP_bregx:
     243        1148 :           if (! state_get_reg (state, op->number, &val1))
     244             :             {
     245           0 :               free (stack.addrs);
     246           0 :               return false;
     247             :             }
     248         574 :           val1 += op->number2;
     249         574 :           if (! push (val1))
     250             :             {
     251           0 :               free (stack.addrs);
     252           0 :               return false;
     253             :             }
     254             :           break;
     255             :         case DW_OP_dup:
     256           2 :           if (! pop (&val1) || ! push (val1) || ! push (val1))
     257             :             {
     258           0 :               free (stack.addrs);
     259           0 :               return false;
     260             :             }
     261             :           break;
     262             :         case DW_OP_drop:
     263           2 :           if (! pop (&val1))
     264             :             {
     265           0 :               free (stack.addrs);
     266           0 :               return false;
     267             :             }
     268             :           break;
     269             :         case DW_OP_pick:
     270           2 :           if (stack.used <= op->number)
     271             :             {
     272           0 :               free (stack.addrs);
     273           0 :               __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     274           0 :               return false;
     275             :             }
     276           2 :           if (! push (stack.addrs[stack.used - 1 - op->number]))
     277             :             {
     278           0 :               free (stack.addrs);
     279           0 :               return false;
     280             :             }
     281             :           break;
     282             :         case DW_OP_over:
     283          21 :           if (! pop (&val1) || ! pop (&val2)
     284           7 :               || ! push (val2) || ! push (val1) || ! push (val2))
     285             :             {
     286           0 :               free (stack.addrs);
     287           0 :               return false;
     288             :             }
     289             :           break;
     290             :         case DW_OP_swap:
     291           3 :           if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2))
     292             :             {
     293           0 :               free (stack.addrs);
     294           0 :               return false;
     295             :             }
     296             :           break;
     297             :         case DW_OP_rot:
     298             :           {
     299             :             Dwarf_Addr val3;
     300           4 :             if (! pop (&val1) || ! pop (&val2) || ! pop (&val3)
     301           1 :                 || ! push (val1) || ! push (val3) || ! push (val2))
     302             :               {
     303           0 :                 free (stack.addrs);
     304           0 :                 return false;
     305             :               }
     306             :           }
     307             :           break;
     308             :         case DW_OP_deref:
     309             :         case DW_OP_deref_size:
     310           6 :           if (process->callbacks->memory_read == NULL)
     311             :             {
     312           0 :               free (stack.addrs);
     313           0 :               __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
     314           0 :               return false;
     315             :             }
     316          12 :           if (! pop (&val1)
     317           6 :               || ! process->callbacks->memory_read (process->dwfl, val1, &val1,
     318             :                                                     process->callbacks_arg))
     319             :             {
     320           0 :               free (stack.addrs);
     321           0 :               return false;
     322             :             }
     323           6 :           if (op->atom == DW_OP_deref_size)
     324             :             {
     325           0 :               const int elfclass = frame->cache->e_ident[EI_CLASS];
     326           0 :               const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8;
     327           0 :               if (op->number > addr_bytes)
     328             :                 {
     329           0 :                   free (stack.addrs);
     330           0 :                   __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     331           0 :                   return false;
     332             :                 }
     333             : #if BYTE_ORDER == BIG_ENDIAN
     334             :               if (op->number == 0)
     335             :                 val1 = 0;
     336             :               else
     337             :                 val1 >>= (addr_bytes - op->number) * 8;
     338             : #else
     339           0 :               if (op->number < 8)
     340           0 :                 val1 &= (1 << (op->number * 8)) - 1;
     341             : #endif
     342             :             }
     343           6 :           if (! push (val1))
     344             :             {
     345           0 :               free (stack.addrs);
     346           0 :               return false;
     347             :             }
     348             :           break;
     349             : #define UNOP(atom, expr)                                                \
     350             :         case atom:                                                      \
     351             :           if (! pop (&val1) || ! push (expr))                               \
     352             :             {                                                           \
     353             :               free (stack.addrs);                                       \
     354             :               return false;                                             \
     355             :             }                                                           \
     356             :           break;
     357           4 :         UNOP (DW_OP_abs, llabs ((int64_t) val1))
     358           6 :         UNOP (DW_OP_neg, -(int64_t) val1)
     359           2 :         UNOP (DW_OP_not, ~val1)
     360             : #undef UNOP
     361             :         case DW_OP_plus_uconst:
     362         942 :           if (! pop (&val1) || ! push (val1 + op->number))
     363             :             {
     364           0 :               free (stack.addrs);
     365           0 :               return false;
     366             :             }
     367             :           break;
     368             : #define BINOP(atom, op)                                                 \
     369             :         case atom:                                                      \
     370             :           if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2))  \
     371             :             {                                                           \
     372             :               free (stack.addrs);                                       \
     373             :               return false;                                             \
     374             :             }                                                           \
     375             :           break;
     376             : #define BINOP_SIGNED(atom, op)                                          \
     377             :         case atom:                                                      \
     378             :           if (! pop (&val2) || ! pop (&val1)                            \
     379             :               || ! push ((int64_t) val1 op (int64_t) val2))             \
     380             :             {                                                           \
     381             :               free (stack.addrs);                                       \
     382             :               return false;                                             \
     383             :             }                                                           \
     384             :           break;
     385           6 :         BINOP (DW_OP_and, &)
     386             :         case DW_OP_div:
     387          15 :           if (! pop (&val2) || ! pop (&val1))
     388             :             {
     389           0 :               free (stack.addrs);
     390           0 :               return false;
     391             :             }
     392           5 :           if (val2 == 0)
     393             :             {
     394           0 :               free (stack.addrs);
     395           0 :               __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     396           0 :               return false;
     397             :             }
     398           5 :           if (! push ((int64_t) val1 / (int64_t) val2))
     399             :             {
     400           0 :               free (stack.addrs);
     401           0 :               return false;
     402             :             }
     403             :           break;
     404          15 :         BINOP (DW_OP_minus, -)
     405             :         case DW_OP_mod:
     406           9 :           if (! pop (&val2) || ! pop (&val1))
     407             :             {
     408           0 :               free (stack.addrs);
     409           0 :               return false;
     410             :             }
     411           3 :           if (val2 == 0)
     412             :             {
     413           0 :               free (stack.addrs);
     414           0 :               __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     415           0 :               return false;
     416             :             }
     417           3 :           if (! push (val1 % val2))
     418             :             {
     419           0 :               free (stack.addrs);
     420           0 :               return false;
     421             :             }
     422             :           break;
     423          12 :         BINOP (DW_OP_mul, *)
     424           3 :         BINOP (DW_OP_or, |)
     425           6 :         BINOP (DW_OP_plus, +)
     426           3 :         BINOP (DW_OP_shl, <<)
     427           6 :         BINOP (DW_OP_shr, >>)
     428           6 :         BINOP_SIGNED (DW_OP_shra, >>)
     429           3 :         BINOP (DW_OP_xor, ^)
     430           9 :         BINOP_SIGNED (DW_OP_le, <=)
     431           9 :         BINOP_SIGNED (DW_OP_ge, >=)
     432         156 :         BINOP_SIGNED (DW_OP_eq, ==)
     433          12 :         BINOP_SIGNED (DW_OP_lt, <)
     434          12 :         BINOP_SIGNED (DW_OP_gt, >)
     435           9 :         BINOP_SIGNED (DW_OP_ne, !=)
     436             : #undef BINOP
     437             : #undef BINOP_SIGNED
     438             :         case DW_OP_bra:
     439         122 :           if (! pop (&val1))
     440             :             {
     441           0 :               free (stack.addrs);
     442           0 :               return false;
     443             :             }
     444          61 :           if (val1 == 0)
     445             :             break;
     446             :           /* FALLTHRU */
     447             :         case DW_OP_skip:;
     448          61 :           Dwarf_Word offset = op->offset + 1 + 2 + (int16_t) op->number;
     449         122 :           const Dwarf_Op *found = bsearch ((void *) (uintptr_t) offset, ops, nops,
     450             :                                            sizeof (*ops), bra_compar);
     451          61 :           if (found == NULL)
     452             :             {
     453           0 :               free (stack.addrs);
     454             :               /* PPC32 vDSO has such invalid operations.  */
     455           0 :               __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     456           0 :               return false;
     457             :             }
     458             :           /* Undo the 'for' statement increment.  */
     459          61 :           op = found - 1;
     460          61 :           break;
     461             :         case DW_OP_nop:
     462             :           break;
     463             :         /* DW_OP_* not listed in libgcc/unwind-dw2.c execute_stack_op:  */
     464             :         case DW_OP_call_frame_cfa:;
     465             :           // Not used by CFI itself but it is synthetized by elfutils internation.
     466             :           Dwarf_Op *cfa_ops;
     467             :           size_t cfa_nops;
     468             :           Dwarf_Addr cfa;
     469         580 :           if (frame == NULL
     470         580 :               || dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0
     471         580 :               || ! expr_eval (state, NULL, cfa_ops, cfa_nops, &cfa, bias)
     472         580 :               || ! push (cfa))
     473             :             {
     474           0 :               __libdwfl_seterrno (DWFL_E_LIBDW);
     475           0 :               free (stack.addrs);
     476           0 :               return false;
     477             :             }
     478             :           is_location = true;
     479             :           break;
     480             :         case DW_OP_stack_value:
     481             :           // Not used by CFI itself but it is synthetized by elfutils internation.
     482          98 :           is_location = false;
     483          98 :           break;
     484             :         default:
     485           0 :           __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     486           0 :           return false;
     487             :       }
     488             :     }
     489        2464 :   if (! pop (result))
     490             :     {
     491           0 :       free (stack.addrs);
     492           0 :       return false;
     493             :     }
     494        1232 :   free (stack.addrs);
     495        1232 :   if (is_location)
     496             :     {
     497         482 :       if (process->callbacks->memory_read == NULL)
     498             :         {
     499           0 :           __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
     500           0 :           return false;
     501             :         }
     502         482 :       if (! process->callbacks->memory_read (process->dwfl, *result, result,
     503             :                                              process->callbacks_arg))
     504             :         return false;
     505             :     }
     506             :   return true;
     507             : #undef push
     508             : #undef pop
     509             : }
     510             : 
     511             : static Dwfl_Frame *
     512         168 : new_unwound (Dwfl_Frame *state)
     513             : {
     514         168 :   assert (state->unwound == NULL);
     515         168 :   Dwfl_Thread *thread = state->thread;
     516         168 :   Dwfl_Process *process = thread->process;
     517         168 :   Ebl *ebl = process->ebl;
     518         168 :   size_t nregs = ebl_frame_nregs (ebl);
     519         168 :   assert (nregs > 0);
     520             :   Dwfl_Frame *unwound;
     521         168 :   unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs);
     522         168 :   if (unlikely (unwound == NULL))
     523             :     return NULL;
     524         168 :   state->unwound = unwound;
     525         168 :   unwound->thread = thread;
     526         168 :   unwound->unwound = NULL;
     527         168 :   unwound->signal_frame = false;
     528         168 :   unwound->initial_frame = false;
     529         168 :   unwound->pc_state = DWFL_FRAME_STATE_ERROR;
     530         168 :   memset (unwound->regs_set, 0, sizeof (unwound->regs_set));
     531         168 :   return unwound;
     532             : }
     533             : 
     534             : /* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation
     535             :    error so one can easily catch the problem with a debugger.  Still there are
     536             :    archs with invalid CFI for some registers where the registers are never used
     537             :    later.  Therefore we continue unwinding leaving the registers undefined.  */
     538             : 
     539             : static void
     540         173 : handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
     541             : {
     542             :   Dwarf_Frame *frame;
     543         173 :   if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0)
     544             :     {
     545          38 :       __libdwfl_seterrno (DWFL_E_LIBDW);
     546          38 :       return;
     547             :     }
     548             : 
     549         135 :   Dwfl_Frame *unwound = new_unwound (state);
     550         135 :   if (unwound == NULL)
     551             :     {
     552           0 :       __libdwfl_seterrno (DWFL_E_NOMEM);
     553           0 :       return;
     554             :     }
     555             : 
     556         135 :   unwound->signal_frame = frame->fde->cie->signal_frame;
     557         135 :   Dwfl_Thread *thread = state->thread;
     558         135 :   Dwfl_Process *process = thread->process;
     559         135 :   Ebl *ebl = process->ebl;
     560         135 :   size_t nregs = ebl_frame_nregs (ebl);
     561         135 :   assert (nregs > 0);
     562             : 
     563             :   /* The return register is special for setting the unwound->pc_state.  */
     564         135 :   unsigned ra = frame->fde->cie->return_address_register;
     565         135 :   bool ra_set = false;
     566         135 :   ebl_dwarf_to_regno (ebl, &ra);
     567             : 
     568        4338 :   for (unsigned regno = 0; regno < nregs; regno++)
     569             :     {
     570             :       Dwarf_Op reg_ops_mem[3], *reg_ops;
     571             :       size_t reg_nops;
     572        4203 :       if (dwarf_frame_register (frame, regno, reg_ops_mem, &reg_ops,
     573             :                                 &reg_nops) != 0)
     574             :         {
     575           0 :           __libdwfl_seterrno (DWFL_E_LIBDW);
     576        2805 :           continue;
     577             :         }
     578             :       Dwarf_Addr regval;
     579        4203 :       if (reg_nops == 0)
     580             :         {
     581        3551 :           if (reg_ops == reg_ops_mem)
     582             :             {
     583             :               /* REGNO is undefined.  */
     584        1987 :               if (regno == ra)
     585          11 :                 unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
     586        1987 :               continue;
     587             :             }
     588        1564 :           else if (reg_ops == NULL)
     589             :             {
     590             :               /* REGNO is same-value.  */
     591        1564 :               if (! state_get_reg (state, regno, &regval))
     592         818 :                 continue;
     593             :             }
     594             :           else
     595             :             {
     596           0 :               __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
     597           0 :               continue;
     598             :             }
     599             :         }
     600         652 :       else if (! expr_eval (state, frame, reg_ops, reg_nops, &regval, bias))
     601             :         {
     602             :           /* PPC32 vDSO has various invalid operations, ignore them.  The
     603             :              register will look as unset causing an error later, if used.
     604             :              But PPC32 does not use such registers.  */
     605           0 :           continue;
     606             :         }
     607             : 
     608             :       /* Some architectures encode some extra info in the return address.  */
     609        1398 :       if (regno == frame->fde->cie->return_address_register)
     610         124 :         regval &= ebl_func_addr_mask (ebl);
     611             : 
     612             :       /* This is another strange PPC[64] case.  There are two
     613             :          registers numbers that can represent the same DWARF return
     614             :          register number.  We only want one to actually set the return
     615             :          register value.  But we always want to override the value if
     616             :          the register is the actual CIE return address register.  */
     617        1398 :       if (ra_set && regno != frame->fde->cie->return_address_register)
     618             :         {
     619         198 :           unsigned r = regno;
     620         198 :           if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
     621           0 :             continue;
     622             :         }
     623             : 
     624        1398 :       if (! __libdwfl_frame_reg_set (unwound, regno, regval))
     625             :         {
     626           0 :           __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
     627           0 :           continue;
     628             :         }
     629        1398 :       else if (! ra_set)
     630             :         {
     631        1200 :           unsigned r = regno;
     632        1200 :           if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
     633         124 :             ra_set = true;
     634             :         }
     635             :     }
     636         135 :   if (unwound->pc_state == DWFL_FRAME_STATE_ERROR
     637         248 :       && __libdwfl_frame_reg_get (unwound,
     638         124 :                                   frame->fde->cie->return_address_register,
     639             :                                   &unwound->pc))
     640             :     {
     641             :       /* PPC32 __libc_start_main properly CFI-unwinds PC as zero.  Currently
     642             :          none of the archs supported for unwinding have zero as a valid PC.  */
     643         124 :       if (unwound->pc == 0)
     644           0 :         unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
     645             :       else
     646             :         {
     647         124 :           unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
     648             :           /* In SPARC the return address register actually contains
     649             :              the address of the call instruction instead of the return
     650             :              address.  Therefore we add here an offset defined by the
     651             :              backend.  Most likely 0.  */
     652         124 :           unwound->pc += ebl_ra_offset (ebl);
     653             :         }
     654             :     }
     655         135 :   free (frame);
     656             : }
     657             : 
     658             : static bool
     659           0 : setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg)
     660             : {
     661           0 :   Dwfl_Frame *state = arg;
     662           0 :   Dwfl_Frame *unwound = state->unwound;
     663           0 :   if (firstreg < 0)
     664             :     {
     665           0 :       assert (firstreg == -1);
     666           0 :       assert (nregs == 1);
     667           0 :       assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
     668           0 :       unwound->pc = *regs;
     669           0 :       unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
     670           0 :       return true;
     671             :     }
     672           0 :   while (nregs--)
     673           0 :     if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++))
     674             :       return false;
     675             :   return true;
     676             : }
     677             : 
     678             : static bool
     679           0 : getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg)
     680             : {
     681           0 :   Dwfl_Frame *state = arg;
     682           0 :   assert (firstreg >= 0);
     683           0 :   while (nregs--)
     684           0 :     if (! __libdwfl_frame_reg_get (state, firstreg++, regs++))
     685             :       return false;
     686             :   return true;
     687             : }
     688             : 
     689             : static bool
     690           6 : readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg)
     691             : {
     692           6 :   Dwfl_Frame *state = arg;
     693           6 :   Dwfl_Thread *thread = state->thread;
     694           6 :   Dwfl_Process *process = thread->process;
     695           6 :   return process->callbacks->memory_read (process->dwfl, addr, datap,
     696             :                                           process->callbacks_arg);
     697             : }
     698             : 
     699             : void
     700             : internal_function
     701         259 : __libdwfl_frame_unwind (Dwfl_Frame *state)
     702             : {
     703         259 :   if (state->unwound)
     704         259 :     return;
     705             :   /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE
     706             :      which would deadlock us.  */
     707             :   Dwarf_Addr pc;
     708         168 :   bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL);
     709         168 :   assert (ok);
     710             :   /* Check whether this is the initial frame or a signal frame.
     711             :      Then we need to unwind from the original, unadjusted PC.  */
     712         168 :   if (! state->initial_frame && ! state->signal_frame)
     713         133 :     pc--;
     714         168 :   Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc);
     715         168 :   if (mod == NULL)
     716           1 :     __libdwfl_seterrno (DWFL_E_NO_DWARF);
     717             :   else
     718             :     {
     719             :       Dwarf_Addr bias;
     720         167 :       Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias);
     721         167 :       if (cfi_eh)
     722             :         {
     723         157 :           handle_cfi (state, pc - bias, cfi_eh, bias);
     724         157 :           if (state->unwound)
     725         135 :             return;
     726             :         }
     727          42 :       Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias);
     728          42 :       if (cfi_dwarf)
     729             :         {
     730          16 :           handle_cfi (state, pc - bias, cfi_dwarf, bias);
     731          16 :           if (state->unwound)
     732             :             return;
     733             :         }
     734             :     }
     735          33 :   assert (state->unwound == NULL);
     736          33 :   Dwfl_Thread *thread = state->thread;
     737          33 :   Dwfl_Process *process = thread->process;
     738          33 :   Ebl *ebl = process->ebl;
     739          33 :   if (new_unwound (state) == NULL)
     740             :     {
     741           0 :       __libdwfl_seterrno (DWFL_E_NOMEM);
     742           0 :       return;
     743             :     }
     744          33 :   state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
     745             :   // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield.
     746          33 :   bool signal_frame = false;
     747          33 :   if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame))
     748             :     {
     749             :       // Discard the unwind attempt.  During next __libdwfl_frame_unwind call
     750             :       // we may have for example the appropriate Dwfl_Module already mapped.
     751          33 :       assert (state->unwound->unwound == NULL);
     752          33 :       free (state->unwound);
     753          33 :       state->unwound = NULL;
     754             :       // __libdwfl_seterrno has been called above.
     755          33 :       return;
     756             :     }
     757           0 :   assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET);
     758           0 :   state->unwound->signal_frame = signal_frame;
     759             : }

Generated by: LCOV version 1.12