diff options
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 85 | ||||
-rw-r--r-- | gas/ChangeLog | 6 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 14 |
4 files changed, 71 insertions, 42 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 410b979..e1f5c87 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 1dd6d78..e808cb5 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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" diff --git a/gas/ChangeLog b/gas/ChangeLog index abcdba7..11de10f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index fc2a045..1417c26 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -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; |