This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add support for version 2 of the GNU Build Attribute note specification.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=88305e1b9f4592a2ab129015ce409fcc16613ebb

commit 88305e1b9f4592a2ab129015ce409fcc16613ebb
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Jun 28 14:52:12 2017 +0100

    Add support for version 2 of the GNU Build Attribute note specification.
    
    	* objcopy.c (merge_gnu_build_notes): Add support for version 2 notes.
    	* readelf.c (print_gnu_build_attribute_name): Likewise.

Diff:
---
 binutils/ChangeLog |  5 ++++
 binutils/objcopy.c | 68 ++++++++++++++++++++++++++++++++++++------------------
 binutils/readelf.c | 22 ++++++++++++------
 3 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index da3cf67..c5b8f19 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2017-06-28  Nick Clifton  <nickc@redhat.com>
+
+	* objcopy.c (merge_gnu_build_notes): Add support for version 2 notes.
+	* readelf.c (print_gnu_build_attribute_name): Likewise.
+
 2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
 	    Matthew Fortune  <matthew.fortune@imgtec.com>
 
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 42c7775..4f48190 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -1915,10 +1915,13 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
   Elf_Internal_Note * pnotes;
   Elf_Internal_Note * pnote;
   bfd_size_type       remain = size;
-  unsigned            version_notes_seen = 0;
+  unsigned            version_1_seen = 0;
+  unsigned            version_2_seen = 0;
   bfd_boolean         duplicate_found = FALSE;
   const char *        err = NULL;
   bfd_byte *          in = contents;
+  int                 attribute_type_byte;
+  int                 val_start;
 
   /* Make a copy of the notes.
      Minimum size of a note is 12 bytes.  */
@@ -1968,8 +1971,18 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
 	  goto done;
 	}
       
-      if (pnote->namesz > 1 && pnote->namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION)
-	++ version_notes_seen;
+      if (pnote->namesz > 2
+	  && pnote->namedata[0] == '$'
+	  && pnote->namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION
+	  && pnote->namedata[2] == '1')
+	++ version_1_seen;
+      else if (pnote->namesz > 4
+	  && pnote->namedata[0] == 'G'
+	  && pnote->namedata[1] == 'A'
+	  && pnote->namedata[2] == '$'
+	  && pnote->namedata[3] == GNU_BUILD_ATTRIBUTE_VERSION
+	  && pnote->namedata[4] == '2')
+	++ version_2_seen;
       pnote ++;
     }
 
@@ -1978,34 +1991,36 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
   /* Check that the notes are valid.  */
   if (remain != 0)
     {
-      err = _("corrupt GNU build attribute notes: data at end");
+      err = _("corrupt GNU build attribute notes: excess data at end");
       goto done;
     }
 
-  if (version_notes_seen == 0)
+  if (version_1_seen == 0 && version_2_seen == 0)
     {
-      err = _("bad GNU build attribute notes: no version note");
+      err = _("bad GNU build attribute notes: no known versions detected");
+      goto done;
+    }
+
+  if (version_1_seen > 0 && version_2_seen > 0)
+    {
+      err = _("bad GNU build attribute notes: multiple different versions");
       goto done;
     }
 
   /* Merging is only needed if there is more than one version note...  */
-  if (version_notes_seen == 1)
+  if (version_1_seen == 1 || version_2_seen == 1)
     goto done;
 
+  attribute_type_byte = version_1_seen ? 1 : 3;
+  val_start = attribute_type_byte + 1;
+
   /* The first note should be the first version note.  */
-  if (pnotes[0].namedata[1] != GNU_BUILD_ATTRIBUTE_VERSION)
+  if (pnotes[0].namedata[attribute_type_byte] != GNU_BUILD_ATTRIBUTE_VERSION)
     {
       err = _("bad GNU build attribute notes: first note not version note");
       goto done;
     }
 
