diff options
author | Nick Clifton <nickc@redhat.com> | 2017-06-28 14:52:12 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2017-06-28 14:52:12 +0100 |
commit | 88305e1b9f4592a2ab129015ce409fcc16613ebb (patch) | |
tree | b5d5a5cfc8e893ba455d66ba5008474e43091ff0 /binutils/objcopy.c | |
parent | 65a55fbbd949868f7df3c65d39eb8d4455515132 (diff) | |
download | gdb-88305e1b9f4592a2ab129015ce409fcc16613ebb.zip gdb-88305e1b9f4592a2ab129015ce409fcc16613ebb.tar.gz gdb-88305e1b9f4592a2ab129015ce409fcc16613ebb.tar.bz2 |
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.
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r-- | binutils/objcopy.c | 68 |
1 files changed, 45 insertions, 23 deletions
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 |