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

Generated by: LCOV version 1.13