diff -rup binutils.orig/binutils/objcopy.c binutils-2.29.1/binutils/objcopy.c --- binutils.orig/binutils/objcopy.c 2018-01-03 16:06:45.005657092 +0000 +++ binutils-2.29.1/binutils/objcopy.c 2018-01-03 16:06:57.927502748 +0000 @@ -1905,84 +1905,229 @@ num_bytes (unsigned long val) return count; } +typedef struct objcopy_internal_note +{ + Elf_Internal_Note note; + bfd_vma start; + bfd_vma end; + bfd_boolean modified; +} objcopy_internal_note; + +/* Returns TRUE if a gap does, or could, exist between the address range + covered by PNOTE1 and PNOTE2. */ + +static bfd_boolean +gap_exists (objcopy_internal_note * pnote1, + objcopy_internal_note * pnote2) +{ + /* Without range end notes, we assume that a gap might exist. */ + if (pnote1->end == 0 || pnote2->end == 0) + return TRUE; + + /* FIXME: Alignment of 16 bytes taken from x86_64 binaries. + Really we should extract the alignment of the section covered by the notes. */ + return BFD_ALIGN (pnote1->end, 16) < pnote2->start; +} + +static bfd_boolean +is_open_note (objcopy_internal_note * pnote) +{ + return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_OPEN); +} + +static bfd_boolean +is_func_note (objcopy_internal_note * pnote) +{ + return (pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_FUNC); +} + +static bfd_boolean +is_64bit (bfd * abfd) +{ + /* Should never happen, but let's be paranoid. */ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return FALSE; + + return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64; +} + /* Merge the notes on SEC, removing redundant entries. Returns the new, smaller size of the section upon success. */ static bfd_size_type merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte * contents) { - Elf_Internal_Note * pnotes_end; - Elf_Internal_Note * pnotes; - Elf_Internal_Note * pnote; + objcopy_internal_note * pnotes_end; + objcopy_internal_note * pnotes = NULL; + objcopy_internal_note * pnote; bfd_size_type remain = size; unsigned version_1_seen = 0; unsigned version_2_seen = 0; + unsigned version_3_seen = 0; bfd_boolean duplicate_found = FALSE; const char * err = NULL; bfd_byte * in = contents; int attribute_type_byte; int val_start; + unsigned long previous_func_start = 0; + unsigned long previous_open_start = 0; + unsigned long previous_func_end = 0; + unsigned long previous_open_end = 0; + long relsize; + - /* Make a copy of the notes. + relsize = bfd_get_reloc_upper_bound (abfd, sec); + if (relsize > 0) + { + arelent ** relpp; + long relcount; + + /* If there are relocs associated with this section then we + cannot safely merge it. */ + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, sec, relpp, isympp); + free (relpp); + if (relcount != 0) + goto done; + } + + /* Make a copy of the notes and convert to our internal format. Minimum size of a note is 12 bytes. */ - pnote = pnotes = (Elf_Internal_Note *) xcalloc ((size / 12), sizeof (Elf_Internal_Note)); + pnote = pnotes = (objcopy_internal_note *) xcalloc ((size / 12), sizeof (* pnote)); while (remain >= 12) { - pnote->namesz = (bfd_get_32 (abfd, in ) + 3) & ~3; - pnote->descsz = (bfd_get_32 (abfd, in + 4) + 3) & ~3; - pnote->type = bfd_get_32 (abfd, in + 8); + bfd_vma start, end; - if (pnote->type != NT_GNU_BUILD_ATTRIBUTE_OPEN - && pnote->type != NT_GNU_BUILD_ATTRIBUTE_FUNC) + pnote->note.namesz = (bfd_get_32 (abfd, in ) + 3) & ~3; + pnote->note.descsz = (bfd_get_32 (abfd, in + 4) + 3) & ~3; + pnote->note.type = bfd_get_32 (abfd, in + 8); + + if (pnote->note.type != NT_GNU_BUILD_ATTRIBUTE_OPEN + && pnote->note.type != NT_GNU_BUILD_ATTRIBUTE_FUNC) { err = _("corrupt GNU build attribute note: wrong note type"); goto done; } - if (pnote->namesz + pnote->descsz + 12 > remain) + if (pnote->note.namesz + pnote->note.descsz + 12 > remain) { err = _("corrupt GNU build attribute note: note too big"); goto done; } - if (pnote->namesz < 2) + if (pnote->note.namesz < 2) { err = _("corrupt GNU build attribute note: name too small"); goto done; } - if (pnote->descsz != 0 - && pnote->descsz != 4 - && pnote->descsz != 8) + pnote->note.namedata = (char *)(in + 12); + pnote->note.descdata = (char *)(in + 12 + pnote->note.namesz); + + remain -= 12 + pnote->note.namesz + pnote->note.descsz; + in += 12 + pnote->note.namesz + pnote->note.descsz; + + if (pnote->note.namesz > 2 + && pnote->note.namedata[0] == '$' + && pnote->note.namedata[1] == GNU_BUILD_ATTRIBUTE_VERSION + && pnote->note.namedata[2] == '1') + ++ version_1_seen; + else if (pnote->note.namesz > 4 + && pnote->note.namedata[0] == 'G' + && pnote->note.namedata[1] == 'A' + && pnote->note.namedata[2] == '$' + && pnote->note.namedata[3] == GNU_BUILD_ATTRIBUTE_VERSION) { + if (pnote->note.namedata[4] == '2') + ++ version_2_seen; + else if (pnote->note.namedata[4] == '3') + ++ version_3_seen; + else + { + err = _("corrupt GNU build attribute note: unsupported version"); + goto done; + } + } + + switch (pnote->note.descsz) + { + case 0: + start = end = 0; + break; + + case 4: + start = bfd_get_32 (abfd, pnote->note.descdata); + /* FIXME: For version 1 and 2 notes we should try to + calculate the end address by finding a symbol whose + value is START, and then adding in its size. + + For now though, since v1 and v2 was not intended to + handle gaps, we chose an artificially large end + address. */ + end = 0x7ffffffffffffffUL; + break; + + case 8: + if (! is_64bit (abfd)) + { + start = bfd_get_32 (abfd, pnote->note.descdata); + end = bfd_get_32 (abfd, pnote->note.descdata + 4); + } + else + { + start = bfd_get_64 (abfd, pnote->note.descdata); + /* FIXME: For version 1 and 2 notes we should try to + calculate the end address by finding a symbol whose + value is START, and then adding in its size. + + For now though, since v1 and v2 was not intended to + handle gaps, we chose an artificially large end + address. */ + end = 0x7ffffffffffffffUL; + } + break; + + case 16: + start = bfd_get_64 (abfd, pnote->note.descdata); + end = bfd_get_64 (abfd, pnote->note.descdata + 8); + break; + + default: err = _("corrupt GNU build attribute note: bad description size"); goto done; } - pnote->namedata = (char *)(in + 12); - pnote->descdata = (char *)(in + 12 + pnote->namesz); + if (is_open_note (pnote)) + { + if (start) + previous_open_start = start; + + pnote->start = previous_open_start; - remain -= 12 + pnote->namesz + pnote->descsz; - in += 12 + pnote->namesz + pnote->descsz; + if (end) + previous_open_end = end; - if (pnote->namedata[pnote->namesz - 1] != 0) + pnote->end = previous_open_end; + } + else + { + if (start) + previous_func_start = start; + + pnote->start = previous_func_start; + + if (end) + previous_func_end = end; + + pnote->end = previous_func_end; + } + + if (pnote->note.namedata[pnote->note.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 ++; } @@ -1995,27 +2140,29 @@ merge_gnu_build_notes (bfd * abfd, asect goto done; } - if (version_1_seen == 0 && version_2_seen == 0) + if (version_1_seen == 0 && version_2_seen == 0 && version_3_seen == 0) { err = _("bad GNU build attribute notes: no known versions detected"); goto done; } - if (version_1_seen > 0 && version_2_seen > 0) + if ((version_1_seen > 0 && version_2_seen > 0) + || (version_1_seen > 0 && version_3_seen > 0) + || (version_2_seen > 0 && version_3_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_1_seen == 1 || version_2_seen == 1) + if (version_1_seen == 1 || version_2_seen == 1 || version_3_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[attribute_type_byte] != GNU_BUILD_ATTRIBUTE_VERSION) + if (pnotes[0].note.namedata[attribute_type_byte] != GNU_BUILD_ATTRIBUTE_VERSION) { err = _("bad GNU build attribute notes: first note not version note"); goto done; @@ -2026,7 +2173,9 @@ merge_gnu_build_notes (bfd * abfd, asect 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. + of name and whose address ranges coincide. + IE - it there are gaps in the coverage of the notes, then these gaps + must be preserved. 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 @@ -2036,103 +2185,134 @@ merge_gnu_build_notes (bfd * abfd, asect address to which it refers. */ for (pnote = pnotes + 1; pnote < pnotes_end; pnote ++) { - Elf_Internal_Note * back; - Elf_Internal_Note * prev_open = NULL; + int note_type; + objcopy_internal_note * back; + objcopy_internal_note * prev_open_with_range = NULL; - if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC) + /* Rule 2 - preserve function notes. */ + if (! is_open_note (pnote)) continue; - /* Scan for duplicates. Clear the type field of any found - but do not - delete them just yet. */ + note_type = pnote->note.namedata[attribute_type_byte]; + + /* Scan backwards from pnote, looking for duplicates. + Clear the type field of any found - but do not delete them just yet. */ for (back = pnote - 1; back >= pnotes; back --) { - if (back->descsz > 0 - && back->type != NT_GNU_BUILD_ATTRIBUTE_FUNC - && prev_open == NULL) - prev_open = back; + int back_type = back->note.namedata[attribute_type_byte]; + + /* If this is the first open note with an address + range that we have encountered then record it. */ + if (prev_open_with_range == NULL + && back->note.descsz > 0 + && ! is_func_note (back)) + prev_open_with_range = back; + + if (! is_open_note (back)) + continue; + + /* If the two notes are different then keep on searching. */ + if (back_type != note_type) + continue; - if (back->type == pnote->type - && back->namedata[attribute_type_byte] == pnote->namedata[attribute_type_byte]) + /* Rule 4 - combine stack size notes. */ + if (back_type == GNU_BUILD_ATTRIBUTE_STACK_SIZE) { - 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->note.namesz - val_start, + name = (unsigned char *) pnote->note.namedata + val_start; + bytes--;) { - 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; + byte = (* name ++) & 0xff; + note_val |= byte << shift; + shift += 8; } - - if (back->namesz == pnote->namesz - && memcmp (back->namedata, pnote->namedata, back->namesz) == 0) + + for (shift = 0, back_val = 0, + bytes = back->note.namesz - val_start, + name = (unsigned char *) back->note.namedata + val_start; + bytes--;) { - duplicate_found = TRUE; - pnote->type = 0; - break; + byte = (* name ++) & 0xff; + back_val |= byte << shift; + shift += 8; } - /* If we have found an attribute match then stop searching backwards. */ - 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) + back_val += note_val; + if (num_bytes (back_val) >= back->note.namesz - val_start) { - /* Since we are keeping this note we must check to see if its - 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 - && prev_open->type == 0) - prev_open->type = NT_GNU_BUILD_ATTRIBUTE_FUNC; + /* 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; + } - break; + /* Write the new val into back. */ + name = (unsigned char *) back->note.namedata + val_start; + while (name < (unsigned char *) back->note.namedata + + back->note.namesz) + { + byte = back_val & 0xff; + * name ++ = byte; + if (back_val == 0) + break; + back_val >>= 8; } + + duplicate_found = TRUE; + pnote->note.type = 0; + break; + } + + /* Rule 3 - combine identical open notes. */ + if (back->note.namesz == pnote->note.namesz + && memcmp (back->note.namedata, + pnote->note.namedata, back->note.namesz) == 0 + && ! gap_exists (back, pnote)) + { + duplicate_found = TRUE; + pnote->note.type = 0; + + if (pnote->end > back->end) + back->end = pnote->end; + + if (version_3_seen) + back->modified = TRUE; + break; } + + /* Rule 5 - Since we are keeping this note we must check to see + if its description refers back to an earlier OPEN version + note that has been scheduled for deletion. If so then we + must make sure that version note is also preserved. */ + if (version_3_seen) + { + /* As of version 3 we can just + move the range into the note. */ + pnote->modified = TRUE; + pnote->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC; + back->modified = TRUE; + back->note.type = NT_GNU_BUILD_ATTRIBUTE_FUNC; + } + else + { + if (pnote->note.descsz == 0 + && prev_open_with_range != NULL + && prev_open_with_range->note.type == 0) + prev_open_with_range->note.type = NT_GNU_BUILD_ATTRIBUTE_OPEN; + } + + /* We have found a similar attribute but the details do not match. + Stop searching backwards. */ + break; } } @@ -2142,22 +2322,8 @@ merge_gnu_build_notes (bfd * abfd, asect bfd_byte * old; bfd_byte * new; bfd_size_type new_size; - arelent ** relpp = NULL; - long relsize; - long relcount = 0; - - relsize = bfd_get_reloc_upper_bound (abfd, sec); - if (relsize > 0) - { - /* If there are relocs associated with this section then we may - have to adjust them as well, as we remove notes. */ - relpp = (arelent **) xmalloc (relsize); - relcount = bfd_canonicalize_reloc (abfd, sec, relpp, isympp); - if (relcount < 0) - /* Do not bother complaining here - copy_relocations_in_section - will do that for us. */ - relcount = 0; - } + bfd_vma prev_start = 0; + bfd_vma prev_end = 0; /* Eliminate the duplicates. */ new = new_contents = xmalloc (size); @@ -2165,36 +2331,52 @@ merge_gnu_build_notes (bfd * abfd, asect pnote < pnotes_end; pnote ++) { - bfd_size_type note_size = 12 + pnote->namesz + pnote->descsz; + bfd_size_type note_size = 12 + pnote->note.namesz + pnote->note.descsz; - if (pnote->type == 0) + if (pnote->note.type != 0) { - if (relcount > 0) + if (pnote->modified) { - arelent ** rel; - - /* If there is a reloc at the current offset, delete it. - Adjust the location of any relocs above the current - location downwards by the size of the note being deleted. - FIXME: We could optimize this loop by retaining a pointer to - the last reloc below the current note. */ - for (rel = relpp; rel < relpp + relcount; rel ++) + /* If the note has been modified then we must copy it by + hand, potentially adding in a new description field. */ + if (pnote->start == prev_start && pnote->end == prev_end) { - if ((* rel)->howto == NULL) - continue; - if ((* rel)->address < (bfd_vma) (new - new_contents)) - continue; - if ((* rel)->address >= (bfd_vma) ((new + note_size) - new_contents)) - (* rel)->address -= note_size; + bfd_put_32 (abfd, pnote->note.namesz, new); + bfd_put_32 (abfd, 0, new + 4); + bfd_put_32 (abfd, pnote->note.type, new + 8); + new += 12; + memcpy (new, pnote->note.namedata, pnote->note.namesz); + new += pnote->note.namesz; + } + else + { + bfd_put_32 (abfd, pnote->note.namesz, new); + bfd_put_32 (abfd, is_64bit (abfd) ? 16 : 8, new + 4); + bfd_put_32 (abfd, pnote->note.type, new + 8); + new += 12; + memcpy (new, pnote->note.namedata, pnote->note.namesz); + new += pnote->note.namesz; + if (is_64bit (abfd)) + { + bfd_put_64 (abfd, pnote->start, new); + bfd_put_64 (abfd, pnote->end, new + 8); + new += 16; + } else - (* rel)->howto = NULL; + { + bfd_put_32 (abfd, pnote->start, new); + bfd_put_32 (abfd, pnote->end, new + 4); + new += 8; + } } } - } - else - { - memcpy (new, old, note_size); - new += note_size; + else + { + memcpy (new, old, note_size); + new += note_size; + } + prev_start = pnote->start; + prev_end = pnote->end; } old += note_size; @@ -2204,24 +2386,6 @@ merge_gnu_build_notes (bfd * abfd, asect memcpy (contents, new_contents, new_size); size = new_size; free (new_contents); - - if (relcount > 0) - { - arelent **rel = relpp; - - 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--; - } - bfd_set_reloc (abfd, sec, relpp, relcount); - } } done: diff -rup binutils.orig/binutils/readelf.c binutils-2.29.1/binutils/readelf.c --- binutils.orig/binutils/readelf.c 2018-01-03 16:06:45.005657092 +0000 +++ binutils-2.29.1/binutils/readelf.c 2018-01-03 16:28:24.417115970 +0000 @@ -16247,9 +16247,9 @@ get_note_type (unsigned e_type) case NT_ARCH: return _("NT_ARCH (architecture)"); case NT_GNU_BUILD_ATTRIBUTE_OPEN: - return _("NT_GNU_BUILD_ATTRIBUTE_OPEN"); + return _("OPEN"); case NT_GNU_BUILD_ATTRIBUTE_FUNC: - return _("NT_GNU_BUILD_ATTRIBUTE_FUNC"); + return _("func"); default: break; } @@ -17064,13 +17064,16 @@ print_ia64_vms_note (Elf_Internal_Note * return TRUE; } -/* Print the name of the symbol associated with a build attribute - that is attached to address OFFSET. */ - -static bfd_boolean -print_symbol_for_build_attribute (FILE * file, - unsigned long offset, - bfd_boolean is_open_attr) +/* Find the symbol associated with a build attribute that is attached + to address OFFSET. If PNAME is non-NULL then store the name of + the symbol (if found) in the provided pointer, Returns NULL if a + symbol could not be found. */ + +static Elf_Internal_Sym * +get_symbol_for_build_attribute (FILE * file, + unsigned long offset, + bfd_boolean is_open_attr, + const char ** pname) { static FILE * saved_file = NULL; static char * strtab; @@ -17109,10 +17112,7 @@ print_symbol_for_build_attribute (FILE * } if (symtab == NULL || strtab == NULL) - { - printf ("\n"); - return FALSE; - } + return NULL; /* Find a symbol whose value matches offset. */ for (sym = symtab; sym < symtab + nsyms; sym ++) @@ -17132,14 +17132,15 @@ print_symbol_for_build_attribute (FILE * FUNC symbols entirely. */ switch (ELF_ST_TYPE (sym->st_info)) { - case STT_FILE: - saved_sym = sym; - /* We can stop searching now. */ - sym = symtab + nsyms; - continue; - case STT_OBJECT: + case STT_FILE: saved_sym = sym; + if (sym->st_size) + { + /* If the symbol has a size associated + with it then we can stop searching. */ + sym = symtab + nsyms; + } continue; case STT_FUNC: @@ -17177,55 +17178,118 @@ print_symbol_for_build_attribute (FILE * } } - printf (" (%s: %s)\n", - is_open_attr ? _("file") : _("func"), - saved_sym ? strtab + saved_sym->st_name : _(")")); - return TRUE; + if (saved_sym && pname) + * pname = strtab + saved_sym->st_name; + + return saved_sym; } static bfd_boolean print_gnu_build_attribute_description (Elf_Internal_Note * pnote, FILE * file) { - static unsigned long global_offset = 0; - unsigned long offset; - unsigned int desc_size = is_32bit_elf ? 4 : 8; - bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN; - - if (pnote->descsz == 0) - { + static unsigned long global_offset = 0; + static unsigned long global_end = 0; + static unsigned long func_offset = 0; + static unsigned long func_end = 0; + + Elf_Internal_Sym * sym; + const char * name; + unsigned long start; + unsigned long end; + bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN; + + switch (pnote->descsz) + { + case 0: + /* A zero-length description means that the range of + the previous note of the same type should be used. */ if (is_open_attr) { - printf (_(" Applies from offset %#lx\n"), global_offset); - return TRUE; + if (global_end > global_offset) + printf (_(" Applies to region from %#lx to %#lx\n"), + global_offset, global_end); + else + printf (_(" Applies to region from %#lx\n"), global_offset); } else { - printf (_(" Applies to func at %#lx"), global_offset); - return print_symbol_for_build_attribute (file, global_offset, is_open_attr); + if (func_end > func_offset) + printf (_(" Applies to region from %#lx to %#lx\n"), func_offset, func_end); + else + printf (_(" Applies to region from %#lx\n"), func_offset); } - } + return TRUE; - if (pnote->descsz != desc_size) - { + case 4: + start = byte_get ((unsigned char *) pnote->descdata, 4); + end = 0; + break; + + case 8: + if (is_32bit_elf) + { + /* FIXME: We should check that version 3+ notes are being used here... */ + start = byte_get ((unsigned char *) pnote->descdata, 4); + end = byte_get ((unsigned char *) pnote->descdata + 4, 4); + } + else + { + start = byte_get ((unsigned char *) pnote->descdata, 8); + end = 0; + } + break; + + case 16: + start = byte_get ((unsigned char *) pnote->descdata, 8); + end = byte_get ((unsigned char *) pnote->descdata + 8, 8); + break; + + default: error (_(" \n"), pnote->descsz); printf (_(" ")); return FALSE; } - offset = byte_get ((unsigned char *) pnote->descdata, desc_size); + name = NULL; + sym = get_symbol_for_build_attribute (file, start, is_open_attr, & name); + + if (end == 0 && sym != NULL && sym->st_size > 0) + end = start + sym->st_size; if (is_open_attr) { - printf (_(" Applies from offset %#lx"), offset); - global_offset = offset; + /* FIXME: Need to properly allow for section alignment. 16 is just the alignment used on x86_64. */ + if (global_end > 0 && start > BFD_ALIGN (global_end, 16)) + warn (_("Gap in build notes detected from %#lx to %#lx\n"), + global_end + 1, start - 1); + + printf (_(" Applies to region from %#lx"), start); + global_offset = start; + + if (end) + { + printf (_(" to %#lx"), end); + global_end = end; + } } else { - printf (_(" Applies to func at %#lx"), offset); + printf (_(" Applies to region from %#lx"), start); + func_offset = start; + + if (end) + { + printf (_(" to %#lx"), end); + func_end = end; + } } - return print_symbol_for_build_attribute (file, offset, is_open_attr); + if (sym && name) + printf (_(" (%s)"), name); + + printf ("\n"); + return TRUE; } static bfd_boolean @@ -17248,11 +17312,21 @@ print_gnu_build_attribute_name (Elf_Inte return FALSE; } - left = 20; + if (do_wide) + left = 28; + else + left = 20; /* Version 2 of the spec adds a "GA" prefix to the name field. */ if (name[0] == 'G' && name[1] == 'A') { + if (pnote->namesz < 4) + { + error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz); + print_symbol (-20, _(" ")); + return FALSE; + } + printf ("GA"); name += 2; left -= 2; diff -rup binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r.d binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r.d --- binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r.d 2018-01-03 16:06:45.013656996 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r.d 2018-01-03 16:06:57.927502748 +0000 @@ -5,7 +5,5 @@ #as: -32 #source: ../note-2-32.s -Relocation section '\.rel\.gnu\.build\.attributes' at offset .* contains 2 entries: - Offset Info Type Sym\.Value Sym\. Name -00000010 ......02 R_MIPS_32 00000100 note1\.s -0000006c ......02 R_MIPS_32 00000104 note2\.s +There are no relocations in this file. +#... diff -rup binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r-n32.d binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r-n32.d --- binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r-n32.d 2018-01-03 16:06:45.014656984 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r-n32.d 2018-01-03 16:06:57.927502748 +0000 @@ -5,7 +5,5 @@ #as: -n32 -mips3 #source: ../note-2-32.s -Relocation section '\.rela\.gnu\.build\.attributes' at offset .* contains 2 entries: - Offset Info Type Sym\.Value Sym\. Name \+ Addend -00000010 ......02 R_MIPS_32 00000100 note1\.s \+ 0 -0000006c ......02 R_MIPS_32 00000104 note2\.s \+ 0 +There are no relocations in this file. +#... diff -rup binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r-n64.d binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r-n64.d --- binutils.orig/binutils/testsuite/binutils-all/mips/mips-note-2r-n64.d 2018-01-03 16:06:45.014656984 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/mips/mips-note-2r-n64.d 2018-01-03 16:06:57.927502748 +0000 @@ -5,11 +5,5 @@ #as: -64 -mips3 #source: ../note-2-64.s -Relocation section '\.rela\.gnu\.build\.attributes' at offset .* contains 2 entries: - Offset Info Type Sym\. Value Sym\. Name \+ Addend -000000000010 ....00000012 R_MIPS_64 0000000000000100 note1\.s \+ 0 - Type2: R_MIPS_NONE - Type3: R_MIPS_NONE -000000000070 ....00000012 R_MIPS_64 0000000000000104 note2\.s \+ 0 - Type2: R_MIPS_NONE - Type3: R_MIPS_NONE +There are no relocations in this file. +#... diff -rup binutils.orig/binutils/testsuite/binutils-all/note-2-32.d binutils-2.29.1/binutils/testsuite/binutils-all/note-2-32.d --- binutils.orig/binutils/testsuite/binutils-all/note-2-32.d 2018-01-03 16:06:45.013656996 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-2-32.d 2018-01-03 16:06:57.927502748 +0000 @@ -6,12 +6,12 @@ #... Owner Data size Description -[ ]+\$1[ ]+0x00000004[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 \(file: note1.s\) -[ ]+\$gcc 7.0.1[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\+true[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\*static[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\*0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\$1[ ]+0x00000004[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. \(file: note2.s\) -[ ]+!false[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. -[ ]+\*pic[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[ ]+Applies to func at 0x10. \(func: func1\) +[ ]+\$1[ ]+0x00000004[ ]+OPEN[ ]+Applies to region from 0x100 \(note1.s\) +[ ]+\$gcc 7.0.1[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\+true[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\*static[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\*0x0[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\$1[ ]+0x00000004[ ]+OPEN[ ]+Applies to region from 0x104 \(note2.s\) +[ ]+!false[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x104 +[ ]+\*pic[ ]+0x00000004[ ]+func[ ]+Applies to region from 0x104 \(func1\) #... diff -rup binutils.orig/binutils/testsuite/binutils-all/note-2-32.s binutils-2.29.1/binutils/testsuite/binutils-all/note-2-32.s --- binutils.orig/binutils/testsuite/binutils-all/note-2-32.s 2018-01-03 16:06:45.010657032 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-2-32.s 2018-01-03 16:06:57.927502748 +0000 @@ -2,7 +2,7 @@ .org 0x100 .global note1.s note1.s: - .word 0 + .dc.l 0 .pushsection .gnu.build.attributes, "0x100000", %note .balign 4 @@ -10,7 +10,7 @@ note1.s: .dc.l 4 .dc.l 0x100 .asciz "$1" - .dc.l note1.s + .dc.l 0x100 .dc.l 12 .dc.l 0 @@ -39,14 +39,14 @@ note1.s: note2.s: .type func1, STT_FUNC func1: - .word 0x100 + .dc.l 0x100 .pushsection .gnu.build.attributes, "0x100000", %note .dc.l 4 .dc.l 4 .dc.l 0x100 .asciz "$1" - .dc.l note2.s + .dc.l 0x104 .dc.l 12 .dc.l 0 @@ -60,26 +60,28 @@ func1: .dc.b 0 .dc.l 4 - .dc.l 0 + .dc.l 4 .dc.l 0x101 .dc.b 0x2a, 0x7, 1, 0 - + .dc.l 0x104 + .dc.l 4 .dc.l 0 .dc.l 0x100 .dc.b 0x2a, 0x6, 0, 0 .popsection + .global note3.s note3.s: - .word 0x100 + .dc.l 0x100 .pushsection .gnu.build.attributes, "0x100000", %note .dc.l 4 .dc.l 4 .dc.l 0x100 .asciz "$1" - .dc.l note3.s + .dc.l 0x108 .dc.l 12 .dc.l 0 diff -rup binutils.orig/binutils/testsuite/binutils-all/note-2-64.d binutils-2.29.1/binutils/testsuite/binutils-all/note-2-64.d --- binutils.orig/binutils/testsuite/binutils-all/note-2-64.d 2018-01-03 16:06:45.010657032 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-2-64.d 2018-01-03 16:06:57.927502748 +0000 @@ -6,12 +6,12 @@ #... Owner Data size Description -[ ]+\$1[ ]+0x00000008[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 \(file: note1.s\) -[ ]+\$gcc 7.0.1[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\+true[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\*static[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\*0x0[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x100 -[ ]+\$1[ ]+0x00000008[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. \(file: note2.s\) -[ ]+!false[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_OPEN[ ]+Applies from offset 0x10. -[ ]+\*pic[ ]+0x00000000[ ]+NT_GNU_BUILD_ATTRIBUTE_FUNC[ ]+Applies to func at 0x10. \(func: func1\) +[ ]+\$1[ ]+0x00000008[ ]+OPEN[ ]+Applies to region from 0x100 \(note1.s\) +[ ]+\$gcc 7.0.1[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\+true[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\*static[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\*0x0[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 +[ ]+\$1[ ]+0x00000008[ ]+OPEN[ ]+Applies to region from 0x104 \(note2.s\) +[ ]+!false[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x104 +[ ]+\*pic[ ]+0x00000008[ ]+func[ ]+Applies to region from 0x104 \(func1\) #... diff -rup binutils.orig/binutils/testsuite/binutils-all/note-2-64.s binutils-2.29.1/binutils/testsuite/binutils-all/note-2-64.s --- binutils.orig/binutils/testsuite/binutils-all/note-2-64.s 2018-01-03 16:06:45.014656984 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-2-64.s 2018-01-03 16:06:57.927502748 +0000 @@ -2,7 +2,7 @@ .org 0x100 .global note1.s note1.s: - .word 0 + .dc.l 0 .pushsection .gnu.build.attributes, "0x100000", %note .balign 4 @@ -10,7 +10,7 @@ note1.s: .dc.l 8 .dc.l 0x100 .asciz "$1" - .8byte note1.s + .8byte 0x100 .dc.l 12 .dc.l 0 @@ -40,14 +40,14 @@ note2.s: .global func1 .type func1, STT_FUNC func1: - .word 0x100 + .dc.l 0x100 .pushsection .gnu.build.attributes, "0x100000", %note .dc.l 4 .dc.l 8 .dc.l 0x100 .asciz "$1" - .8byte note2.s + .8byte 0x104 .dc.l 12 .dc.l 0 @@ -61,9 +61,10 @@ func1: .dc.b 0 .dc.l 4 - .dc.l 0 + .dc.l 8 .dc.l 0x101 .dc.b 0x2a, 0x7, 1, 0 + .8byte 0x104 .dc.l 4 .dc.l 0 @@ -74,14 +75,14 @@ func1: .global note3.s note3.s: - .word 0x100 + .dc.l 0x100 .pushsection .gnu.build.attributes, "0x100000", %note .dc.l 4 .dc.l 8 .dc.l 0x100 .asciz "$1" - .8byte note3.s + .8byte 0x108 .dc.l 12 .dc.l 0 diff -rup binutils.orig/binutils/testsuite/binutils-all/objcopy.exp binutils-2.29.1/binutils/testsuite/binutils-all/objcopy.exp --- binutils.orig/binutils/testsuite/binutils-all/objcopy.exp 2018-01-03 16:06:45.013656996 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/objcopy.exp 2018-01-03 16:21:05.682365371 +0000 @@ -1056,8 +1056,10 @@ if [is_elf_format] { run_dump_test "note-1" if [is_elf64 tmpdir/bintest.o] { run_dump_test "note-2-64" + run_dump_test "note-4-64" } else { run_dump_test "note-2-32" + run_dump_test "note-4-32" } } --- /dev/null 2018-01-03 08:45:19.457895336 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-4-32.s 2018-01-03 16:36:13.314505682 +0000 @@ -0,0 +1,74 @@ + .text + .org 0x100 +note_4.s: + .dc.l 0 + .dc.l 0 + + .type bar, STT_FUNC +bar: + .dc.l 0 +bar_end: + .dc.l 0 +note_4.s_end: + + .pushsection .gnu.build.attributes, "", %note + .balign 4 + + .dc.l 8 + .dc.l 8 + .dc.l 0x100 + .asciz "GA$3p3" + .dc.l note_4.s + .dc.l note_4.s_end + + .dc.l 23 + .dc.l 0 + .dc.l 0x100 + .asciz "GA$gcc 7.2.1 20170915" + .dc.b 0 + + .dc.l 10 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0 + .dc.b 0, 0 + + .dc.l 6 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0 + .dc.b 0, 0 + + .dc.l 13 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0 + .dc.b 0, 0, 0 + + .dc.l 6 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0 + .dc.b 0, 0 + + .dc.l 5 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x21, 0x8, 0 + .dc.b 0, 0, 0 + + .dc.l 13 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0 + .dc.b 0, 0, 0 + + .dc.l 6 + .dc.l 8 + .dc.l 0x101 + .dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0 + .dc.b 0, 0 + .dc.l bar + .dc.l bar_end + + .popsection --- /dev/null 2018-01-03 08:45:19.457895336 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-4-32.d 2018-01-03 16:36:13.313505694 +0000 @@ -0,0 +1,19 @@ +#PROG: objcopy +#readelf: --notes --wide +#objcopy: --merge-notes +#name: v3 gnu build attribute notes (32-bit) +#source: note-4-32.s + +#... +Displaying notes found in: .gnu.build.attributes +[ ]+Owner[ ]+Data size[ ]+Description +[ ]+GA\$3p3[ ]+0x00000008[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 \(note_4.s\) +[ ]+GA\$gcc 7.2.1 20170915[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*GOW:0x700[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*off[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*FORTIFY:0xff[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*PIC[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\!false[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*0x[0-9a-f]+[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x110 +[ ]+GA\*strong[ ]+0x00000008[ ]+func[ ]+Applies to region from 0x108 to 0x10c.* +#... --- /dev/null 2018-01-03 08:45:19.457895336 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-4-64.s 2018-01-03 16:36:07.041580738 +0000 @@ -0,0 +1,78 @@ + .text + .org 0x100 +note_4.s: + .dc.l 0 + .dc.l 0 + .dc.l 0 + .dc.l 0 + + .type bar, @function +bar: + .dc.l 0 + .dc.l 0 + .dc.l 0 +bar_end: + .dc.l 0 +note_4.s_end: + + .pushsection .gnu.build.attributes, "", %note + .balign 4 + + .dc.l 8 + .dc.l 16 + .dc.l 0x100 + .asciz "GA$3p3" + .8byte note_4.s + .8byte note_4.s_end + + .dc.l 23 + .dc.l 0 + .dc.l 0x100 + .asciz "GA$gcc 7.2.1 20170915" + .dc.b 0 + + .dc.l 10 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x47, 0x4f, 0x57, 0, 0, 0x7, 0 + .dc.b 0, 0 + + .dc.l 6 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x2, 0, 0 + .dc.b 0, 0 + + .dc.l 13 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x46, 0x4f, 0x52, 0x54, 0x49, 0x46, 0x59, 0, 0xff, 0 + .dc.b 0, 0, 0 + + .dc.l 6 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x7, 0x2, 0 + .dc.b 0, 0 + + .dc.l 5 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x21, 0x8, 0 + .dc.b 0, 0, 0 + + .dc.l 13 + .dc.l 0 + .dc.l 0x100 + .dc.b 0x47, 0x41, 0x2a, 0x6, 0xf2, 0x3, 0x38, 0xee, 0xce, 0xfa, 0x5e, 0x3c, 0 + .dc.b 0, 0, 0 + + .dc.l 6 + .dc.l 16 + .dc.l 0x101 + .dc.b 0x47, 0x41, 0x2a, 0x2, 0x3, 0 + .dc.b 0, 0 + .8byte bar + .8byte bar_end + + .popsection --- /dev/null 2018-01-03 08:45:19.457895336 +0000 +++ binutils-2.29.1/binutils/testsuite/binutils-all/note-4-64.d 2018-01-03 16:36:07.041580738 +0000 @@ -0,0 +1,19 @@ +#PROG: objcopy +#readelf: --notes --wide +#objcopy: --merge-notes +#name: v3 gnu build attribute notes (64-bit) +#source: note-4-64.s + +#... +Displaying notes found in: .gnu.build.attributes +[ ]+Owner[ ]+Data size[ ]+Description +[ ]+GA\$3p3[ ]+0x00000010[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 \(note_4.s\) +[ ]+GA\$gcc 7.2.1 20170915[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*GOW:0x700[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*off[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*FORTIFY:0xff[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*PIC[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\!false[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*0x[0-9a-f]+[ ]+0x00000000[ ]+OPEN[ ]+Applies to region from 0x100 to 0x120 +[ ]+GA\*strong[ ]+0x00000010[ ]+func[ ]+Applies to region from 0x110 to 0x11c.* +#...