gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / unwind-ia64.c
index e98f9d349431cf822f60ec92293db4fe314d9b6a..b9eae5bb21d468873a932bf86e257a906662415e 100644 (file)
@@ -1,5 +1,5 @@
 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
-   Copyright (C) 2000-2018 Free Software Foundation, Inc.
+   Copyright (C) 2000-2020 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                                                                           \
@@ -360,7 +359,7 @@ typedef bfd_vma unw_word;
       /* PR 18420.  */                                                 \
       if ((dp + (unw_rlen / 4)) > end)                                 \
        {                                                               \
-         printf ("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n",\
+         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;                                                        \
@@ -542,38 +541,57 @@ typedef bfd_vma unw_word;
  */
 
 static unw_word
-unw_decode_uleb128 (const unsigned char **dpp)
+unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end)
 {
   unsigned shift = 0;
+  int status = 1;
   unw_word byte, result = 0;
   const unsigned char *bp = *dpp;
 
-  while (1)
+  while (bp < end)
     {
       byte = *bp++;
-      result |= (byte & 0x7f) << shift;
+      if (shift < sizeof (result) * 8)
+       {
+         result |= (byte & 0x7f) << shift;
+         if ((result >> shift) != (byte & 0x7f))
+           /* Overflow.  */
+           status |= 2;
+         shift += 7;
+       }
+      else if ((byte & 0x7f) != 0)
+       status |= 2;
 
       if ((byte & 0x80) == 0)
-       break;
-
-      shift += 7;
+       {
+         status &= ~1;
+         break;
+       }
     }
 
   *dpp = bp;
+  if (status != 0)
+    printf (_("Bad uleb128\n"));
 
   return result;
 }
 
 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);
@@ -584,14 +602,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;
@@ -604,15 +628,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);
@@ -626,15 +656,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);
@@ -662,27 +698,33 @@ 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,
-              const unsigned char * end ATTRIBUTE_UNUSED)
+              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,
-              const unsigned char * end ATTRIBUTE_UNUSED)
+              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;
 }
@@ -705,14 +747,30 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
 {
   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);
@@ -765,6 +823,11 @@ unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
     {
       unw_word grmask, frmask, byte1, byte2, byte3;
 
+      if ((end - dp) < 3)
+       {
+         printf (_("\t<corrupt P5>\n"));
+         return end;
+       }
       byte1 = *dp++;
       byte2 = *dp++;
       byte3 = *dp++;
@@ -795,7 +858,7 @@ 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,
-                  const unsigned char * end ATTRIBUTE_UNUSED)
+                  const unsigned char * end)
 {
   unsigned char r, byte1, byte2;
   unw_word t, size;
@@ -803,11 +866,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;
 
@@ -867,8 +930,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:
@@ -936,28 +1005,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,30 +1065,30 @@ 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,
-              const unsigned char * end 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,
-                 const unsigned char * end ATTRIBUTE_UNUSED)
+                 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
@@ -1017,13 +1098,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;
@@ -1067,6 +1148,12 @@ unw_decode (const unsigned char *dp, int inside_body,
   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, end);
This page took 0.028568 seconds and 4 git commands to generate.