mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
Fix performance regression due to ld -r memmove
The idea here is that instead of using memmove to shuffle the relocs array every time one is deleted, to add a "wrel" pointer and copy from rel[0] to wrel[0] as we go. * elf64-ppc.c (ppc64_elf_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. * elf32-ppc.c (ppc_elf_relocate_section): Likewise.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
2015-11-10 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf64-ppc.c (ppc64_elf_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.
|
||||||
|
* elf32-ppc.c (ppc_elf_relocate_section): Likewise.
|
||||||
|
|
||||||
2015-11-09 Dominik Vogt <vogt@linux.vnet.ibm.com>
|
2015-11-09 Dominik Vogt <vogt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
* elf64-ppc.c (ppc64_elf_size_stubs, ppc64_elf_build_stubs): Fix left
|
* elf64-ppc.c (ppc64_elf_size_stubs, ppc64_elf_build_stubs): Fix left
|
||||||
|
122
bfd/elf32-ppc.c
122
bfd/elf32-ppc.c
@ -7650,6 +7650,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
struct ppc_elf_link_hash_table *htab;
|
struct ppc_elf_link_hash_table *htab;
|
||||||
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *rel;
|
||||||
|
Elf_Internal_Rela *wrel;
|
||||||
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
||||||
Elf_Internal_Rela outrel;
|
Elf_Internal_Rela outrel;
|
||||||
asection *got2;
|
asection *got2;
|
||||||
@ -7685,9 +7686,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
".tls_vars"));
|
".tls_vars"));
|
||||||
if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET)
|
if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET)
|
||||||
relax_info = elf_section_data (input_section)->sec_info;
|
relax_info = elf_section_data (input_section)->sec_info;
|
||||||
rel = relocs;
|
rel = wrel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
for (; rel < relend; rel++)
|
for (; rel < relend; wrel++, rel++)
|
||||||
{
|
{
|
||||||
enum elf_ppc_reloc_type r_type;
|
enum elf_ppc_reloc_type r_type;
|
||||||
bfd_vma addend;
|
bfd_vma addend;
|
||||||
@ -7706,6 +7707,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
struct plt_entry **ifunc;
|
struct plt_entry **ifunc;
|
||||||
struct reloc_howto_struct alt_howto;
|
struct reloc_howto_struct alt_howto;
|
||||||
|
|
||||||
|
again:
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
sec = NULL;
|
sec = NULL;
|
||||||
@ -7742,8 +7744,22 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
howto = NULL;
|
howto = NULL;
|
||||||
if (r_type < R_PPC_max)
|
if (r_type < R_PPC_max)
|
||||||
howto = ppc_elf_howto_table[r_type];
|
howto = ppc_elf_howto_table[r_type];
|
||||||
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
|
||||||
|
non-debug to preserve relocs in .eh_frame which the
|
||||||
|
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))
|
if (bfd_link_relocatable (info))
|
||||||
@ -7759,7 +7775,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
if (r_type != R_PPC_RELAX_PLT
|
if (r_type != R_PPC_RELAX_PLT
|
||||||
&& r_type != R_PPC_RELAX_PLTREL24
|
&& r_type != R_PPC_RELAX_PLTREL24
|
||||||
&& r_type != R_PPC_RELAX)
|
&& r_type != R_PPC_RELAX)
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TLS optimizations. Replace instruction sequences and relocs
|
/* TLS optimizations. Replace instruction sequences and relocs
|
||||||
@ -7802,10 +7818,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
bfd_vma insn;
|
bfd_vma insn;
|
||||||
|
|
||||||
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
|
insn = bfd_get_32 (output_bfd,
|
||||||
|
contents + rel->r_offset - d_offset);
|
||||||
insn &= 31 << 21;
|
insn &= 31 << 21;
|
||||||
insn |= 0x3c020000; /* addis 0,2,0 */
|
insn |= 0x3c020000; /* addis 0,2,0 */
|
||||||
bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset);
|
bfd_put_32 (output_bfd, insn,
|
||||||
|
contents + rel->r_offset - d_offset);
|
||||||
r_type = R_PPC_TPREL16_HA;
|
r_type = R_PPC_TPREL16_HA;
|
||||||
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||||
}
|
}
|
||||||
@ -7941,8 +7959,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
/* We changed the symbol on an LD reloc. Start over
|
/* We changed the symbol on an LD reloc. Start over
|
||||||
in order to get h, sym, sec etc. right. */
|
in order to get h, sym, sec etc. right. */
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -8000,8 +8017,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
/* Zap the reloc on the _tls_get_addr call too. */
|
/* Zap the reloc on the _tls_get_addr call too. */
|
||||||
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset);
|
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset);
|
||||||
rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
|
rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -8080,9 +8096,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
got_addr = (htab->got->output_section->vma
|
got_addr = (htab->got->output_section->vma
|
||||||
+ htab->got->output_offset
|
+ htab->got->output_offset
|
||||||
+ (h->got.offset & ~1));
|
+ (h->got.offset & ~1));
|
||||||
rel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
|
wrel->r_offset = (p - contents) + d_offset;
|
||||||
rel->r_addend = got_addr;
|
wrel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
|
||||||
rel->r_offset = (p - contents) + d_offset;
|
wrel->r_addend = got_addr;
|
||||||
insn &= ~0xffff;
|
insn &= ~0xffff;
|
||||||
insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
|
insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
|
||||||
bfd_put_32 (output_bfd, insn, p);
|
bfd_put_32 (output_bfd, insn, p);
|
||||||
@ -8100,9 +8116,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
/* Use one of the spare relocs, so --emit-relocs
|
/* Use one of the spare relocs, so --emit-relocs
|
||||||
output is reasonable. */
|
output is reasonable. */
|
||||||
memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel));
|
memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel));
|
||||||
rel++;
|
wrel++, rel++;
|
||||||
|
rel->r_offset = wrel[-1].r_offset + 4;
|
||||||
rel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_LO);
|
rel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_LO);
|
||||||
rel->r_offset += 4;
|
rel->r_addend = wrel[-1].r_addend;
|
||||||
|
|
||||||
/* Continue on as if we had a got reloc, to output
|
/* Continue on as if we had a got reloc, to output
|
||||||
dynamic reloc. */
|
dynamic reloc. */
|
||||||
@ -8236,7 +8253,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_NONE:
|
case R_PPC_NONE:
|
||||||
case R_PPC_TLS:
|
case R_PPC_TLS:
|
||||||
@ -8245,7 +8262,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC_EMB_MRKREF:
|
case R_PPC_EMB_MRKREF:
|
||||||
case R_PPC_GNU_VTINHERIT:
|
case R_PPC_GNU_VTINHERIT:
|
||||||
case R_PPC_GNU_VTENTRY:
|
case R_PPC_GNU_VTENTRY:
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
/* GOT16 relocations. Like an ADDR16 using the symbol's
|
/* GOT16 relocations. Like an ADDR16 using the symbol's
|
||||||
address in the GOT as relocation value instead of the
|
address in the GOT as relocation value instead of the
|
||||||
@ -8496,7 +8513,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
/* If here for a picfixup, we're done. */
|
/* If here for a picfixup, we're done. */
|
||||||
if (r_type != ELF32_R_TYPE (rel->r_info))
|
if (r_type != ELF32_R_TYPE (rel->r_info))
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
relocation = (htab->got->output_section->vma
|
relocation = (htab->got->output_section->vma
|
||||||
+ htab->got->output_offset
|
+ htab->got->output_offset
|
||||||
@ -8529,7 +8546,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
rel->r_offset,
|
rel->r_offset,
|
||||||
TRUE))
|
TRUE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -8768,7 +8785,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
||||||
|
|
||||||
if (skip == -1)
|
if (skip == -1)
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
/* This reloc will be computed at runtime. We clear the memory
|
/* This reloc will be computed at runtime. We clear the memory
|
||||||
so that it contains predictable value. */
|
so that it contains predictable value. */
|
||||||
@ -8861,12 +8878,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
relocs to describe this relocation. */
|
relocs to describe this relocation. */
|
||||||
BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE);
|
BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE);
|
||||||
/* The relocs are at the bottom 2 bytes */
|
/* The relocs are at the bottom 2 bytes */
|
||||||
rel[0].r_offset += d_offset;
|
wrel->r_offset = rel->r_offset + d_offset;
|
||||||
memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel));
|
wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
|
||||||
rel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
|
wrel->r_addend = rel->r_addend;
|
||||||
rel[1].r_offset += 4;
|
memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel));
|
||||||
rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
|
wrel++, rel++;
|
||||||
rel++;
|
wrel->r_offset += 4;
|
||||||
|
wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -9014,37 +9032,37 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
relocation = relocation + addend;
|
relocation = relocation + addend;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16a_type);
|
relocation, split16a_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_VLE_LO16D:
|
case R_PPC_VLE_LO16D:
|
||||||
relocation = relocation + addend;
|
relocation = relocation + addend;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16d_type);
|
relocation, split16d_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_VLE_HI16A:
|
case R_PPC_VLE_HI16A:
|
||||||
relocation = (relocation + addend) >> 16;
|
relocation = (relocation + addend) >> 16;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16a_type);
|
relocation, split16a_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_VLE_HI16D:
|
case R_PPC_VLE_HI16D:
|
||||||
relocation = (relocation + addend) >> 16;
|
relocation = (relocation + addend) >> 16;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16d_type);
|
relocation, split16d_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_VLE_HA16A:
|
case R_PPC_VLE_HA16A:
|
||||||
relocation = (relocation + addend + 0x8000) >> 16;
|
relocation = (relocation + addend + 0x8000) >> 16;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16a_type);
|
relocation, split16a_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC_VLE_HA16D:
|
case R_PPC_VLE_HA16D:
|
||||||
relocation = (relocation + addend + 0x8000) >> 16;
|
relocation = (relocation + addend + 0x8000) >> 16;
|
||||||
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
|
||||||
relocation, split16d_type);
|
relocation, split16d_type);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
|
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
|
||||||
case R_PPC_EMB_SDA21:
|
case R_PPC_EMB_SDA21:
|
||||||
@ -9093,7 +9111,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sda != NULL)
|
if (sda != NULL)
|
||||||
@ -9131,7 +9149,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
if (r_type == R_PPC_VLE_SDA21
|
if (r_type == R_PPC_VLE_SDA21
|
||||||
&& ((relocation + 0x80000) & 0xffffffff) > 0x100000)
|
&& ((relocation + 0x80000) & 0xffffffff) > 0x100000)
|
||||||
goto overflow;
|
goto overflow;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
else if (r_type == R_PPC_EMB_SDA21
|
else if (r_type == R_PPC_EMB_SDA21
|
||||||
|| r_type == R_PPC_VLE_SDA21
|
|| r_type == R_PPC_VLE_SDA21
|
||||||
@ -9187,7 +9205,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sda != NULL)
|
if (sda != NULL)
|
||||||
@ -9234,7 +9252,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
value, split16d_type);
|
value, split16d_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
/* Relocate against the beginning of the section. */
|
/* Relocate against the beginning of the section. */
|
||||||
case R_PPC_SECTOFF:
|
case R_PPC_SECTOFF:
|
||||||
@ -9282,7 +9300,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_invalid_operation);
|
bfd_set_error (bfd_error_invalid_operation);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do any further special processing. */
|
/* Do any further special processing. */
|
||||||
@ -9342,7 +9360,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
that make up part of the insn opcode. */
|
that make up part of the insn opcode. */
|
||||||
unsigned int insn, mask, lobit;
|
unsigned int insn, mask, lobit;
|
||||||
|
|
||||||
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
|
insn = bfd_get_32 (output_bfd,
|
||||||
|
contents + rel->r_offset - d_offset);
|
||||||
mask = 0;
|
mask = 0;
|
||||||
if (is_insn_ds_form (insn))
|
if (is_insn_ds_form (insn))
|
||||||
mask = 3;
|
mask = 3;
|
||||||
@ -9452,6 +9471,31 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
copy_reloc:
|
||||||
|
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;
|
||||||
|
wrel++;
|
||||||
|
}
|
||||||
|
relend = wrel;
|
||||||
|
rel_hdr = _bfd_elf_single_rel_hdr (input_section);
|
||||||
|
rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
|
||||||
|
input_section->reloc_count -= deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -13162,6 +13162,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *rel;
|
||||||
|
Elf_Internal_Rela *wrel;
|
||||||
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
||||||
Elf_Internal_Rela outrel;
|
Elf_Internal_Rela outrel;
|
||||||
bfd_byte *loc;
|
bfd_byte *loc;
|
||||||
@ -13193,9 +13194,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
sym_hashes = elf_sym_hashes (input_bfd);
|
sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
|
is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
|
||||||
|
|
||||||
rel = relocs;
|
rel = wrel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
for (; rel < relend; rel++)
|
for (; rel < relend; wrel++, rel++)
|
||||||
{
|
{
|
||||||
enum elf_ppc64_reloc_type r_type;
|
enum elf_ppc64_reloc_type r_type;
|
||||||
bfd_vma addend;
|
bfd_vma addend;
|
||||||
@ -13219,10 +13220,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
struct ppc_stub_hash_entry *stub_entry;
|
struct ppc_stub_hash_entry *stub_entry;
|
||||||
bfd_vma max_br_offset;
|
bfd_vma max_br_offset;
|
||||||
bfd_vma from;
|
bfd_vma from;
|
||||||
const Elf_Internal_Rela orig_rel = *rel;
|
Elf_Internal_Rela orig_rel;
|
||||||
reloc_howto_type *howto;
|
reloc_howto_type *howto;
|
||||||
struct reloc_howto_struct alt_howto;
|
struct reloc_howto_struct alt_howto;
|
||||||
|
|
||||||
|
again:
|
||||||
|
orig_rel = *rel;
|
||||||
|
|
||||||
r_type = ELF64_R_TYPE (rel->r_info);
|
r_type = ELF64_R_TYPE (rel->r_info);
|
||||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||||
|
|
||||||
@ -13230,10 +13234,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
symbol of the previous ADDR64 reloc. The symbol gives us the
|
symbol of the previous ADDR64 reloc. The symbol gives us the
|
||||||
proper TOC base to use. */
|
proper TOC base to use. */
|
||||||
if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC)
|
if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC)
|
||||||
&& rel != relocs
|
&& wrel != relocs
|
||||||
&& ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64
|
&& ELF64_R_TYPE (wrel[-1].r_info) == R_PPC64_ADDR64
|
||||||
&& is_opd)
|
&& is_opd)
|
||||||
r_symndx = ELF64_R_SYM (rel[-1].r_info);
|
r_symndx = ELF64_R_SYM (wrel[-1].r_info);
|
||||||
|
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
sec = NULL;
|
sec = NULL;
|
||||||
@ -13314,13 +13318,27 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
h = (struct ppc_link_hash_entry *) h_elf;
|
h = (struct ppc_link_hash_entry *) h_elf;
|
||||||
|
|
||||||
if (sec != NULL && discarded_section (sec))
|
if (sec != NULL && discarded_section (sec))
|
||||||
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
|
{
|
||||||
rel, 1, relend,
|
_bfd_clear_contents (ppc64_elf_howto_table[r_type],
|
||||||
ppc64_elf_howto_table[r_type], 0,
|
input_bfd, input_section,
|
||||||
contents);
|
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
|
||||||
|
non-debug to preserve relocs in .eh_frame which the
|
||||||
|
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))
|
if (bfd_link_relocatable (info))
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
if (h != NULL && &h->elf == htab->elf.hgot)
|
if (h != NULL && &h->elf == htab->elf.hgot)
|
||||||
{
|
{
|
||||||
@ -13480,10 +13498,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
&& (tls_mask & TLS_TPREL) == 0)
|
&& (tls_mask & TLS_TPREL) == 0)
|
||||||
{
|
{
|
||||||
toctprel:
|
toctprel:
|
||||||
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
|
insn = bfd_get_32 (output_bfd,
|
||||||
|
contents + rel->r_offset - d_offset);
|
||||||
insn &= 31 << 21;
|
insn &= 31 << 21;
|
||||||
insn |= 0x3c0d0000; /* addis 0,13,0 */
|
insn |= 0x3c0d0000; /* addis 0,13,0 */
|
||||||
bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset);
|
bfd_put_32 (output_bfd, insn,
|
||||||
|
contents + rel->r_offset - d_offset);
|
||||||
r_type = R_PPC64_TPREL16_HA;
|
r_type = R_PPC64_TPREL16_HA;
|
||||||
if (toc_symndx != 0)
|
if (toc_symndx != 0)
|
||||||
{
|
{
|
||||||
@ -13491,8 +13511,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
rel->r_addend = toc_addend;
|
rel->r_addend = toc_addend;
|
||||||
/* We changed the symbol. Start over in order to
|
/* We changed the symbol. Start over in order to
|
||||||
get h, sym, sec etc. right. */
|
get h, sym, sec etc. right. */
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
|
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
|
||||||
@ -13518,8 +13537,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
rel->r_addend = toc_addend;
|
rel->r_addend = toc_addend;
|
||||||
/* We changed the symbol. Start over in order to
|
/* We changed the symbol. Start over in order to
|
||||||
get h, sym, sec etc. right. */
|
get h, sym, sec etc. right. */
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
|
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
|
||||||
@ -13658,8 +13676,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
/* We changed the symbol. Start over in order
|
/* We changed the symbol. Start over in order
|
||||||
to get h, sym, sec etc. right. */
|
to get h, sym, sec etc. right. */
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -13703,10 +13720,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
bfd_put_32 (output_bfd, insn2, contents + offset);
|
bfd_put_32 (output_bfd, insn2, contents + offset);
|
||||||
if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0)
|
if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0)
|
||||||
{
|
goto again;
|
||||||
rel--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -13748,8 +13762,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
insn2 = NOP;
|
insn2 = NOP;
|
||||||
}
|
}
|
||||||
bfd_put_32 (output_bfd, insn2, contents + offset);
|
bfd_put_32 (output_bfd, insn2, contents + offset);
|
||||||
rel--;
|
goto again;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -14091,7 +14104,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
&& addend == 0)
|
&& addend == 0)
|
||||||
{
|
{
|
||||||
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -14107,7 +14120,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
case R_PPC64_NONE:
|
case R_PPC64_NONE:
|
||||||
case R_PPC64_TLS:
|
case R_PPC64_TLS:
|
||||||
@ -14116,7 +14129,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC64_TOCSAVE:
|
case R_PPC64_TOCSAVE:
|
||||||
case R_PPC64_GNU_VTINHERIT:
|
case R_PPC64_GNU_VTINHERIT:
|
||||||
case R_PPC64_GNU_VTENTRY:
|
case R_PPC64_GNU_VTENTRY:
|
||||||
continue;
|
goto copy_reloc;
|
||||||
|
|
||||||
/* GOT16 relocations. Like an ADDR16 using the symbol's
|
/* GOT16 relocations. Like an ADDR16 using the symbol's
|
||||||
address in the GOT as relocation value instead of the
|
address in the GOT as relocation value instead of the
|
||||||
@ -14752,7 +14765,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
bfd_set_error (bfd_error_invalid_operation);
|
bfd_set_error (bfd_error_invalid_operation);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Multi-instruction sequences that access the TOC can be
|
/* Multi-instruction sequences that access the TOC can be
|
||||||
@ -14901,7 +14914,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
mask + 1);
|
mask + 1);
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
continue;
|
goto copy_reloc;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -15000,6 +15013,29 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
if (more_info != NULL)
|
if (more_info != NULL)
|
||||||
free (more_info);
|
free (more_info);
|
||||||
}
|
}
|
||||||
|
copy_reloc:
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're emitting relocations, then shortly after this function
|
/* If we're emitting relocations, then shortly after this function
|
||||||
|
Reference in New Issue
Block a user