Handle multiple target events before commit resume
[deliverable/binutils-gdb.git] / binutils / unwind-ia64.c
index 642f9b2a49d26fb5be02da9b7ea8d8f21676590e..f6f73ce83ea895fa95a64b9cc0b05e8d7eeb7c53 100644 (file)
@@ -1,5 +1,5 @@
 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
-   Copyright (C) 2000-2014 Free Software Foundation, Inc.
+   Copyright (C) 2000-2019 Free Software Foundation, Inc.
 
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
@@ -21,9 +21,8 @@
    MA 02110-1301, USA.  */
 
 #include "config.h"
+#include "sysdep.h"
 #include "unwind-ia64.h"
-#include <stdio.h>
-#include <string.h>
 
 #if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
@@ -174,7 +173,7 @@ unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
 typedef bfd_vma unw_word;
 
 #define UNW_DEC_BAD_CODE(code)                 \
-    printf ("Unknown code 0x%02x\n", code)
+  printf (_("Unknown code 0x%02x\n"), code)
 
 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg)                                 \
   do                                                                           \
@@ -349,14 +348,22 @@ typedef bfd_vma unw_word;
   printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n",              \
          fmt, 4*(unsigned long)pspoff)
 
-#define UNW_DEC_SPILL_MASK(fmt, dp, arg)                                       \
-  do                                                                           \
-    {                                                                          \
-      static const char *spill_type = "-frb";                                  \
+#define UNW_DEC_SPILL_MASK(fmt, dp, arg, end)                          \
+  do                                                                   \
+    {                                                                  \
+      static const char *spill_type = "-frb";                          \
       unsigned const char *imaskp = dp;                                        \
-      unsigned char mask = 0;                                                  \
-      bfd_vma insn = 0;                                                                \
-                                                                               \
+      unsigned char mask = 0;                                          \
+      bfd_vma insn = 0;                                                        \
+                                                                       \
+      /* PR 18420.  */                                                 \
+      if ((dp + (unw_rlen / 4)) > end)                                 \
+       {                                                               \
+         printf (_("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n"), \
+                 (long) (unw_rlen / 4), (long)(end - dp));             \
+         /* FIXME: Should we reset unw_rlen ?  */                      \
+         break;                                                        \
+       }                                                               \
       printf ("\t%s:spill_mask(imask=[", fmt);                                 \
       for (insn = 0; insn < unw_rlen; ++insn)                                  \
        {                                                                       \
@@ -533,44 +540,14 @@ typedef bfd_vma unw_word;
  *     UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
  */
 
-static unw_word unw_decode_uleb128 (const unsigned char **);
-static const unsigned char *unw_decode_x1
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_x2
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_x3
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_x4
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_r1
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_r2
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_r3
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_p1
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_p2_p5
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_p6
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_p7_p10
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_b1
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_b2
-  (const unsigned char *, unsigned int, void *);
-static const unsigned char *unw_decode_b3_x4
-  (const unsigned char *, unsigned int, void *);
-
 static unw_word
-unw_decode_uleb128 (const unsigned char **dpp)
+unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end)
 {
   unsigned shift = 0;
   unw_word byte, result = 0;
   const unsigned char *bp = *dpp;
 
-  while (1)
+  while (bp < end)
     {
       byte = *bp++;
       result |= (byte & 0x7f) << shift;
@@ -588,14 +565,20 @@ unw_decode_uleb128 (const unsigned char **dpp)
 
 static const unsigned char *
 unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
 {
   unsigned char byte1, abreg;
   unw_word t, off;
 
+  if ((end - dp) < 3)
+    {
+      printf (_("\t<corrupt X1>\n"));
+      return end;
+    }
+
   byte1 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-  off = unw_decode_uleb128 (&dp);
+  t = unw_decode_uleb128 (&dp, end);
+  off = unw_decode_uleb128 (&dp, end);
   abreg = (byte1 & 0x7f);
   if (byte1 & 0x80)
     UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
@@ -606,14 +589,20 @@ unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
 
 static const unsigned char *
 unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
 {
   unsigned char byte1, byte2, abreg, x, ytreg;
   unw_word t;
 
+  if ((end - dp) < 3)
+    {
+      printf (_("\t<corrupt X2>\n"));
+      return end;
+    }
+
   byte1 = *dp++;
   byte2 = *dp++;
-  t = unw_decode_uleb128 (&dp);
+  t = unw_decode_uleb128 (&dp, end);
   abreg = (byte1 & 0x7f);
   ytreg = byte2;
   x = (byte1 >> 7) & 1;
@@ -626,15 +615,21 @@ unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
 
 static const unsigned char *
 unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
 {
   unsigned char byte1, byte2, abreg, qp;
   unw_word t, off;
 
+  if ((end - dp) < 4)
+    {
+      printf (_("\t<corrupt X3>\n"));
+      return end;
+    }
+
   byte1 = *dp++;
   byte2 = *dp++;
-  t = unw_decode_uleb128 (&dp);
-  off = unw_decode_uleb128 (&dp);
+  t = unw_decode_uleb128 (&dp, end);
+  off = unw_decode_uleb128 (&dp, end);
 
   qp = (byte1 & 0x3f);
   abreg = (byte2 & 0x7f);
@@ -648,15 +643,21 @@ unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
 
 static const unsigned char *
 unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
 {
   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
   unw_word t;
 
+  if ((end - dp) < 4)
+    {
+      printf (_("\t<corrupt X4>\n"));
+      return end;
+    }
+
   byte1 = *dp++;
   byte2 = *dp++;
   byte3 = *dp++;
-  t = unw_decode_uleb128 (&dp);
+  t = unw_decode_uleb128 (&dp, end);
 
   qp = (byte1 & 0x3f);
   abreg = (byte2 & 0x7f);
@@ -671,7 +672,8 @@ unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
 }
 
 static const unsigned char *
-unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
+unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
+              const unsigned char * end ATTRIBUTE_UNUSED)
 {
   int body = (code & 0x20) != 0;
   unw_word rlen;
@@ -682,33 +684,42 @@ unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
 }
 
 static const unsigned char *
-unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
+unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
+              const unsigned char * end)
 {
   unsigned char byte1, mask, grsave;
   unw_word rlen;
 
+  if ((end - dp) < 2)
+    {
+      printf (_("\t<corrupt R2>\n"));
+      return end;
+    }
+
   byte1 = *dp++;
 
   mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
   grsave = (byte1 & 0x7f);
-  rlen = unw_decode_uleb128 (& dp);
+  rlen = unw_decode_uleb128 (& dp, end);
   UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
   return dp;
 }
 
 static const unsigned char *
-unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
+unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
+              const unsigned char * end)
 {
   unw_word rlen;
 
-  rlen = unw_decode_uleb128 (& dp);
+  rlen = unw_decode_uleb128 (& dp, end);
   UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
   return dp;
 }
 
 static const unsigned char *
 unw_decode_p1 (const unsigned char *dp, unsigned int code,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED,
+              const unsigned char * end ATTRIBUTE_UNUSED)
 {
   unsigned char brmask = (code & 0x1f);
 
@@ -718,18 +729,35 @@ unw_decode_p1 (const unsigned char *dp, unsigned int code,
 
 static const unsigned char *
 unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
-                 void *arg ATTRIBUTE_UNUSED)
+                 void *arg ATTRIBUTE_UNUSED,
+                 const unsigned char * end)
 {
   if ((code & 0x10) == 0)
     {
-      unsigned char byte1 = *dp++;
+      unsigned char byte1;
+
+      if ((end - dp) < 1)
+       {
+         printf (_("\t<corrupt P2>\n"));
+         return end;
+       }
+
+      byte1 = *dp++;
 
       UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
                     (byte1 & 0x7f), arg);
     }
   else if ((code & 0x08) == 0)
     {
-      unsigned char byte1 = *dp++, r, dst;
+      unsigned char byte1, r, dst;
+
+      if ((end - dp) < 1)
+       {
+         printf (_("\t<corrupt P3>\n"));
+         return end;
+       }
+
+      byte1 = *dp++;
 
       r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
       dst = (byte1 & 0x7f);
@@ -777,11 +805,16 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
        }
     }
   else if ((code & 0x7) == 0)
-    UNW_DEC_SPILL_MASK ("P4", dp, arg);
+    UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
   else if ((code & 0x7) == 1)
     {
       unw_word grmask, frmask, byte1, byte2, byte3;
 
+      if ((end - dp) < 3)
+       {
+         printf (_("\t<corrupt P5>\n"));
+         return end;
+       }
       byte1 = *dp++;
       byte2 = *dp++;
       byte3 = *dp++;
@@ -797,7 +830,8 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
 
 static const unsigned char *
 unw_decode_p6 (const unsigned char *dp, unsigned int code,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED,
+              const unsigned char * end ATTRIBUTE_UNUSED)
 {
   int gregs = (code & 0x10) != 0;
   unsigned char mask = (code & 0x0f);
@@ -810,7 +844,8 @@ unw_decode_p6 (const unsigned char *dp, unsigned int code,
 }
 
 static const unsigned char *
-unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
+unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
+                  const unsigned char * end)
 {
   unsigned char r, byte1, byte2;
   unw_word t, size;
@@ -818,11 +853,11 @@ unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
   if ((code & 0x10) == 0)
     {
       r = (code & 0xf);
-      t = unw_decode_uleb128 (&dp);
+      t = unw_decode_uleb128 (&dp, end);
       switch (r)
        {
        case 0:
-         size = unw_decode_uleb128 (&dp);
+         size = unw_decode_uleb128 (&dp, end);
          UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
          break;
 
@@ -882,8 +917,14 @@ unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
        {
        case 0x0:               /* p8 */
          {
+           if ((end - dp) < 2)
+             {
+               printf (_("\t<corrupt P8>\n"));
+               return end;
+             }
+
            r = *dp++;
-           t = unw_decode_uleb128 (&dp);
+           t = unw_decode_uleb128 (&dp, end);
            switch (r)
              {
              case 1:
@@ -951,28 +992,40 @@ unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
          break;
 
        case 0x1:
+         if ((end - dp) < 2)
+           {
+             printf (_("\t<corrupt P9>\n"));
+             return end;
+           }
+
          byte1 = *dp++;
          byte2 = *dp++;
          UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
          break;
 
        case 0xf:               /* p10 */
+         if ((end - dp) < 2)
+           {
+             printf (_("\t<corrupt P10>\n"));
+             return end;
+           }
+
          byte1 = *dp++;
          byte2 = *dp++;
          UNW_DEC_ABI ("P10", byte1, byte2, arg);
          break;
 
        case 0x9:
-         return unw_decode_x1 (dp, code, arg);
+         return unw_decode_x1 (dp, code, arg, end);
 
        case 0xa:
-         return unw_decode_x2 (dp, code, arg);
+         return unw_decode_x2 (dp, code, arg, end);
 
        case 0xb:
-         return unw_decode_x3 (dp, code, arg);
+         return unw_decode_x3 (dp, code, arg, end);
 
        case 0xc:
-         return unw_decode_x4 (dp, code, arg);
+         return unw_decode_x4 (dp, code, arg, end);
 
        default:
          UNW_DEC_BAD_CODE (code);
@@ -984,7 +1037,8 @@ unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
 
 static const unsigned char *
 unw_decode_b1 (const unsigned char *dp, unsigned int code,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED,
+              const unsigned char * end ATTRIBUTE_UNUSED)
 {
   unw_word label = (code & 0x1f);
 
@@ -997,29 +1051,31 @@ unw_decode_b1 (const unsigned char *dp, unsigned int code,
 
 static const unsigned char *
 unw_decode_b2 (const unsigned char *dp, unsigned int code,
-              void *arg ATTRIBUTE_UNUSED)
+              void *arg ATTRIBUTE_UNUSED,
+              const unsigned char * end)
 {
   unw_word t;
 
-  t = unw_decode_uleb128 (& dp);
+  t = unw_decode_uleb128 (& dp, end);
   UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
   return dp;
 }
 
 static const unsigned char *
-unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
+unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
+                 const unsigned char * end)
 {
   unw_word t, ecount, label;
 
   if ((code & 0x10) == 0)
     {
-      t = unw_decode_uleb128 (&dp);
-      ecount = unw_decode_uleb128 (&dp);
+      t = unw_decode_uleb128 (&dp, end);
+      ecount = unw_decode_uleb128 (&dp, end);
       UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
     }
   else if ((code & 0x07) == 0)
     {
-      label = unw_decode_uleb128 (&dp);
+      label = unw_decode_uleb128 (&dp, end);
       if ((code & 0x08) != 0)
        UNW_DEC_COPY_STATE ("B4", label, arg);
       else
@@ -1029,13 +1085,13 @@ unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
     switch (code & 0x7)
       {
       case 1:
-       return unw_decode_x1 (dp, code, arg);
+       return unw_decode_x1 (dp, code, arg, end);
       case 2:
-       return unw_decode_x2 (dp, code, arg);
+       return unw_decode_x2 (dp, code, arg, end);
       case 3:
-       return unw_decode_x3 (dp, code, arg);
+       return unw_decode_x3 (dp, code, arg, end);
       case 4:
-       return unw_decode_x4 (dp, code, arg);
+       return unw_decode_x4 (dp, code, arg, end);
       default:
        UNW_DEC_BAD_CODE (code);
        break;
@@ -1044,7 +1100,7 @@ unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
 }
 
 typedef const unsigned char *(*unw_decoder)
-     (const unsigned char *, unsigned int, void *);
+  (const unsigned char *, unsigned int, void *, const unsigned char *);
 
 static const unw_decoder unw_decode_table[2][8] =
   {
@@ -1074,12 +1130,18 @@ static const unw_decoder unw_decode_table[2][8] =
 /* Decode one descriptor and return address of next descriptor.  */
 const unsigned char *
 unw_decode (const unsigned char *dp, int inside_body,
-           void *ptr_inside_body)
+           void *ptr_inside_body, const unsigned char * end)
 {
   unw_decoder decoder;
   unsigned char code;
 
+  if ((end - dp) < 1)
+    {
+      printf (_("\t<corrupt IA64 descriptor>\n"));
+      return end;
+    }
+
   code = *dp++;
   decoder = unw_decode_table[inside_body][code >> 5];
-  return (*decoder) (dp, code, ptr_inside_body);
+  return (*decoder) (dp, code, ptr_inside_body, end);
 }
This page took 0.030361 seconds and 4 git commands to generate.