[PATCH] readelf support for DW_END_default, DW_END_big, DW_END_little

Nick Clifton nickc@redhat.com
Wed Oct 11 11:09:00 GMT 2017


Hi Peeter,

> + * binutils/dwarf.c (read_and_display_attr_value): Handle
> + DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little

Thanks for submitting this patch.  There was a small problem in that
the code did not handle user specified endian values (ie in the range
0x40 - 0xff).

Whilst looking into this, I also noticed that there are some more DWARF
attributes whose values we do not decode (eg DW_AT_decimal_sign and
DW_AT_defaulted).  Plus there was no testcase for the encoding and 
decoding of these attributes.  So I have taken the liberty of extending
your patch to include these features and checked it in.

Cheers
  Nick

binutils/ChangeLog
2017-10-11  Peeter Joot  <peeter.joot@lzlabs.com>
	Nick Clifton  <nickc@redhat.com>

	* dwarf.c (read_and_display_attr_value): Handle DW_AT_endianity,
	DW_END_default, DW_END_big, DW_END_little, DW_ATE_UCS,
	DW_ATE_ASCII, DW_CC_pass_by_reference, DW_CC_pass_by_value,
	DW_CC_GNU_renesas_sh, DW_CC_GNU_borland_fastcall_i386,
	DW_AT_decimal_sign, DW_AT_defaulted, DW_AT_discr_list.
	(get_TAG_name): Report user generated tag values.
	* testsuite/binutils-all/dwarf-attributes.S: New test.
	* testsuite/binutils-all/dwarf-attributes.W. Expected output from
	readelf.
	* testsuite/binutils-all/readelf.exp: Run the new test.
-------------- next part --------------
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 2506d533b6..06702ef42d 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -963,13 +963,16 @@ process_abbrev_section (unsigned char *start, unsigned char *end)
 static const char *
 get_TAG_name (unsigned long tag)
 {
-  const char *name = get_DW_TAG_name ((unsigned int)tag);
+  const char *name = get_DW_TAG_name ((unsigned int) tag);
 
   if (name == NULL)
     {
       static char buffer[100];
 
-      snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag);
+      if (tag >= DW_TAG_lo_user && tag <= DW_TAG_hi_user)
+	snprintf (buffer, sizeof (buffer), _("User TAG value: %#lx"), tag);
+      else
+	snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %#lx"), tag);
       return buffer;
     }
 
