aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-11-09 23:49:02 -0800
committerH.J. Lu <hjl.tools@gmail.com>2015-11-10 00:00:04 -0800
commit60f2e42e00083accdcdbdda399534082bf309d1e (patch)
tree8b35187979e66adbacca26926c1bbdfbe0c6f3ca /bfd/elf64-x86-64.c
parent6637a4265e6144f5a9ad29e9fa08aba4bd959cb9 (diff)
downloadgdb-60f2e42e00083accdcdbdda399534082bf309d1e.zip
gdb-60f2e42e00083accdcdbdda399534082bf309d1e.tar.gz
gdb-60f2e42e00083accdcdbdda399534082bf309d1e.tar.bz2
Fix performance regression on x86 with ld -r
Similar fix to "commit c316a17c40e44e8798b34ff84130904f2e7a53de". * elf32-i386.c (elf_i386_relocate_section): Use read and write pointers to reloc array, rather than memmove when deleting a reloc. Don't use RELOC_AGAINST_DISCARDED_SECTION. Adjust reloc counts at end of loop. * elf64-x86-64.c (elf_x86_64_relocate_section): Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index deaee91..8e62d3d 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -3866,6 +3866,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
bfd_vma *local_got_offsets;
bfd_vma *local_tlsdesc_gotents;
Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *wrel;
Elf_Internal_Rela *relend;
const unsigned int plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
@@ -3881,9 +3882,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
elf_x86_64_set_tls_module_base (info);
- rel = relocs;
+ rel = wrel = relocs;
relend = relocs + input_section->reloc_count;
- for (; rel < relend; rel++)
+ for (; rel < relend; wrel++, rel++)
{
unsigned int r_type;
reloc_howto_type *howto;
@@ -3961,8 +3962,22 @@ elf_x86_64_relocate_section (bfd *output_bfd,
}
if (sec != NULL && discarded_section (sec))
- RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
- rel, 1, relend, howto, 0, contents);
+ {
+ _bfd_clear_contents (howto, input_bfd, input_section,
+ contents + rel->r_offset);
+ wrel->r_offset = rel->r_offset;
+ wrel->r_info = 0;
+ wrel->r_addend = 0;
+
+ /* For ld -r, remove relocations in debug sections against
+ sections defined in discarded sections. Not done for
+ eh_frame editing code expects to be present. */
+ if (bfd_link_relocatable (info)
+ && (input_section->flags & SEC_DEBUGGING))
+ wrel--;
+
+ continue;
+ }
if (bfd_link_relocatable (info))
continue;
@@ -4782,6 +4797,7 @@ direct:
contents + roff + 8 + largepic);
/* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64. */
rel++;
+ wrel++;
continue;
}
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
@@ -5064,6 +5080,7 @@ direct:
contents + roff + 8 + largepic);
/* Skip R_X86_64_PLT32/R_X86_64_PLTOFF64. */
rel++;
+ wrel++;
continue;
}
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
@@ -5148,6 +5165,7 @@ direct:
"\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12);
/* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64. */
rel++;
+ wrel++;
continue;
}
@@ -5264,6 +5282,29 @@ check_relocation_error:
return FALSE;
}
}
+
+ if (wrel != rel)
+ *wrel = *rel;
+ }
+
+ if (wrel != rel)
+ {
+ Elf_Internal_Shdr *rel_hdr;
+ size_t deleted = rel - wrel;
+
+ rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
+ rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+ if (rel_hdr->sh_size == 0)
+ {
+ /* It is too late to remove an empty reloc section. Leave
+ one NONE reloc.
+ ??? What is wrong with an empty section??? */
+ rel_hdr->sh_size = rel_hdr->sh_entsize;
+ deleted -= 1;
+ }
+ rel_hdr = _bfd_elf_single_rel_hdr (input_section);
+ rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+ input_section->reloc_count -= deleted;
}
return TRUE;