Update support for GNU Build Attribute notes to include version 2 notes.
This commit is contained in:
parent
3ce2e142bc
commit
44c0bed7f3
@ -1646,3 +1646,338 @@ diff -rup binutils.orig/binutils/readelf.c binutils-2.28/binutils/readelf.c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
diff -rup binutils.orig/binutils/objcopy.c binutils-2.28/binutils/objcopy.c
|
||||||
|
--- binutils.orig/binutils/objcopy.c 2017-06-28 15:28:35.859154073 +0100
|
||||||
|
+++ binutils-2.28/binutils/objcopy.c 2017-06-28 15:33:35.093694480 +0100
|
||||||
|
@@ -1854,14 +1854,17 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
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. */
|
||||||
|
- pnote = pnotes = (Elf_Internal_Note *) xmalloc ((size / 12) * sizeof (Elf_Internal_Note));
|
||||||
|
+ pnote = pnotes = (Elf_Internal_Note *) xcalloc ((size / 12), sizeof (Elf_Internal_Note));
|
||||||
|
while (remain >= 12)
|
||||||
|
{
|
||||||
|
pnote->namesz = (bfd_get_32 (abfd, in ) + 3) & ~3;
|
||||||
|
@@ -1901,8 +1904,24 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
remain -= 12 + pnote->namesz + pnote->descsz;
|
||||||
|
in += 12 + pnote->namesz + pnote->descsz;
|
||||||
|
|
||||||
|
- if (pnote->namesz > 1 && pnote->namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION)
|
||||||
|
- ++ version_notes_seen;
|
||||||
|
+ if (pnote->namedata[pnote->namesz - 1] != 0)
|
||||||
|
+ {
|
||||||
|
+ err = _("corrupt GNU build attribute note: name not NUL terminated");
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ 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 ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1911,41 +1930,45 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
/* 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_1_seen == 0 && version_2_seen == 0)
|
||||||
|
+ {
|
||||||
|
+ err = _("bad GNU build attribute notes: no known versions detected");
|
||||||
|
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: 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.
|
||||||
|
3. Eliminate any NT_GNU_BUILD_ATTRIBUTE_OPEN notes that have the same
|
||||||
|
full name field as the immediately preceeding note with the same type
|
||||||
|
of name.
|
||||||
|
- 4. If an NT_GNU_BUILD_ATTRIBUTE_OPEN note is going to be preserved and
|
||||||
|
+ 4. Combine the numeric value of any NT_GNU_BUILD_ATTRIBUTE_OPEN notes
|
||||||
|
+ of type GNU_BUILD_ATTRIBUTE_STACK_SIZE.
|
||||||
|
+ 5. If an NT_GNU_BUILD_ATTRIBUTE_OPEN note is going to be preserved and
|
||||||
|
its description field is empty then the nearest preceeding OPEN note
|
||||||
|
with a non-empty description field must also be preserved *OR* the
|
||||||
|
description field of the note must be changed to contain the starting
|
||||||
|
@@ -1968,8 +1991,63 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
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[attribute_type_byte] == GNU_BUILD_ATTRIBUTE_STACK_SIZE)
|
||||||
|
+ {
|
||||||
|
+ unsigned char * name;
|
||||||
|
+ unsigned long note_val;
|
||||||
|
+ unsigned long back_val;
|
||||||
|
+ unsigned int shift;
|
||||||
|
+ unsigned int bytes;
|
||||||
|
+ unsigned long byte;
|
||||||
|
+
|
||||||
|
+ 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 - 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 - val_start)
|
||||||
|
+ {
|
||||||
|
+ /* We have a problem - the new value requires more bytes of
|
||||||
|
+ storage in the name field than are available. Currently
|
||||||
|
+ we have no way of fixing this, so we just preserve both
|
||||||
|
+ notes. */
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Write the new val into back. */
|
||||||
|
+ name = (unsigned char *) back->namedata + val_start;
|
||||||
|
+ while (name < (unsigned char *) back->namedata + back->namesz)
|
||||||
|
+ {
|
||||||
|
+ byte = back_val & 0xff;
|
||||||
|
+ * name ++ = byte;
|
||||||
|
+ if (back_val == 0)
|
||||||
|
+ break;
|
||||||
|
+ back_val >>= 8;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ duplicate_found = TRUE;
|
||||||
|
+ pnote->type = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (back->namesz == pnote->namesz
|
||||||
|
&& memcmp (back->namedata, pnote->namedata, back->namesz) == 0)
|
||||||
|
{
|
||||||
|
@@ -1979,11 +2057,12 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have found an attribute match then stop searching backwards. */
|
||||||
|
- if (! ISPRINT (back->namedata[1])
|
||||||
|
- || strcmp (back->namedata + 2, pnote->namedata + 2) == 0)
|
||||||
|
+ if (! ISPRINT (back->namedata[attribute_type_byte])
|
||||||
|
+ /* Names are NUL terminated, so this is safe. */
|
||||||
|
+ || 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 note. If so
|
||||||
|
+ description refers back to an earlier OPEN version note. If so
|
||||||
|
then we must make sure that version note is also preserved. */
|
||||||
|
if (pnote->descsz == 0
|
||||||
|
&& prev_open != NULL
|
||||||
|
@@ -2067,15 +2146,18 @@ merge_gnu_build_notes (bfd * abfd, asect
|
||||||
|
|
||||||
|
if (relcount > 0)
|
||||||
|
{
|
||||||
|
- arelent ** rel;
|
||||||
|
+ arelent **rel = relpp;
|
||||||
|
|
||||||
|
- for (rel = relpp; rel < relpp + relcount; rel ++)
|
||||||
|
- if ((* rel)->howto == NULL)
|
||||||
|
+ while (rel < relpp + relcount)
|
||||||
|
+ if ((*rel)->howto != NULL)
|
||||||
|
+ rel++;
|
||||||
|
+ else
|
||||||
|
{
|
||||||
|
/* Delete eliminated relocs.
|
||||||
|
FIXME: There are better ways to do this. */
|
||||||
|
- memmove (rel, rel + 1, ((relcount - (rel - relpp)) - 1) * sizeof (* rel));
|
||||||
|
- relcount --;
|
||||||
|
+ memmove (rel, rel + 1,
|
||||||
|
+ ((relcount - (rel - relpp)) - 1) * sizeof (*rel));
|
||||||
|
+ relcount--;
|
||||||
|
}
|
||||||
|
bfd_set_reloc (abfd, sec, relpp, relcount);
|
||||||
|
}
|
||||||
|
diff -rup binutils.orig/binutils/readelf.c binutils-2.28/binutils/readelf.c
|
||||||
|
--- binutils.orig/binutils/readelf.c 2017-06-28 15:28:35.868153969 +0100
|
||||||
|
+++ binutils-2.28/binutils/readelf.c 2017-06-28 15:35:01.500695487 +0100
|
||||||
|
@@ -16517,7 +16517,7 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
const char * expected_types;
|
||||||
|
const char * name = pnote->namedata;
|
||||||
|
const char * text;
|
||||||
|
- int left;
|
||||||
|
+ signed int left;
|
||||||
|
|
||||||
|
if (name == NULL || pnote->namesz < 2)
|
||||||
|
{
|
||||||
|
@@ -16526,6 +16526,16 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
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:
|
||||||
|
@@ -16533,6 +16543,7 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
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);
|
||||||
|
@@ -16540,7 +16551,6 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- left = 19;
|
||||||
|
++ name;
|
||||||
|
text = NULL;
|
||||||
|
|
||||||
|
@@ -16586,7 +16596,6 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
expected_types = bool_expected;
|
||||||
|
++ name;
|
||||||
|
break;
|
||||||
|
-
|
||||||
|
default:
|
||||||
|
if (ISPRINT (* name))
|
||||||
|
{
|
||||||
|
@@ -16601,6 +16610,7 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static char tmpbuf [128];
|
||||||
|
+
|
||||||
|
error (_("unrecognised byte in name field: %d\n"), * name);
|
||||||
|
sprintf (tmpbuf, _("<unknown:_%d>"), * name);
|
||||||
|
text = tmpbuf;
|
||||||
|
@@ -16611,10 +16621,7 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
@@ -16634,10 +16641,10 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
{
|
||||||
|
case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
|
||||||
|
{
|
||||||
|
- unsigned int bytes;
|
||||||
|
- unsigned long long val = 0;
|
||||||
|
- unsigned int shift = 0;
|
||||||
|
- char * decoded = NULL;
|
||||||
|
+ unsigned int bytes;
|
||||||
|
+ unsigned long long val = 0;
|
||||||
|
+ unsigned int shift = 0;
|
||||||
|
+ char * decoded = NULL;
|
||||||
|
|
||||||
|
bytes = pnote->namesz - (name - pnote->namedata);
|
||||||
|
if (bytes > 0)
|
||||||
|
@@ -16735,6 +16742,7 @@ print_gnu_build_attribute_name (Elf_Inte
|
||||||
|
I.E. the value of namesz for the name "FSF" is 4.
|
||||||
|
|
||||||
|
If the value of namesz is zero, there is no name present. */
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
process_note (Elf_Internal_Note * pnote,
|
||||||
|
FILE * file)
|
||||||
|
--- fred/binutils/objcopy.c 2017-06-28 15:39:09.627826773 +0100
|
||||||
|
+++ binutils-2.28/binutils/objcopy.c 2017-06-28 15:39:29.117601441 +0100
|
||||||
|
@@ -1844,6 +1844,22 @@ copy_unknown_object (bfd *ibfd, bfd *obf
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Returns the number of bytes needed to store VAL. */
|
||||||
|
+
|
||||||
|
+static inline unsigned int
|
||||||
|
+num_bytes (unsigned long val)
|
||||||
|
+{
|
||||||
|
+ unsigned int count = 0;
|
||||||
|
+
|
||||||
|
+ /* FIXME: There must be a faster way to do this. */
|
||||||
|
+ while (val)
|
||||||
|
+ {
|
||||||
|
+ count ++;
|
||||||
|
+ val >>= 8;
|
||||||
|
+ }
|
||||||
|
+ return count;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Merge the notes on SEC, removing redundant entries.
|
||||||
|
Returns the new, smaller size of the section upon success. */
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
Summary: A GNU collection of binary utilities
|
Summary: A GNU collection of binary utilities
|
||||||
Name: %{?cross}binutils%{?_with_debug:-debug}
|
Name: %{?cross}binutils%{?_with_debug:-debug}
|
||||||
Version: 2.28
|
Version: 2.28
|
||||||
Release: 9%{?dist}
|
Release: 10%{?dist}
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
Group: Development/Tools
|
Group: Development/Tools
|
||||||
URL: http://sources.redhat.com/binutils
|
URL: http://sources.redhat.com/binutils
|
||||||
@ -602,6 +602,9 @@ exit 0
|
|||||||
%endif # %{isnative}
|
%endif # %{isnative}
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Jun 28 2017 Nick Clifton <nickc@redhat.com> 2.28-10
|
||||||
|
- Update support for GNU Build Attribute notes to include version 2 notes.
|
||||||
|
|
||||||
* Thu Jun 15 2017 Nick Clifton <nickc@redhat.com> 2.28-9
|
* Thu Jun 15 2017 Nick Clifton <nickc@redhat.com> 2.28-9
|
||||||
- Update patch to fix AArch64 copy reloc generation.
|
- Update patch to fix AArch64 copy reloc generation.
|
||||||
(#1452170)
|
(#1452170)
|
||||||
|
Loading…
Reference in New Issue
Block a user