@@ -2238,6 +2241,12 @@ read_and_display_attr_value (unsigned long attribute,
 	case DW_ATE_edited:		printf ("(edited)"); break;
 	case DW_ATE_signed_fixed:	printf ("(signed_fixed)"); break;
 	case DW_ATE_unsigned_fixed:	printf ("(unsigned_fixed)"); break;
+	  /* DWARF 4 values:  */
+	case DW_ATE_UTF:		printf ("(unicode string)"); break;
+	  /* DWARF 5 values:  */
+	case DW_ATE_UCS:		printf ("(UCS)"); break;
+	case DW_ATE_ASCII:		printf ("(ASCII)"); break;
+
 	  /* HP extensions:  */
 	case DW_ATE_HP_float80:		printf ("(HP_float80)"); break;
 	case DW_ATE_HP_complex_float80:	printf ("(HP_complex_float80)"); break;
@@ -2246,8 +2255,6 @@ read_and_display_attr_value (unsigned long attribute,
 	case DW_ATE_HP_floathpintel:	printf ("(HP_floathpintel)"); break;
 	case DW_ATE_HP_imaginary_float80:	printf ("(HP_imaginary_float80)"); break;
 	case DW_ATE_HP_imaginary_float128:	printf ("(HP_imaginary_float128)"); break;
-	  /* DWARF 4 values:  */
-	case DW_ATE_UTF:		printf ("(unicode string)"); break;
 
 	default:
 	  if (uvalue >= DW_ATE_lo_user
@@ -2283,6 +2290,22 @@ read_and_display_attr_value (unsigned long attribute,
 	}
       break;
 
+    case DW_AT_endianity:
+      printf ("\t");
+      switch (uvalue)
+	{
+	case DW_END_default:		printf ("(default)"); break;
+	case DW_END_big:		printf ("(big)"); break;
+	case DW_END_little:		printf ("(little)"); break;
+	default:
+	  if (uvalue >= DW_END_lo_user && uvalue <= DW_END_hi_user)
+	    printf (_("(user specified)"));
+	  else
+	    printf (_("(unknown endianity)"));
+	  break;
+	}
+      break;
+
     case DW_AT_virtuality:
       printf ("\t");
       switch (uvalue)
@@ -2313,6 +2336,10 @@ read_and_display_attr_value (unsigned long attribute,
 	case DW_CC_normal:	printf ("(normal)"); break;
 	case DW_CC_program:	printf ("(program)"); break;
 	case DW_CC_nocall:	printf ("(nocall)"); break;
+	case DW_CC_pass_by_reference: printf ("(pass by ref)"); break;
+	case DW_CC_pass_by_value: printf ("(pass by value)"); break;
+	case DW_CC_GNU_renesas_sh: printf ("(Rensas SH)"); break;
+	case DW_CC_GNU_borland_fastcall_i386: printf ("(Borland fastcall i386)"); break;
 	default:
 	  if (uvalue >= DW_CC_lo_user
 	      && uvalue <= DW_CC_hi_user)
@@ -2326,12 +2353,47 @@ read_and_display_attr_value (unsigned long attribute,
       printf ("\t");
       switch (uvalue)
 	{
+	case 255:
 	case -1: printf (_("(undefined)")); break;
 	case 0:  printf ("(row major)"); break;
 	case 1:  printf ("(column major)"); break;
 	}
       break;
 
+    case DW_AT_decimal_sign:
+      printf ("\t");
+      switch (uvalue)
+	{
+	case DW_DS_unsigned:            printf (_("(unsigned)")); break;
+	case DW_DS_leading_overpunch:   printf (_("(leading overpunch)")); break;
+	case DW_DS_trailing_overpunch:  printf (_("(trailing overpunch)")); break;
+	case DW_DS_leading_separate:    printf (_("(leading separate)")); break;
+	case DW_DS_trailing_separate:   printf (_("(trailing separate)")); break;
+	default:                        printf (_("(unrecognised)")); break;
+	}
+      break;
+
+    case DW_AT_defaulted:
+      printf ("\t");
+      switch (uvalue)
+	{
+	case DW_DEFAULTED_no:           printf (_("(no)")); break;
+	case DW_DEFAULTED_in_class:     printf (_("(in class)")); break;
+	case DW_DEFAULTED_out_of_class: printf (_("(out of class)")); break;
+	default:                        printf (_("(unrecognised)")); break;
+	}
+      break;
+
+    case DW_AT_discr_list:
+      printf ("\t");
+      switch (uvalue)
+	{
+	case DW_DSC_label:  printf (_("(label)")); break;
+	case DW_DSC_range:  printf (_("(range)")); break;
+	default:            printf (_("(unrecognised)")); break;
+	}
+      break;
+      
     case DW_AT_frame_base:
       have_frame_base = 1;
       /* Fall through.  */
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 81d1809225..10fd8d8da7 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -420,14 +420,15 @@ if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then {
     readelf_test {--decompress --hex-dump .debug_loc} $tempfile readelf.z  {}
 }
 
-# Skip the next test for the RISCV architectures because they do not
-# support .ULEB128 pseudo-ops with non-constant values.
+# Skip the next test for the RISCV architectures because they
+# do not support .ULEB128 pseudo-ops with non-constant values.
 if ![istarget "riscv*-*-*"] then {
 
     set hpux ""
     if [istarget "hppa*64*-*-hpux*"] {
 	set hpux "--defsym HPUX=1"
     }
+
     # Assemble the DWARF-5 test file.
     if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $hpux]} then {
 	unresolved "readelf -wiaoRlL dw5 (failed to assemble)"
@@ -447,3 +448,21 @@ if ![istarget "riscv*-*-*"] then {
 	readelf_test -wiaoRlL $tempfile dw5.W { nds32*-elf }
     }
 }
+
+# Assemble the DWARF-5 attributes test file.
+if {![binutils_assemble_flags $srcdir/$subdir/dwarf-attributes.S tmpdir/dwarf-attributes.o ""]} then {
+    unresolved "readelf -wi dwarf-attributes (failed to assemble)"
+} else {
+    # Download it.
+    if ![is_remote host] {
+	set tempfile tmpdir/dwarf-attributes.o
+    } else {
+	set tempfile [remote_download host tmpdir/dwarf-attributes.o]
+    }
+
+    # First, determine the size, so specific output matchers can be used.
+    readelf_find_size $tempfile
+
+    # Make sure that readelf can decode the contents.
+    readelf_test -wi $tempfile dwarf-attributes.W {}
+}


More information about the Binutils mailing list