Index: bfd/archures.c =================================================================== RCS file: /cvs/src/src/bfd/archures.c,v retrieving revision 1.165 diff -u -p -r1.165 archures.c --- bfd/archures.c 9 Mar 2012 23:39:04 -0000 1.165 +++ bfd/archures.c 13 Apr 2012 18:16:21 -0000 @@ -244,6 +244,7 @@ DESCRIPTION .#define bfd_mach_ppc_e5500 5006 .#define bfd_mach_ppc_e6500 5007 .#define bfd_mach_ppc_titan 83 +.#define bfd_mach_ppc_vle 84 . bfd_arch_rs6000, {* IBM RS/6000 *} .#define bfd_mach_rs6k 6000 .#define bfd_mach_rs6k_rs1 6001 Index: bfd/bfd-in2.h =================================================================== RCS file: /cvs/src/src/bfd/bfd-in2.h,v retrieving revision 1.563 diff -u -p -r1.563 bfd-in2.h --- bfd/bfd-in2.h 29 Mar 2012 13:22:43 -0000 1.563 +++ bfd/bfd-in2.h 13 Apr 2012 18:16:21 -0000 @@ -1348,6 +1348,9 @@ typedef struct bfd_section when memory read flag isn't set. */ #define SEC_COFF_NOREAD 0x40000000 + /* Indicate that the section has the VLE bit set. */ +#define SEC_PPC_VLE 0x80000000 + /* End of section flags. */ /* Some internal packed boolean fields. */ @@ -1945,6 +1948,7 @@ enum bfd_architecture #define bfd_mach_ppc_e5500 5006 #define bfd_mach_ppc_e6500 5007 #define bfd_mach_ppc_titan 83 +#define bfd_mach_ppc_vle 84 bfd_arch_rs6000, /* IBM RS/6000 */ #define bfd_mach_rs6k 6000 #define bfd_mach_rs6k_rs1 6001 @@ -3092,6 +3096,23 @@ instruction. */ BFD_RELOC_PPC_EMB_RELST_HA, BFD_RELOC_PPC_EMB_BIT_FLD, BFD_RELOC_PPC_EMB_RELSDA, + BFD_RELOC_PPC_VLE_REL8, + BFD_RELOC_PPC_VLE_REL15, + BFD_RELOC_PPC_VLE_REL24, + BFD_RELOC_PPC_VLE_LO16A, + BFD_RELOC_PPC_VLE_LO16D, + BFD_RELOC_PPC_VLE_HI16A, + BFD_RELOC_PPC_VLE_HI16D, + BFD_RELOC_PPC_VLE_HA16A, + BFD_RELOC_PPC_VLE_HA16D, + BFD_RELOC_PPC_VLE_SDA21, + BFD_RELOC_PPC_VLE_SDA21_LO, + BFD_RELOC_PPC_VLE_SDAREL_LO16A, + BFD_RELOC_PPC_VLE_SDAREL_LO16D, + BFD_RELOC_PPC_VLE_SDAREL_HI16A, + BFD_RELOC_PPC_VLE_SDAREL_HI16D, + BFD_RELOC_PPC_VLE_SDAREL_HA16A, + BFD_RELOC_PPC_VLE_SDAREL_HA16D, BFD_RELOC_PPC64_HIGHER, BFD_RELOC_PPC64_HIGHER_S, BFD_RELOC_PPC64_HIGHEST, Index: bfd/cpu-powerpc.c =================================================================== RCS file: /cvs/src/src/bfd/cpu-powerpc.c,v retrieving revision 1.26 diff -u -p -r1.26 cpu-powerpc.c --- bfd/cpu-powerpc.c 9 Mar 2012 23:39:04 -0000 1.26 +++ bfd/cpu-powerpc.c 13 Apr 2012 18:16:21 -0000 @@ -376,6 +376,21 @@ const bfd_arch_info_type bfd_powerpc_arc &bfd_powerpc_archs[19] }, { + 16, /* 16 or 32 bits in a word */ + 32, /* 32 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_powerpc, + bfd_mach_ppc_vle, + "powerpc", + "powerpc:vle", + 3, + FALSE, /* not the default */ + powerpc_compatible, + bfd_default_scan, + bfd_arch_default_fill, + &bfd_powerpc_archs[20] + }, + { 64, /* 64 bits in a word */ 64, /* 64 bits in an address */ 8, /* 8 bits in a byte */ @@ -388,7 +403,7 @@ const bfd_arch_info_type bfd_powerpc_arc powerpc_compatible, bfd_default_scan, bfd_arch_default_fill, - &bfd_powerpc_archs[20] + &bfd_powerpc_archs[21] }, { 64, /* 64 bits in a word */ Index: bfd/elf32-ppc.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-ppc.c,v retrieving revision 1.308 diff -u -p -r1.308 elf32-ppc.c --- bfd/elf32-ppc.c 13 Mar 2012 06:04:34 -0000 1.308 +++ bfd/elf32-ppc.c 13 Apr 2012 18:16:22 -0000 @@ -38,12 +38,21 @@ #include "elf-vxworks.h" #include "dwarf2.h" +typedef enum split16_format_type +{ + split16a_type = 0, + split16d_type +} +split16_format_type; + /* RELA relocations are used here. */ static bfd_reloc_status_type ppc_elf_addr16_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc_elf_unhandled_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static void ppc_elf_vle_split16 + (bfd *, bfd_byte *, bfd_vma, bfd_vma, split16_format_type); /* Branch prediction bit for branch taken relocs. */ #define BRANCH_PREDICT_BIT 0x200000 @@ -1392,6 +1401,262 @@ static reloc_howto_type ppc_elf_howto_ra 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* A relative 8 bit branch. */ + HOWTO (R_PPC_VLE_REL8, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_REL8", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A relative 15 bit branch. */ + HOWTO (R_PPC_VLE_REL15, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + TRUE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_REL15", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfe, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A relative 24 bit branch. */ + HOWTO (R_PPC_VLE_REL24, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_REL24", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1fffffe, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* The 16 LSBS in split16a format. */ + HOWTO (R_PPC_VLE_LO16A, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ /* FIXME: Does this apply to split relocs? */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_LO16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* The 16 LSBS in split16d format. */ + HOWTO (R_PPC_VLE_LO16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_LO16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 split16a format. */ + HOWTO (R_PPC_VLE_HI16A, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_HI16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 split16d format. */ + HOWTO (R_PPC_VLE_HI16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_HI16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 (High Adjusted) in split16a format. */ + HOWTO (R_PPC_VLE_HA16A, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_HA16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 (High Adjusted) in split16d format. */ + HOWTO (R_PPC_VLE_HA16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_HA16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* This reloc does nothing. */ + HOWTO (R_PPC_VLE_SDA21, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDA21", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* This reloc does nothing. */ + HOWTO (R_PPC_VLE_SDA21_LO, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDA21_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* The 16 LSBS relative to _SDA_BASE_ in split16a format. */ + HOWTO (R_PPC_VLE_SDAREL_LO16A,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_LO16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* The 16 LSBS relative to _SDA_BASE_ in split16d format. */ + /* This reloc does nothing. */ + HOWTO (R_PPC_VLE_SDAREL_LO16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_LO16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 relative to _SDA_BASE_ in split16a format. */ + HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_HI16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 relative to _SDA_BASE_ in split16d format. */ + HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_HI16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */ + HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_HA16A", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f00fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */ + HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_VLE_SDAREL_HA16D", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1f07ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO (R_PPC_IRELATIVE, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1628,6 +1893,35 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATT case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break; case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break; case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break; + case BFD_RELOC_PPC_VLE_REL8: r = R_PPC_VLE_REL8; break; + case BFD_RELOC_PPC_VLE_REL15: r = R_PPC_VLE_REL15; break; + case BFD_RELOC_PPC_VLE_REL24: r = R_PPC_VLE_REL24; break; + case BFD_RELOC_PPC_VLE_LO16A: r = R_PPC_VLE_LO16A; break; + case BFD_RELOC_PPC_VLE_LO16D: r = R_PPC_VLE_LO16D; break; + case BFD_RELOC_PPC_VLE_HI16A: r = R_PPC_VLE_HI16A; break; + case BFD_RELOC_PPC_VLE_HI16D: r = R_PPC_VLE_HI16D; break; + case BFD_RELOC_PPC_VLE_HA16A: r = R_PPC_VLE_HA16A; break; + case BFD_RELOC_PPC_VLE_HA16D: r = R_PPC_VLE_HA16D; break; + case BFD_RELOC_PPC_VLE_SDA21: r = R_PPC_VLE_SDA21; break; + case BFD_RELOC_PPC_VLE_SDA21_LO: r = R_PPC_VLE_SDA21_LO; break; + case BFD_RELOC_PPC_VLE_SDAREL_LO16A: + r = R_PPC_VLE_SDAREL_LO16A; + break; + case BFD_RELOC_PPC_VLE_SDAREL_LO16D: + r = R_PPC_VLE_SDAREL_LO16D; + break; + case BFD_RELOC_PPC_VLE_SDAREL_HI16A: + r = R_PPC_VLE_SDAREL_HI16A; + break; + case BFD_RELOC_PPC_VLE_SDAREL_HI16D: + r = R_PPC_VLE_SDAREL_HI16D; + break; + case BFD_RELOC_PPC_VLE_SDAREL_HA16A: + r = R_PPC_VLE_SDAREL_HA16A; + break; + case BFD_RELOC_PPC_VLE_SDAREL_HA16D: + r = R_PPC_VLE_SDAREL_HA16D; + break; case BFD_RELOC_16_PCREL: r = R_PPC_REL16; break; case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break; case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break; @@ -1952,6 +2246,36 @@ ppc_elf_write_core_note (bfd *abfd, char } } +static bfd_boolean +ppc_elf_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr) +{ + if (hdr->sh_flags & SHF_PPC_VLE) + *flags |= SEC_PPC_VLE; + return TRUE; +} + +static flagword +ppc_elf_lookup_section_flags (char *flag_name) +{ + + if (!strcmp (flag_name, "SHF_PPC_VLE")) + return SEC_PPC_VLE; + + 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. */ @@ -2025,6 +2349,70 @@ ppc_elf_additional_program_headers (bfd return ret; } +/* Modify the segment map for VLE executables. */ + +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_vma sect0_vle, sectj_vle; + + /* 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 + there is no mixing of VLE & non-VLE sections in a text segment. + If we find that case, we split the segment. + We maintain the original output section order. */ + + for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + { + if (m->count == 0) + continue; + + sect0_vle = m->sections[0]->flags & SEC_PPC_VLE; + for (j = 1; j < m->count; ++j) + { + if ((m->sections[j]->flags & SEC_PPC_VLE) != sect0_vle) + break; + } + if (j >= m->count) + continue; + + sectj_vle = m->sections[j]->flags & SEC_PPC_VLE; + + /* 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); + if (n == NULL) + 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->next = m->next; + m->next = n; + + /* Fix the current segment */ + m->count = j; + } + + return TRUE; +} + /* Add extra PPC sections -- Note, for now, make .sbss2 and .PPC.EMB.sbss0 a normal section, and not a bss section so that the linker doesn't crater when trying to make more than @@ -3620,10 +4008,21 @@ ppc_elf_check_relocs (bfd *abfd, } break; + case R_PPC_VLE_SDAREL_LO16A: + case R_PPC_VLE_SDAREL_LO16D: + case R_PPC_VLE_SDAREL_HI16A: + case R_PPC_VLE_SDAREL_HI16D: + case R_PPC_VLE_SDAREL_HA16A: + case R_PPC_VLE_SDAREL_HA16D: case R_PPC_SDAREL16: if (htab->sdata[0].sym == NULL && !create_sdata_sym (info, &htab->sdata[0])) return FALSE; + + if (htab->sdata[1].sym == NULL + && !create_sdata_sym (info, &htab->sdata[1])) + return FALSE; + if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; @@ -3631,6 +4030,17 @@ ppc_elf_check_relocs (bfd *abfd, } break; + case R_PPC_VLE_REL8: + case R_PPC_VLE_REL15: + case R_PPC_VLE_REL24: + case R_PPC_VLE_LO16A: + case R_PPC_VLE_LO16D: + case R_PPC_VLE_HI16A: + case R_PPC_VLE_HI16D: + case R_PPC_VLE_HA16A: + case R_PPC_VLE_HA16D: + break; + case R_PPC_EMB_SDA2REL: if (info->shared) { @@ -3647,6 +4057,8 @@ ppc_elf_check_relocs (bfd *abfd, } break; + case R_PPC_VLE_SDA21_LO: + case R_PPC_VLE_SDA21: case R_PPC_EMB_SDA21: case R_PPC_EMB_RELSDA: if (info->shared) @@ -4244,6 +4656,24 @@ ppc_elf_merge_private_bfd_data (bfd *ibf return TRUE; } + +static void +ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *contents, + bfd_vma offset, bfd_vma relocation, + split16_format_type split16_format) + +{ + bfd_vma insn, top5, bottom11; + + insn = bfd_get_32 (output_bfd, contents + offset); + top5 = relocation >> 11; + top5 = top5 << (split16_format == split16a_type ? 20 : 16); + bottom11 = relocation & 0x7ff; + insn |= top5; + insn |= bottom11; + bfd_put_32 (output_bfd, insn, contents + offset); +} + /* Choose which PLT scheme to use, and set .plt flags appropriately. Returns -1 on error, 0 for old PLT, 1 for new PLT. */ @@ -7611,6 +8041,9 @@ ppc_elf_relocate_section (bfd *output_bf case R_PPC_UADDR16: goto dodyn; + case R_PPC_VLE_REL8: + case R_PPC_VLE_REL15: + case R_PPC_VLE_REL24: case R_PPC_REL24: case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: @@ -7984,9 +8417,53 @@ ppc_elf_relocate_section (bfd *output_bf } break; + case R_PPC_VLE_LO16A: + relocation = (relocation + addend) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + relocation, split16a_type); + continue; + + case R_PPC_VLE_LO16D: + relocation = (relocation + addend) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + relocation, split16d_type); + continue; + + case R_PPC_VLE_HI16A: + relocation = ((relocation + addend) >> 16) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + relocation, split16a_type); + continue; + + case R_PPC_VLE_HI16D: + relocation = ((relocation + addend) >> 16) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + relocation, split16d_type); + continue; + + case R_PPC_VLE_HA16A: + { + bfd_vma value = relocation + addend; + value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16a_type); + } + continue; + + case R_PPC_VLE_HA16D: + { + bfd_vma value = relocation + addend; + value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16d_type); + } + continue; + /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ case R_PPC_EMB_SDA21: + case R_PPC_VLE_SDA21: case R_PPC_EMB_RELSDA: + case R_PPC_VLE_SDA21_LO: { const char *name; int reg; @@ -8043,7 +8520,25 @@ ppc_elf_relocate_section (bfd *output_bf addend -= SYM_VAL (sda); } - if (r_type == R_PPC_EMB_SDA21) + if (reg == 0 + && (r_type == R_PPC_VLE_SDA21 + || r_type == R_PPC_VLE_SDA21_LO)) + { + /* Use the split20 format. */ + bfd_vma insn, bits12to15, bits21to31; + bfd_vma value = (relocation + rel->r_offset) & 0xffff; + /* Propagate sign bit, if necessary. */ + insn = (value & 0x8000) ? 0x70107800 : 0x70000000; + bits12to15 = value & 0x700; + bits21to31 = value & 0x7ff; + insn |= bits12to15; + insn |= bits21to31; + bfd_put_32 (output_bfd, insn, contents + rel->r_offset); + continue; + } + else if (r_type == R_PPC_EMB_SDA21 + || r_type == R_PPC_VLE_SDA21 + || r_type == R_PPC_VLE_SDA21_LO) { bfd_vma insn; /* Fill in register field. */ @@ -8054,6 +8549,107 @@ ppc_elf_relocate_section (bfd *output_bf } break; + case R_PPC_VLE_SDAREL_LO16A: + case R_PPC_VLE_SDAREL_LO16D: + case R_PPC_VLE_SDAREL_HI16A: + case R_PPC_VLE_SDAREL_HI16D: + case R_PPC_VLE_SDAREL_HA16A: + case R_PPC_VLE_SDAREL_HA16D: + { + bfd_vma value; + const char *name; + //int reg; + struct elf_link_hash_entry *sda = NULL; + + if (sec == NULL || sec->output_section == NULL) + { + unresolved_reloc = TRUE; + break; + } + + name = bfd_get_section_name (abfd, sec->output_section); + if (((CONST_STRNEQ (name, ".sdata") + && (name[6] == 0 || name[6] == '.')) + || (CONST_STRNEQ (name, ".sbss") + && (name[5] == 0 || name[5] == '.')))) + { + //reg = 13; + sda = htab->sdata[0].sym; + } + else if (CONST_STRNEQ (name, ".sdata2") + || CONST_STRNEQ (name, ".sbss2")) + { + //reg = 2; + sda = htab->sdata[1].sym; + } + else + { + (*_bfd_error_handler) + (_("%B: the target (%s) of a %s relocation is " + "in the wrong output section (%s)"), + input_bfd, + sym_name, + howto->name, + name); + + bfd_set_error (bfd_error_bad_value); + ret = FALSE; + continue; + } + + if (sda != NULL) + { + if (!is_static_defined (sda)) + { + unresolved_reloc = TRUE; + break; + } + } + + value = sda->root.u.def.section->output_section->vma + + sda->root.u.def.section->output_offset; + + if (r_type == R_PPC_VLE_SDAREL_LO16A) + { + value = (value + addend) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16a_type); + } + else if (r_type == R_PPC_VLE_SDAREL_LO16D) + { + value = (value + addend) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16d_type); + } + else if (r_type == R_PPC_VLE_SDAREL_HI16A) + { + value = ((value + addend) >> 16) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16a_type); + } + else if (r_type == R_PPC_VLE_SDAREL_HI16D) + { + value = ((value + addend) >> 16) & 0xffff; + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16d_type); + } + else if (r_type == R_PPC_VLE_SDAREL_HA16A) + { + value += addend; + value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16a_type); + } + else if (r_type == R_PPC_VLE_SDAREL_HA16D) + { + value += addend; + value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); + ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, + value, split16d_type); + } + } + continue; + /* Relocate against the beginning of the section. */ case R_PPC_SECTOFF: case R_PPC_SECTOFF_LO: @@ -9113,6 +9709,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou #define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections #define elf_backend_fake_sections ppc_elf_fake_sections #define elf_backend_additional_program_headers ppc_elf_additional_program_headers +#define elf_backend_modify_segment_map ppc_elf_modify_segment_map #define elf_backend_grok_prstatus ppc_elf_grok_prstatus #define elf_backend_grok_psinfo ppc_elf_grok_psinfo #define elf_backend_write_core_note ppc_elf_write_core_note @@ -9125,6 +9722,9 @@ ppc_elf_finish_dynamic_sections (bfd *ou #define elf_backend_action_discarded ppc_elf_action_discarded #define elf_backend_init_index_section _bfd_elf_init_1_index_section #define elf_backend_post_process_headers _bfd_elf_set_osabi +#define elf_backend_lookup_section_flags_hook ppc_elf_lookup_section_flags +#define elf_backend_section_flags ppc_elf_section_flags +#define elf_backend_section_processing ppc_elf_section_processing #include "elf32-target.h" Index: bfd/elf32-ppc.h =================================================================== RCS file: /cvs/src/src/bfd/elf32-ppc.h,v retrieving revision 1.12 diff -u -p -r1.12 elf32-ppc.h --- bfd/elf32-ppc.h 21 Sep 2009 11:51:01 -0000 1.12 +++ bfd/elf32-ppc.h 13 Apr 2012 18:16:22 -0000 @@ -31,3 +31,6 @@ int ppc_elf_select_plt_layout (bfd *, st asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *, int); bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *); void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *); +extern bfd_boolean ppc_elf_modify_segment_map (bfd *, + struct bfd_link_info * ATTRIBUTE_UNUSED); +extern bfd_boolean ppc_elf_section_processing (bfd *, Elf_Internal_Shdr *); Index: bfd/libbfd.h =================================================================== RCS file: /cvs/src/src/bfd/libbfd.h,v retrieving revision 1.270 diff -u -p -r1.270 libbfd.h --- bfd/libbfd.h 7 Mar 2012 17:51:58 -0000 1.270 +++ bfd/libbfd.h 13 Apr 2012 18:16:22 -0000 @@ -1338,6 +1338,23 @@ static const char *const bfd_reloc_code_ "BFD_RELOC_PPC_EMB_RELST_HA", "BFD_RELOC_PPC_EMB_BIT_FLD", "BFD_RELOC_PPC_EMB_RELSDA", + "BFD_RELOC_PPC_VLE_REL8", + "BFD_RELOC_PPC_VLE_REL15", + "BFD_RELOC_PPC_VLE_REL24", + "BFD_RELOC_PPC_VLE_LO16A", + "BFD_RELOC_PPC_VLE_LO16D", + "BFD_RELOC_PPC_VLE_HI16A", + "BFD_RELOC_PPC_VLE_HI16D", + "BFD_RELOC_PPC_VLE_HA16A", + "BFD_RELOC_PPC_VLE_HA16D", + "BFD_RELOC_PPC_VLE_SDA21", + "BFD_RELOC_PPC_VLE_SDA21_LO", + "BFD_RELOC_PPC_VLE_SDAREL_LO16A", + "BFD_RELOC_PPC_VLE_SDAREL_LO16D", + "BFD_RELOC_PPC_VLE_SDAREL_HI16A", + "BFD_RELOC_PPC_VLE_SDAREL_HI16D", + "BFD_RELOC_PPC_VLE_SDAREL_HA16A", + "BFD_RELOC_PPC_VLE_SDAREL_HA16D", "BFD_RELOC_PPC64_HIGHER", "BFD_RELOC_PPC64_HIGHER_S", "BFD_RELOC_PPC64_HIGHEST", Index: bfd/reloc.c =================================================================== RCS file: /cvs/src/src/bfd/reloc.c,v retrieving revision 1.224 diff -u -p -r1.224 reloc.c --- bfd/reloc.c 7 Mar 2012 17:51:59 -0000 1.224 +++ bfd/reloc.c 13 Apr 2012 18:16:22 -0000 @@ -2797,6 +2797,40 @@ ENUMX ENUMX BFD_RELOC_PPC_EMB_RELSDA ENUMX + BFD_RELOC_PPC_VLE_REL8 +ENUMX + BFD_RELOC_PPC_VLE_REL15 +ENUMX + BFD_RELOC_PPC_VLE_REL24 +ENUMX + BFD_RELOC_PPC_VLE_LO16A +ENUMX + BFD_RELOC_PPC_VLE_LO16D +ENUMX + BFD_RELOC_PPC_VLE_HI16A +ENUMX + BFD_RELOC_PPC_VLE_HI16D +ENUMX + BFD_RELOC_PPC_VLE_HA16A +ENUMX + BFD_RELOC_PPC_VLE_HA16D +ENUMX + BFD_RELOC_PPC_VLE_SDA21 +ENUMX + BFD_RELOC_PPC_VLE_SDA21_LO +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_LO16A +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_LO16D +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_HI16A +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_HI16D +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_HA16A +ENUMX + BFD_RELOC_PPC_VLE_SDAREL_HA16D +ENUMX BFD_RELOC_PPC64_HIGHER ENUMX BFD_RELOC_PPC64_HIGHER_S