mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-23 13:21:43 +08:00
PowerPC VLE sh_flags and p_flags
ELF section sh_flags SHF_PPC_VLE was being set based on arch/mach, which meant all code sections in an object file has the flag or all lacked it. We can do better than that. Only those code sections where VLE is enabled ought to have the flag, allowing an object file to contain both VLE and non-VLE code. Also, ELF header p_flags PF_PPC_VLE wasn't being set, and segments were being split unnecessarily. bfd/ * elf32-ppc.c (ppc_elf_section_processing): Delete. (elf_backend_section_processing): Don't define. (ppc_elf_modify_segment_map): Set p_flags and mark valid. Don't split on non-exec sections differing in SHF_PPC_VLE. When splitting segments, mark size invalid. gas/ * config/tc-ppc.c (md_assemble): Set sh_flags for VLE. Test ppc_cpu rather than calling ppc_mach to determine VLE mode. (ppc_frag_check, ppc_handle_align): Likewise use ppc_cpu.
This commit is contained in:
parent
afe002dd66
commit
f7d69005fb
@ -1,3 +1,11 @@
|
||||
2016-08-31 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_section_processing): Delete.
|
||||
(elf_backend_section_processing): Don't define.
|
||||
(ppc_elf_modify_segment_map): Set p_flags and mark valid. Don't
|
||||
split on non-exec sections differing in SHF_PPC_VLE. When
|
||||
splitting segments, mark size invalid.
|
||||
|
||||
2016-08-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 20531
|
||||
|
@ -2444,18 +2444,6 @@ ppc_elf_lookup_section_flags (char *flag_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add the VLE flag if required. */
|
||||
|
||||
bfd_boolean
|
||||
ppc_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr)
|
||||
{
|
||||
if (bfd_get_mach (abfd) == bfd_mach_ppc_vle
|
||||
&& (shdr->sh_flags & SHF_EXECINSTR) != 0)
|
||||
shdr->sh_flags |= SHF_PPC_VLE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return address for Ith PLT stub in section PLT, for relocation REL
|
||||
or (bfd_vma) -1 if it should not be included. */
|
||||
|
||||
@ -2535,10 +2523,7 @@ bfd_boolean
|
||||
ppc_elf_modify_segment_map (bfd *abfd,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct elf_segment_map *m, *n;
|
||||
bfd_size_type amt;
|
||||
unsigned int j, k;
|
||||
bfd_boolean sect0_vle, sectj_vle;
|
||||
struct elf_segment_map *m;
|
||||
|
||||
/* At this point in the link, output sections have already been sorted by
|
||||
LMA and assigned to segments. All that is left to do is to ensure
|
||||
@ -2548,25 +2533,59 @@ ppc_elf_modify_segment_map (bfd *abfd,
|
||||
|
||||
for (m = elf_seg_map (abfd); m != NULL; m = m->next)
|
||||
{
|
||||
if (m->count == 0)
|
||||
struct elf_segment_map *n;
|
||||
bfd_size_type amt;
|
||||
unsigned int j, k;
|
||||
unsigned int p_flags;
|
||||
|
||||
if (m->p_type != PT_LOAD || m->count == 0)
|
||||
continue;
|
||||
|
||||
sect0_vle = (elf_section_flags (m->sections[0]) & SHF_PPC_VLE) != 0;
|
||||
for (j = 1; j < m->count; ++j)
|
||||
for (p_flags = PF_R, j = 0; j != m->count; ++j)
|
||||
{
|
||||
sectj_vle = (elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0;
|
||||
if ((m->sections[j]->flags & SEC_READONLY) == 0)
|
||||
p_flags |= PF_W;
|
||||
if ((m->sections[j]->flags & SEC_CODE) != 0)
|
||||
{
|
||||
p_flags |= PF_X;
|
||||
if ((elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0)
|
||||
p_flags |= PF_PPC_VLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j != m->count)
|
||||
while (++j != m->count)
|
||||
{
|
||||
unsigned int p_flags1 = PF_R;
|
||||
|
||||
if (sectj_vle != sect0_vle)
|
||||
break;
|
||||
}
|
||||
if (j >= m->count)
|
||||
if ((m->sections[j]->flags & SEC_READONLY) == 0)
|
||||
p_flags1 |= PF_W;
|
||||
if ((m->sections[j]->flags & SEC_CODE) != 0)
|
||||
{
|
||||
p_flags1 |= PF_X;
|
||||
if ((elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0)
|
||||
p_flags1 |= PF_PPC_VLE;
|
||||
if (((p_flags1 ^ p_flags) & PF_PPC_VLE) != 0)
|
||||
break;
|
||||
}
|
||||
p_flags |= p_flags1;
|
||||
}
|
||||
/* If we're splitting a segment which originally contained rw
|
||||
sections then those sections might now only be in one of the
|
||||
two parts. So always set p_flags if splitting, even if we
|
||||
are being called for objcopy with p_flags_valid set. */
|
||||
if (j != m->count || !m->p_flags_valid)
|
||||
{
|
||||
m->p_flags_valid = 1;
|
||||
m->p_flags = p_flags;
|
||||
}
|
||||
if (j == m->count)
|
||||
continue;
|
||||
|
||||
/* sections 0..j-1 stay in this (current) segment,
|
||||
/* Sections 0..j-1 stay in this (current) segment,
|
||||
the remainder are put in a new segment.
|
||||
The scan resumes with the new segment. */
|
||||
|
||||
/* Fix the new segment. */
|
||||
amt = sizeof (struct elf_segment_map);
|
||||
amt += (m->count - j - 1) * sizeof (asection *);
|
||||
n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
||||
@ -2574,20 +2593,13 @@ ppc_elf_modify_segment_map (bfd *abfd,
|
||||
return FALSE;
|
||||
|
||||
n->p_type = PT_LOAD;
|
||||
n->p_flags = PF_X | PF_R;
|
||||
if (sectj_vle)
|
||||
n->p_flags |= PF_PPC_VLE;
|
||||
n->count = m->count - j;
|
||||
for (k = 0; k < n->count; ++k)
|
||||
{
|
||||
n->sections[k] = m->sections[j+k];
|
||||
m->sections[j+k] = NULL;
|
||||
}
|
||||
n->sections[k] = m->sections[j + k];
|
||||
m->count = j;
|
||||
m->p_size_valid = 0;
|
||||
n->next = m->next;
|
||||
m->next = n;
|
||||
|
||||
/* Fix the current segment */
|
||||
m->count = j;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -10860,7 +10872,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
#define elf_backend_action_discarded ppc_elf_action_discarded
|
||||
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
|
||||
#define elf_backend_lookup_section_flags_hook ppc_elf_lookup_section_flags
|
||||
#define elf_backend_section_processing ppc_elf_section_processing
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
2016-08-31 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/tc-ppc.c (md_assemble): Set sh_flags for VLE. Test
|
||||
ppc_cpu rather than calling ppc_mach to determine VLE mode.
|
||||
(ppc_frag_check, ppc_handle_align): Likewise use ppc_cpu.
|
||||
|
||||
2016-08-26 Jose E. Marchesi <jose.marchesi@oracle.com>
|
||||
|
||||
* testsuite/gas/sparc/crypto.d: Rename invalid opcode camellia_fi
|
||||
|
@ -3377,13 +3377,17 @@ md_assemble (char *str)
|
||||
however it'll remain clear for dual-mode instructions on
|
||||
dual-mode and, more importantly, standard-mode processors. */
|
||||
if ((ppc_cpu & opcode->flags) == PPC_OPCODE_VLE)
|
||||
ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1);
|
||||
{
|
||||
ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1);
|
||||
if (elf_section_data (now_seg) != NULL)
|
||||
elf_section_data (now_seg)->this_hdr.sh_flags |= SHF_PPC_VLE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write out the instruction. */
|
||||
/* Differentiate between two and four byte insns. */
|
||||
if (ppc_mach () == bfd_mach_ppc_vle)
|
||||
if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
|
||||
{
|
||||
if (PPC_OP_SE_VLE (insn))
|
||||
insn_length = 2;
|
||||
@ -3400,7 +3404,7 @@ md_assemble (char *str)
|
||||
f = frag_more (insn_length);
|
||||
if (frag_now->has_code && frag_now->insn_addr != addr_mod)
|
||||
{
|
||||
if (ppc_mach() == bfd_mach_ppc_vle)
|
||||
if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
|
||||
as_bad (_("instruction address is not a multiple of 2"));
|
||||
else
|
||||
as_bad (_("instruction address is not a multiple of 4"));
|
||||
@ -6346,7 +6350,7 @@ ppc_frag_check (struct frag *fragP)
|
||||
if (!fragP->has_code)
|
||||
return;
|
||||
|
||||
if (ppc_mach() == bfd_mach_ppc_vle)
|
||||
if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
|
||||
{
|
||||
if (((fragP->fr_address + fragP->insn_addr) & 1) != 0)
|
||||
as_bad (_("instruction address is not a multiple of 2"));
|
||||
@ -6367,7 +6371,7 @@ ppc_handle_align (struct frag *fragP)
|
||||
valueT count = (fragP->fr_next->fr_address
|
||||
- (fragP->fr_address + fragP->fr_fix));
|
||||
|
||||
if (ppc_mach() == bfd_mach_ppc_vle && count != 0 && (count & 1) == 0)
|
||||
if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && count != 0 && (count & 1) == 0)
|
||||
{
|
||||
char *dest = fragP->fr_literal + fragP->fr_fix;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user