[patch] Fix DWARF dumping code to handle DW_OP_const2u correctly

Cary Coutant ccoutant@google.com
Tue May 14 21:38:00 GMT 2013


The SAFE_BYTE_GET patch broke DW_OP_const2u, but reading 1 byte
instead of 2. I also found a case where SAFE_BYTE_GET64 was
incorrectly testing for end-of-buffer, and incrementing the pointer
only in the overflow condition. Also, because we can now call byte_get
and signed_byte_get with any size between 1 and 8, I've added cases
for 5, 6, and 7.

OK for trunk?

-cary


2013-05-14  Cary Coutant  <ccoutant@google.com>

binutils/
        * dwarf.c (SAFE_BYTE_GET64): Correct end-of-buffer check;
        don't increment PTR.
        (decode_location_expression): DW_OP_const2u should read 2 bytes.
        (display_debug_lines_decoded): Adjust formatting.
        * elfcomm.c (byte_get_little_endian): Add cases for 5-, 6-, and
        7-byte reads.
        (byte_get_big_endian): Likewise.
        (byte_get_signed): Likewise.
-------------- next part --------------
2013-05-14  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (SAFE_BYTE_GET64): Correct end-of-buffer check;
	don't increment PTR.
	(decode_location_expression): DW_OP_const2u should read 2 bytes.
	(display_debug_lines_decoded): Adjust formatting.
	* elfcomm.c (byte_get_little_endian): Add cases for 5-, 6-, and
	7-byte reads.
	(byte_get_big_endian): Likewise.
	(byte_get_signed): Likewise.


diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 774904c..862a060 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -337,13 +337,12 @@ read_uleb128 (unsigned char * data,
 #define SAFE_BYTE_GET64(PTR, HIGH, LOW, END)		\
   do							\
     {							\
-      if (((PTR) + 8) < (END))				\
+      if (((PTR) + 8) <= (END))				\
 	{						\
 	  byte_get_64 ((PTR), (HIGH), (LOW));		\
 	}						\
       else						\
 	{						\
-	  PTR = END;					\
 	  * (LOW) = * (HIGH) = 0;			\
 	}						\
     }							\
@@ -883,7 +882,7 @@ decode_location_expression (unsigned char * data,
 	  printf ("DW_OP_const1s: %ld", (long) svalue);
 	  break;
 	case DW_OP_const2u:
-	  SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+	  SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
 	  printf ("DW_OP_const2u: %lu", (unsigned long) uvalue);
 	  break;
 	case DW_OP_const2s:
@@ -3184,7 +3183,8 @@ display_debug_lines_decoded (struct dwarf_section *section,
 			 break;
 		       case DW_LNE_set_address:
 			 SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
-						op_code_data, ext_op_code_len - bytes_read - 1,
+						op_code_data,
+						ext_op_code_len - bytes_read - 1,
 						end);
 			 state_machine_regs.op_index = 0;
 			 break;
diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c
index 1a1fae9..d5b4313 100644
--- a/binutils/elfcomm.c
+++ b/binutils/elfcomm.c
@@ -150,6 +150,57 @@ byte_get_little_endian (unsigned char *field, int size)
 	|    (((unsigned long) (field[2])) << 16)
 	|    (((unsigned long) (field[3])) << 24);
 
+    case 5:
+      if (sizeof (elf_vma) == 8)
+	return  ((elf_vma) (field[0]))
+	  |    (((elf_vma) (field[1])) << 8)
+	  |    (((elf_vma) (field[2])) << 16)
+	  |    (((elf_vma) (field[3])) << 24)
+	  |    (((elf_vma) (field[4])) << 32);
+      else if (sizeof (elf_vma) == 4)
+	/* We want to extract data from an 8 byte wide field and
+	   place it into a 4 byte wide field.  Since this is a little
+	   endian source we can just use the 4 byte extraction code.  */
+	return  ((unsigned long) (field[0]))
+	  |    (((unsigned long) (field[1])) << 8)
+	  |    (((unsigned long) (field[2])) << 16)
+	  |    (((unsigned long) (field[3])) << 24);
+
+    case 6:
+      if (sizeof (elf_vma) == 8)
+	return  ((elf_vma) (field[0]))
+	  |    (((elf_vma) (field[1])) << 8)
+	  |    (((elf_vma) (field[2])) << 16)
+	  |    (((elf_vma) (field[3])) << 24)
+	  |    (((elf_vma) (field[4])) << 32)
+	  |    (((elf_vma) (field[5])) << 40);
+      else if (sizeof (elf_vma) == 4)
+	/* We want to extract data from an 8 byte wide field and
+	   place it into a 4 byte wide field.  Since this is a little
+	   endian source we can just use the 4 byte extraction code.  */
+	return  ((unsigned long) (field[0]))
+	  |    (((unsigned long) (field[1])) << 8)
+	  |    (((unsigned long) (field[2])) << 16)
+	  |    (((unsigned long) (field[3])) << 24);
+
+    case 7:
+      if (sizeof (elf_vma) == 8)
+	return  ((elf_vma) (field[0]))
+	  |    (((elf_vma) (field[1])) << 8)
+	  |    (((elf_vma) (field[2])) << 16)
+	  |    (((elf_vma) (field[3])) << 24)
+	  |    (((elf_vma) (field[4])) << 32)
+	  |    (((elf_vma) (field[5])) << 40)
+	  |    (((elf_vma) (field[6])) << 48);
+      else if (sizeof (elf_vma) == 4)
+	/* We want to extract data from an 8 byte wide field and
+	   place it into a 4 byte wide field.  Since this is a little
+	   endian source we can just use the 4 byte extraction code.  */
+	return  ((unsigned long) (field[0]))
+	  |    (((unsigned long) (field[1])) << 8)
+	  |    (((unsigned long) (field[2])) << 16)
+	  |    (((unsigned long) (field[3])) << 24);
+
     case 8:
       if (sizeof (elf_vma) == 8)
 	return  ((elf_vma) (field[0]))
@@ -197,6 +248,63 @@ byte_get_big_endian (unsigned char *field, int size)
 	|   (((unsigned long) (field[1])) << 16)
 	|   (((unsigned long) (field[0])) << 24);
 
+    case 5:
+      if (sizeof (elf_vma) == 8)
+	return ((elf_vma) (field[4]))
+	  |   (((elf_vma) (field[3])) << 8)
+	  |   (((elf_vma) (field[2])) << 16)
+	  |   (((elf_vma) (field[1])) << 24)
+	  |   (((elf_vma) (field[0])) << 32);
+      else if (sizeof (elf_vma) == 4)
+	{
+	  /* Although we are extracting data from an 8 byte wide field,
+	     we are returning only 4 bytes of data.  */
+	  field += 1;
+	  return ((unsigned long) (field[3]))
+	    |   (((unsigned long) (field[2])) << 8)
+	    |   (((unsigned long) (field[1])) << 16)
+	    |   (((unsigned long) (field[0])) << 24);
+	}
+
+    case 6:
+      if (sizeof (elf_vma) == 8)
+	return ((elf_vma) (field[5]))
+	  |   (((elf_vma) (field[4])) << 8)
+	  |   (((elf_vma) (field[3])) << 16)
+	  |   (((elf_vma) (field[2])) << 24)
+	  |   (((elf_vma) (field[1])) << 32)
+	  |   (((elf_vma) (field[0])) << 40);
+      else if (sizeof (elf_vma) == 4)
+	{
+	  /* Although we are extracting data from an 8 byte wide field,
+	     we are returning only 4 bytes of data.  */
+	  field += 2;
+	  return ((unsigned long) (field[3]))
+	    |   (((unsigned long) (field[2])) << 8)
+	    |   (((unsigned long) (field[1])) << 16)
+	    |   (((unsigned long) (field[0])) << 24);
+	}
+
+    case 7:
+      if (sizeof (elf_vma) == 8)
+	return ((elf_vma) (field[6]))
+	  |   (((elf_vma) (field[5])) << 8)
+	  |   (((elf_vma) (field[4])) << 16)
+	  |   (((elf_vma) (field[3])) << 24)
+	  |   (((elf_vma) (field[2])) << 32)
+	  |   (((elf_vma) (field[1])) << 40)
+	  |   (((elf_vma) (field[0])) << 48);
+      else if (sizeof (elf_vma) == 4)
+	{
+	  /* Although we are extracting data from an 8 byte wide field,
+	     we are returning only 4 bytes of data.  */
+	  field += 3;
+	  return ((unsigned long) (field[3]))
+	    |   (((unsigned long) (field[2])) << 8)
+	    |   (((unsigned long) (field[1])) << 16)
+	    |   (((unsigned long) (field[0])) << 24);
+	}
+
     case 8:
       if (sizeof (elf_vma) == 8)
 	return ((elf_vma) (field[7]))
@@ -209,7 +317,7 @@ byte_get_big_endian (unsigned char *field, int size)
 	  |   (((elf_vma) (field[0])) << 56);
       else if (sizeof (elf_vma) == 4)
 	{
-	  /* Although we are extracing data from an 8 byte wide field,
+	  /* Although we are extracting data from an 8 byte wide field,
 	     we are returning only 4 bytes of data.  */
 	  field += 4;
 	  return ((unsigned long) (field[3]))
@@ -235,9 +343,18 @@ byte_get_signed (unsigned char *field, int size)
       return (x ^ 0x80) - 0x80;
     case 2:
       return (x ^ 0x8000) - 0x8000;
+    case 3:
+      return (x ^ 0x800000) - 0x800000;
     case 4:
       return (x ^ 0x80000000) - 0x80000000;
+    case 5:
+    case 6:
+    case 7:
     case 8:
+      /* Reads of 5-, 6-, and 7-byte numbers are the result of
+         trying to read past the end of a buffer, and will therefore
+         not have meaningful values, so we don't try to deal with
+         the sign in these cases.  */
       return x;
     default:
       abort ();


More information about the Binutils mailing list