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.
This commit is contained in:
parent
65a55fbbd9
commit
88305e1b9f
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user