-  if (pnotes[0].namedata[0] != GNU_BUILD_ATTRIBUTE_TYPE_STRING
-      || pnotes[0].namedata[2] != '1')
-    {
-      err = _("bad GNU build attribute notes: version note not v1");
-      goto done;
-    }
-
   /* Now merge the notes.  The rules are:
      1. Preserve the ordering of the notes.
      2. Preserve any NT_GNU_BUILD_ATTRIBUTE_FUNC notes.
@@ -2037,9 +2052,9 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
 	    prev_open = back;
 
 	  if (back->type == pnote->type
-	      && back->namedata[1] == pnote->namedata[1])
+	      && back->namedata[attribute_type_byte] == pnote->namedata[attribute_type_byte])
 	    {
-	      if (back->namedata[1] == GNU_BUILD_ATTRIBUTE_STACK_SIZE)
+	      if (back->namedata[attribute_type_byte] == GNU_BUILD_ATTRIBUTE_STACK_SIZE)
 		{
 		  unsigned char * name;
 		  unsigned long   note_val;
@@ -2048,22 +2063,28 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
 		  unsigned int    bytes;
 		  unsigned long   byte;
 
-		  for (shift = 0, note_val = 0, bytes = pnote->namesz - 2, name = (unsigned char *) pnote->namedata + 2;
+		  for (shift = 0, note_val = 0,
+			 bytes = pnote->namesz - val_start,
+			 name = (unsigned char *) pnote->namedata + val_start;
 		       bytes--;)
 		    {
 		      byte = (* name ++) & 0xff;
 		      note_val |= byte << shift;
 		      shift += 8;
 		    }
-		  for (shift = 0, back_val = 0, bytes = back->namesz - 2, name = (unsigned char *) back->namedata + 2;
+
+		  for (shift = 0, back_val = 0,
+			 bytes = back->namesz - val_start,
+			 name = (unsigned char *) back->namedata + val_start;
 		       bytes--;)
 		    {
 		      byte = (* name ++) & 0xff;
 		      back_val |= byte << shift;
 		      shift += 8;
 		    }
+
 		  back_val += note_val;
-		  if (num_bytes (back_val) >= back->namesz - 2)
+		  if (num_bytes (back_val) >= back->namesz - val_start)
 		    {
 		      /* We have a problem - the new value requires more bytes of
 			 storage in the name field than are available.  Currently
@@ -2071,8 +2092,9 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
 			 notes.  */
 		      continue;
 		    }
+
 		  /* Write the new val into back.  */
-		  name = (unsigned char *) back->namedata + 2;
+		  name = (unsigned char *) back->namedata + val_start;
 		  while (name < (unsigned char *) back->namedata + back->namesz)
 		    {
 		      byte = back_val & 0xff;
@@ -2096,9 +2118,9 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte
 		}
 
 	      /* If we have found an attribute match then stop searching backwards.  */
-	      if (! ISPRINT (back->namedata[1])
+	      if (! ISPRINT (back->namedata[attribute_type_byte])
 		  /* Names are NUL terminated, so this is safe.  */
-		  || strcmp (back->namedata + 2, pnote->namedata + 2) == 0)
+		  || strcmp (back->namedata + val_start, pnote->namedata + val_start) == 0)
 		{
 		  /* Since we are keeping this note we must check to see if its
 		     description refers back to an earlier OPEN version note.  If so
diff --git a/binutils/readelf.c b/binutils/readelf.c
index edfe652..df7e8c3 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -481,7 +481,7 @@ print_symbol (signed int width, const char *symbol)
 
   if (width < 0)
     {
-      /* Keep the width positive.  This also helps.  */
+      /* Keep the width positive.  This helps the code below.  */
       width = - width;
       extra_padding = TRUE;
     }
@@ -17185,7 +17185,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
   const char * expected_types;
   const char * name = pnote->namedata;
   const char * text;
-  int          left;
+  signed int   left;
 
   if (name == NULL || pnote->namesz < 2)
     {
@@ -17194,6 +17194,16 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
+  left = 20;
+
+  /* Version 2 of the spec adds a "GA" prefix to the name field.  */
+  if (name[0] == 'G' && name[1] == 'A')
+    {
+      printf ("GA");
+      name += 2;
+      left -= 2;
+    }
+
   switch ((name_type = * name))
     {
     case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
@@ -17201,6 +17211,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
     case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
       printf ("%c", * name);
+      left --;
       break;
     default:
       error (_("unrecognised attribute type in name field: %d\n"), name_type);
@@ -17208,7 +17219,6 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
-  left = 19;
   ++ name;
   text = NULL;
 
@@ -17268,6 +17278,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       else
 	{
 	  static char tmpbuf [128];
+
 	  error (_("unrecognised byte in name field: %d\n"), * name);
 	  sprintf (tmpbuf, _("<unknown:_%d>"), * name);
 	  text = tmpbuf;
@@ -17278,10 +17289,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     }
 
   if (text)
-    {
-      printf ("%s", text);
-      left -= strlen (text);
-    }
+    left -= printf ("%s", text);
 
   if (strchr (expected_types, name_type) == NULL)
     warn (_("attribute does not have an expected type (%c)\n"), name_type);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]