dwarf/Gparser: fix crash during unwinding 24/161224/1 accepted/tizen_5.0_base accepted/tizen_5.5_base accepted/tizen_5.5_base_mobile_hotfix accepted/tizen_5.5_base_wearable_hotfix accepted/tizen_6.0_base accepted/tizen_6.0_base_tool accepted/tizen_6.0_base_tool_hotfix tizen_5.0_base tizen_5.5_base_mobile_hotfix tizen_5.5_base_wearable_hotfix tizen_5.5_tv tizen_6.0_base tizen_6.0_base_hotfix accepted/tizen/5.0/base/20181101.090315 accepted/tizen/5.5/base/20191030.081902 accepted/tizen/5.5/base/mobile/hotfix/20201023.084336 accepted/tizen/5.5/base/wearable/hotfix/20201023.080734 accepted/tizen/6.0/base/20201029.110930 accepted/tizen/6.0/base/20230713.142919 accepted/tizen/6.0/base/tool/20201029.112212 accepted/tizen/6.0/base/tool/hotfix/20201030.125016 accepted/tizen/6.0/base/tool/hotfix/20201102.090322 accepted/tizen/base/20180914.214614 submit/tizen_5.0_base/20181101.000001 submit/tizen_5.5_base/20191030.000001 submit/tizen_5.5_base_mobile_hotfix/20201023.171501 submit/tizen_5.5_base_wearable_hotfix/20201023.155601 submit/tizen_6.0_base/20201029.184801 submit/tizen_6.0_base_hotfix/20201030.192501 submit/tizen_6.0_base_hotfix/20201102.162701 submit/tizen_base/20180910.125249 tizen_5.5.m2_release tizen_6.0.m2_release
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Tue, 17 Oct 2017 18:27:53 +0000 (21:27 +0300)
committerKonstantin Baladurin <k.baladurin@partner.samsung.com>
Wed, 22 Nov 2017 07:22:04 +0000 (10:22 +0300)
We should update locations of the registers after all of them will
be restored. Otherwise some locations will be incorrect.

For example if function stores ebp, edi, esi and ebx registers on
stack in its prologue, compiler can generate following unwind info:
DW_CFA_expression: r5 (ebp) (DW_OP_breg5 (ebp): 0)
DW_CFA_expression: r7 (edi) (DW_OP_breg5 (ebp): -4)
DW_CFA_expression: r6 (esi) (DW_OP_breg5 (ebp): -8)
DW_CFA_expression: r3 (ebx) (DW_OP_breg5 (ebp): -12)

In this case locations of the ebx and ebp will be calculated using
current ebp but locations of the esi and edi will be calculated using
previous (restored) one. Due to it their locations will be incorrect
and it could lead to crash if we will try to get esi or edi value.

This patch fixes this problem.

Origin: https://github.com/libunwind/libunwind/pull/44
Change-Id: I33595d23fbbe034820461c2161f26e5285342ff8

src/dwarf/Gparser.c

index 3a47255..455124b 100644 (file)
@@ -776,40 +776,45 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
       cfa = DWARF_GET_LOC (cfa_loc);
     }
 
+  dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS];
+  memcpy(new_loc, c->loc, sizeof(new_loc));
+
   for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
     {
       switch ((dwarf_where_t) rs->reg[i].where)
         {
         case DWARF_WHERE_UNDEF:
-          c->loc[i] = DWARF_NULL_LOC;
+          new_loc[i] = DWARF_NULL_LOC;
           break;
 
         case DWARF_WHERE_SAME:
           break;
 
         case DWARF_WHERE_CFAREL:
-          c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
+          new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
           break;
 
         case DWARF_WHERE_REG:
-          c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
+          new_loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
           break;
 
         case DWARF_WHERE_EXPR:
           addr = rs->reg[i].val;
-          if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
+          if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
             return ret;
           break;
 
         case DWARF_WHERE_VAL_EXPR:
           addr = rs->reg[i].val;
-          if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
+          if ((ret = eval_location_expr (c, as, a, addr, new_loc + i, arg)) < 0)
             return ret;
-          c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i]));
+          new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
           break;
         }
     }
 
+  memcpy(c->loc, new_loc, sizeof(new_loc));
+
   c->cfa = cfa;
   /* DWARF spec says undefined return address location means end of stack. */
   if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))