aboutsummaryrefslogtreecommitdiff
path: root/binutils/objcopy.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2018-01-03 10:28:33 +0000
committerNick Clifton <nickc@redhat.com>2018-01-03 10:30:07 +0000
commit6f156d7a4ad1c245b357dc50f63f3564d397839e (patch)
treea247aad883eb6ba6eeb0c9715c218527fc25c869 /binutils/objcopy.c
parent9f757bf7fcb8834ead780e0c4a76d6029b1402c2 (diff)
downloadgdb-6f156d7a4ad1c245b357dc50f63f3564d397839e.zip
gdb-6f156d7a4ad1c245b357dc50f63f3564d397839e.tar.gz
gdb-6f156d7a4ad1c245b357dc50f63f3564d397839e.tar.bz2
Add support for v3 binary annotation notes.
I am checking in the attached patch which updates the binutils support for version 3 binary annotation notes. (Version 3 adds an end address to the ranges covered by the notes, so that it is possible to detect gaps in the coverage). This patch also stops the note merging feature of objcopy from executing if the notes have relocations against them. This makes the code simpler, and prevents the problems with architectures which have unusual relocation management issues. * objcopy.c (objcopy_internal_note): New structure. (gap_exists): New function. (is_open_note): New function. (is_func_note): New function. (is_64bit): New function. (merge_gnu_build_notes): Handle v3 notes. Do not merge if there are relocations against the notes. * readelf.c (get_note_type): Use short names for build attribute notes. (print_symbol_for_build_attribute): Rename to get_symbol_for_build_attribute. Returns the found symbol rather than printing it. (print_gnu_build_attribute_description): Maintain address ranges for function notes as well as global notes. Handle v3 notes. (print_gnu_build_attribute_name): Use more space for printing the name in wide mode. * testsuite/binutils-all/note-2-32.s: Use .dc.l instead of .word. Eliminate symbol references in order to remove the need for relocations. * testsuite/binutils-all/note-2-64.s: Likewise. * testsuite/binutils-all/note-3-32.s: Add a size to the note_1 symbol. * testsuite/binutils-all/note-3-64.s: Likewise. * testsuite/binutils-all/mips/mips-note-2r-n32.d: Update expected output. * testsuite/binutils-all/mips/mips-note-2r-n64.d: Likewise. * testsuite/binutils-all/mips/mips-note-2r.d: Likewise. * testsuite/binutils-all/note-2-32.d: Likewise. * testsuite/binutils-all/note-2-64.d: Likewise. * testsuite/binutils-all/note-3-32.d: Likewise. * testsuite/binutils-all/note-3-64.d: Likewise. * testsuite/binutils-all/note-4-64.s: New test. Checks v3 notes. * testsuite/binutils-all/note-4-32.s: New test. * testsuite/binutils-all/note-4-64.d: New test result file. * testsuite/binutils-all/note-4-32.d: New test result file.
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r--binutils/objcopy.c514
1 files changed, 339 insertions, 175 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 17b91bf..77193b1 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -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;
+
+ 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->type != NT_GNU_BUILD_ATTRIBUTE_OPEN
- && pnote->type != NT_GNU_BUILD_ATTRIBUTE_FUNC)
+ 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;
+
+ if (end)
+ previous_open_end = end;
- remain -= 12 + pnote->namesz + pnote->descsz;
- in += 12 + pnote->namesz + pnote->descsz;
+ 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->namedata[pnote->namesz - 1] != 0)
+ 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, asection * sec, bfd_size_type size, bfd_byte
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, asection * sec, bfd_size_type size, bfd_byte
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, asection * sec, bfd_size_type size, bfd_byte
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 (back->type == pnote->type
- && 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;
- }
+ /* 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;
- 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;
- }
+ if (! is_open_note (back))
+ continue;
- 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;
- }
+ /* If the two notes are different then keep on searching. */
+ if (back_type != note_type)
+ 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;
+ /* Rule 4 - combine stack size notes. */
+ if (back_type == 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--;)
+ {
+ 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, asection * sec, bfd_size_type size, bfd_byte
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, asection * sec, bfd_size_type size, bfd_byte
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)
+ {
+ 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
{
- 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, 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, asection * sec, bfd_size_type size, bfd_byte
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: