From: Nick Clifton Date: Mon, 7 Dec 2015 14:43:47 +0000 (+0000) Subject: Fix relaxation in RX linker when --no-keep-memory is specified. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5ee4a06adea76e607f47eceff65c6bd4a98c49ff;p=binutils-gdb.git Fix relaxation in RX linker when --no-keep-memory is specified. * elf32-rx.c (elf32_rx_relax_delete_bytes): Add extra parameter - the start of the relocs for the section. Delete code to load in the relocs. (elf32_rx_relax_section): Do not free the loaded relocs. --- diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index c58c184fd19..004d7c2dc87 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -1531,7 +1531,8 @@ next_smaller_reloc (int r) static bfd_boolean elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count, - Elf_Internal_Rela *alignment_rel, int force_snip) + Elf_Internal_Rela *alignment_rel, int force_snip, + Elf_Internal_Rela *irelstart) { Elf_Internal_Shdr * symtab_hdr; unsigned int sec_shndx; @@ -1558,20 +1559,7 @@ elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count, if (alignment_rel) toaddr = alignment_rel->r_offset; - irel = elf_section_data (sec)->relocs; - irelend = irel + sec->reloc_count; - - if (irel == NULL && sec->reloc_count > 0) - { - /* If the relocs have not been kept in the section data - structure (because -no-keep-memory was used) then - reread them now. */ - irel = (_bfd_elf_link_read_relocs - (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, FALSE)); - if (irel == NULL) - /* FIXME: Return FALSE instead ? */ - irelend = irel; - } + BFD_ASSERT (toaddr > addr); /* Actually delete the bytes. */ memmove (contents + addr, contents + addr + count, @@ -1585,6 +1573,10 @@ elf32_rx_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count, else memset (contents + toaddr - count, 0x03, count); + irel = irelstart; + BFD_ASSERT (irel != NULL || sec->reloc_count == 0); + irelend = irel + sec->reloc_count; + /* Adjust all the relocs. */ for (; irel < irelend; irel++) { @@ -1977,7 +1969,6 @@ elf32_rx_relax_section (bfd * abfd, Elf_Internal_Shdr * symtab_hdr; Elf_Internal_Shdr * shndx_hdr; Elf_Internal_Rela * internal_relocs; - Elf_Internal_Rela * free_relocs = NULL; Elf_Internal_Rela * irel; Elf_Internal_Rela * srel; Elf_Internal_Rela * irelend; @@ -2054,13 +2045,15 @@ elf32_rx_relax_section (bfd * abfd, } /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, - link_info->keep_memory)); + /* Note - we ignore the setting of link_info->keep_memory when reading + in these relocs. We have to maintain a permanent copy of the relocs + because we are going to walk over them multiple times, adjusting them + as bytes are deleted from the section, and with this relaxation + function itself being called multiple times on the same section... */ + internal_relocs = _bfd_elf_link_read_relocs + (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, TRUE); if (internal_relocs == NULL) goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; /* The RL_ relocs must be just before the operand relocs they go with, so we must sort them to guarantee this. We use bubblesort @@ -2150,7 +2143,7 @@ elf32_rx_relax_section (bfd * abfd, nbytes *= alignment; elf32_rx_relax_delete_bytes (abfd, sec, erel->r_offset-nbytes, nbytes, next_alignment, - erel->r_offset == sec->size); + erel->r_offset == sec->size, internal_relocs); *again = TRUE; continue; @@ -2189,7 +2182,7 @@ elf32_rx_relax_section (bfd * abfd, nrelocs --; #define SNIPNR(offset, nbytes) \ - elf32_rx_relax_delete_bytes (abfd, sec, (insn - contents) + offset, nbytes, next_alignment, 0); + elf32_rx_relax_delete_bytes (abfd, sec, (insn - contents) + offset, nbytes, next_alignment, 0, internal_relocs); #define SNIP(offset, nbytes, newtype) \ SNIPNR (offset, nbytes); \ srel->r_info = ELF32_R_INFO (ELF32_R_SYM (srel->r_info), newtype) @@ -3009,9 +3002,6 @@ elf32_rx_relax_section (bfd * abfd, return TRUE; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) free (free_contents);