Index: bfd/config.bfd =================================================================== RCS file: /cvs/src/src/bfd/config.bfd,v retrieving revision 1.149 diff -c -r1.149 config.bfd *** bfd/config.bfd 3 Dec 2003 15:07:15 -0000 1.149 --- bfd/config.bfd 18 Dec 2003 10:04:31 -0000 *************** *** 597,602 **** --- 597,617 ---- targ_defvec=bfd_elf32_iq2000_vec ;; + m32r*le-*-linux*) + targ_defvec=bfd_elf32_m32rlelin_vec + targ_selvecs="bfd_elf32_m32rlin_vec bfd_elf32_m32rlelin_vec" + ;; + + m32r*-*-linux*) + targ_defvec=bfd_elf32_m32rlin_vec + targ_selvecs="bfd_elf32_m32rlin_vec bfd_elf32_m32rlelin_vec" + ;; + + m32r*le-*-*) + targ_defvec=bfd_elf32_m32rle_vec + targ_selvecs="bfd_elf32_m32r_vec bfd_elf32_m32rle_vec" + ;; + m32r-*-*) targ_defvec=bfd_elf32_m32r_vec ;; Index: bfd/configure.in =================================================================== RCS file: /cvs/src/src/bfd/configure.in,v retrieving revision 1.141 diff -c -r1.141 configure.in *** bfd/configure.in 3 Dec 2003 15:07:15 -0000 1.141 --- bfd/configure.in 18 Dec 2003 10:04:32 -0000 *************** *** 631,636 **** --- 631,639 ---- bfd_elf32_littlearm_vec) tb="$tb elfarm-nabi.lo elf32.lo $elf" ;; bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; + bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; + bfd_elf32_m32rlin_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; + bfd_elf32_m32rlelin_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;; bfd_elf32_m68hc11_vec) tb="$tb elf32-m68hc11.lo elf32-m68hc1x.lo elf32.lo $elf" ;; bfd_elf32_m68hc12_vec) tb="$tb elf32-m68hc12.lo elf32-m68hc1x.lo elf32.lo $elf" ;; bfd_elf32_m68k_vec) tb="$tb elf32-m68k.lo elf32.lo $elf" ;; Index: bfd/elf32-m32r.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-m32r.c,v retrieving revision 1.38 diff -c -r1.38 elf32-m32r.c *** bfd/elf32-m32r.c 3 Dec 2003 17:38:48 -0000 1.38 --- bfd/elf32-m32r.c 18 Dec 2003 10:04:33 -0000 *************** *** 44,49 **** --- 44,51 ---- PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); static void m32r_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); + static void m32r_info_to_howto + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); bfd_boolean _bfd_m32r_elf_section_from_bfd_section PARAMS ((bfd *, asection *, int *)); void _bfd_m32r_elf_symbol_processing *************** *** 77,86 **** --- 79,112 ---- PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); + static bfd_boolean m32r_elf_adjust_dynamic_symbol + PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); + static bfd_boolean m32r_elf_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); + asection * m32r_elf_gc_mark_hook PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); + static bfd_boolean m32r_elf_create_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); + + static bfd_boolean m32r_elf_finish_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); + + static bfd_boolean m32r_elf_finish_dynamic_symbol + PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *)); + + static bfd_boolean allocate_dynrelocs + PARAMS ((struct elf_link_hash_entry *, PTR)); + static bfd_boolean readonly_dynrelocs + PARAMS ((struct elf_link_hash_entry *, PTR)); + static enum elf_reloc_type_class m32r_elf_reloc_type_class + PARAMS ((const Elf_Internal_Rela *)); + static bfd_boolean m32r_elf_fake_sections + PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); + #define NOP_INSN 0x7000 #define MAKE_PARALLEL(insn) ((insn) | 0x8000) *************** *** 88,98 **** This only saves space in libraries and object files, but perhaps relocs will be put in ROM? All in all though, REL relocs are a pain to work with. */ ! #define USE_REL 1 #ifndef USE_REL #define USE_REL 0 ! #endif static reloc_howto_type m32r_elf_howto_table[] = { --- 114,168 ---- This only saves space in libraries and object files, but perhaps relocs will be put in ROM? All in all though, REL relocs are a pain to work with. */ ! /* #define USE_REL 1 #ifndef USE_REL #define USE_REL 0 ! #endif */ ! /* Use RELA. But use REL to link old objects for backwords compatibility. */ ! ! /* Functions for the M32R ELF linker. */ ! ! /* The name of the dynamic interpreter. This is put in the .interp ! section. */ ! ! #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1" ! ! /* The nop opcode we use. */ ! ! #define M32R_NOP 0x7000f000 ! ! #define PLT_EMPTY 0x10101010 /* RIE -> RIE */ ! ! /* The size in bytes of an entry in the procedure linkage table. */ ! ! #define PLT_ENTRY_SIZE 20 ! #define PLT_HEADER_SIZE 20 ! ! /* The first one entries in a procedure linkage table are reserved, ! and the initial contents are unimportant (we zero them out). ! Subsequent entries look like this. */ ! ! #define PLT0_ENTRY_WORD0 0xd6c00000 /* seth r6, #high(.got+4) */ ! #define PLT0_ENTRY_WORD1 0x86e60000 /* or3 r6, r6, #low(.got)+4) */ ! #define PLT0_ENTRY_WORD2 0x24e626c6 /* ld r4, @r6+ -> ld r6, @r6 */ ! #define PLT0_ENTRY_WORD3 0x1fc6f000 /* jmp r6 || pnop */ ! #define PLT0_ENTRY_WORD4 PLT_EMPTY /* RIE -> RIE */ ! ! #define PLT0_PIC_ENTRY_WORD0 0xa4cc0004 /* ld r4, @(4,r12) */ ! #define PLT0_PIC_ENTRY_WORD1 0xa6cc0008 /* ld r6, @(8,r12) */ ! #define PLT0_PIC_ENTRY_WORD2 0x1fc6f000 /* jmp r6 || nop */ ! #define PLT0_PIC_ENTRY_WORD3 PLT_EMPTY /* RIE -> RIE */ ! #define PLT0_PIC_ENTRY_WORD4 PLT_EMPTY /* RIE -> RIE */ ! ! #define PLT_ENTRY_WORD0 0xe6000000 /* ld24 r6, .name_in_GOT */ ! #define PLT_ENTRY_WORD1 0x06acf000 /* add r6, r12 || nop */ ! #define PLT_ENTRY_WORD0b 0xd6c00000 /* seth r6, #high(.name_in_GOT) */ ! #define PLT_ENTRY_WORD1b 0x86e60000 /* or3 r6, r6, #low(.name_in_GOT) */ ! #define PLT_ENTRY_WORD2 0x26c61fc6 /* ld r6, @r6 -> jmp r6 */ ! #define PLT_ENTRY_WORD3 0xe5000000 /* ld24 r5, $offset */ ! #define PLT_ENTRY_WORD4 0xff000000 /* bra .plt0. */ ! static reloc_howto_type m32r_elf_howto_table[] = { *************** *** 302,420 **** 0, /* dst_mask */ FALSE), /* pcrel_offset */ ! }; ! ! /* Handle the R_M32R_10_PCREL reloc. */ ! ! static bfd_reloc_status_type ! m32r_elf_10_pcrel_reloc (abfd, reloc_entry, symbol, data, ! input_section, output_bfd, error_message) ! bfd * abfd; ! arelent * reloc_entry; ! asymbol * symbol; ! PTR data; ! asection * input_section; ! bfd * output_bfd; ! char ** error_message ATTRIBUTE_UNUSED; ! { ! /* This part is from bfd_elf_generic_reloc. */ ! if (output_bfd != (bfd *) NULL ! && (symbol->flags & BSF_SECTION_SYM) == 0 ! && (! reloc_entry->howto->partial_inplace ! || reloc_entry->addend == 0)) ! { ! reloc_entry->address += input_section->output_offset; ! return bfd_reloc_ok; ! } ! if (output_bfd != NULL) ! { ! /* FIXME: See bfd_perform_relocation. Is this right? */ ! return bfd_reloc_continue; ! } ! return m32r_elf_do_10_pcrel_reloc (abfd, reloc_entry->howto, ! input_section, ! data, reloc_entry->address, ! symbol->section, ! (symbol->value ! + symbol->section->output_section->vma ! + symbol->section->output_offset), ! reloc_entry->addend); ! } ! /* Utility to actually perform an R_M32R_10_PCREL reloc. */ ! static bfd_reloc_status_type ! m32r_elf_do_10_pcrel_reloc (abfd, howto, input_section, data, offset, ! symbol_section, symbol_value, addend) ! bfd *abfd; ! reloc_howto_type *howto; ! asection *input_section; ! bfd_byte *data; ! bfd_vma offset; ! asection *symbol_section ATTRIBUTE_UNUSED; ! bfd_vma symbol_value; ! bfd_vma addend; ! { ! bfd_signed_vma relocation; ! unsigned long x; ! bfd_reloc_status_type status; ! /* Sanity check the address (offset in section). */ ! if (offset > input_section->_cooked_size) ! return bfd_reloc_outofrange; ! relocation = symbol_value + addend; ! /* Make it pc relative. */ ! relocation -= (input_section->output_section->vma ! + input_section->output_offset); ! /* These jumps mask off the lower two bits of the current address ! before doing pcrel calculations. */ ! relocation -= (offset & -(bfd_vma) 4); ! if (relocation < -0x200 || relocation > 0x1ff) ! status = bfd_reloc_overflow; ! else ! status = bfd_reloc_ok; ! x = bfd_get_16 (abfd, data + offset); ! relocation >>= howto->rightshift; ! relocation <<= howto->bitpos; ! x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask); ! bfd_put_16 (abfd, (bfd_vma) x, data + offset); ! return status; ! } ! /* Handle the R_M32R_HI16_[SU]LO relocs. ! HI16_SLO is for the add3 and load/store with displacement instructions. ! HI16_ULO is for the or3 instruction. ! For R_M32R_HI16_SLO, the lower 16 bits are sign extended when added to ! the high 16 bytes so if the lower 16 bits are negative (bit 15 == 1) then ! we must add one to the high 16 bytes (which will get subtracted off when ! the low 16 bits are added). ! These relocs have to be done in combination with an R_M32R_LO16 reloc ! because there is a carry from the LO16 to the HI16. Here we just save ! the information we need; we do the actual relocation when we see the LO16. ! This code is copied from the elf32-mips.c. We also support an arbitrary ! number of HI16 relocs to be associated with a single LO16 reloc. The ! assembler sorts the relocs to ensure each HI16 immediately precedes its ! LO16. However if there are multiple copies, the assembler may not find ! the real LO16 so it picks the first one it finds. */ ! struct m32r_hi16 ! { ! struct m32r_hi16 *next; ! bfd_byte *addr; ! bfd_vma addend; ! }; ! /* FIXME: This should not be a static variable. */ ! static struct m32r_hi16 *m32r_hi16_list; ! static bfd_reloc_status_type m32r_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; --- 372,921 ---- 0, /* dst_mask */ FALSE), /* pcrel_offset */ ! EMPTY_HOWTO (13), ! EMPTY_HOWTO (14), ! EMPTY_HOWTO (15), ! EMPTY_HOWTO (16), ! EMPTY_HOWTO (17), ! EMPTY_HOWTO (18), ! EMPTY_HOWTO (19), ! EMPTY_HOWTO (20), ! EMPTY_HOWTO (21), ! EMPTY_HOWTO (22), ! EMPTY_HOWTO (23), ! EMPTY_HOWTO (24), ! EMPTY_HOWTO (25), ! EMPTY_HOWTO (26), ! EMPTY_HOWTO (27), ! EMPTY_HOWTO (28), ! EMPTY_HOWTO (29), ! EMPTY_HOWTO (30), ! EMPTY_HOWTO (31), ! EMPTY_HOWTO (32), ! /* A 16 bit absolute relocation. */ ! HOWTO (R_M32R_16_RELA, /* type */ ! 0, /* rightshift */ ! 1, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_bitfield, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_16_RELA", /* name */ ! FALSE, /* partial_inplace */ ! 0xffff, /* src_mask */ ! 0xffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* A 32 bit absolute relocation. */ ! HOWTO (R_M32R_32_RELA, /* 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_M32R_32_RELA", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* A 24 bit address. */ ! HOWTO (R_M32R_24_RELA, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 24, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_unsigned, /* complain_on_overflow */ ! bfd_elf_generic_reloc,/* special_function */ ! "R_M32R_24_RELA", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffff, /* src_mask */ ! 0xffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! HOWTO (R_M32R_10_PCREL_RELA, /* type */ ! 2, /* rightshift */ ! 1, /* size (0 = byte, 1 = short, 2 = long) */ ! 10, /* bitsize */ ! TRUE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_signed, /* complain_on_overflow */ ! m32r_elf_10_pcrel_reloc, /* special_function */ ! "R_M32R_10_PCREL_RELA",/* name */ ! FALSE, /* partial_inplace */ ! 0xff, /* src_mask */ ! 0xff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! /* A relative 18 bit relocation, right shifted by 2. */ ! HOWTO (R_M32R_18_PCREL_RELA, /* type */ ! 2, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! TRUE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_signed, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_18_PCREL_RELA",/* name */ ! FALSE, /* partial_inplace */ ! 0xffff, /* src_mask */ ! 0xffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! /* A relative 26 bit relocation, right shifted by 2. */ ! HOWTO (R_M32R_26_PCREL_RELA, /* type */ ! 2, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 26, /* bitsize */ ! TRUE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_signed, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_26_PCREL_RELA",/* name */ ! FALSE, /* partial_inplace */ ! 0xffffff, /* src_mask */ ! 0xffffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! /* High 16 bits of address when lower 16 is or'd in. */ ! HOWTO (R_M32R_HI16_ULO_RELA, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_HI16_ULO_RELA",/* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* High 16 bits of address when lower 16 is added in. */ ! HOWTO (R_M32R_HI16_SLO_RELA, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_HI16_SLO_RELA",/* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* Lower 16 bits of address. */ ! HOWTO (R_M32R_LO16_RELA, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_LO16_RELA", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* Small data area 16 bits offset. */ ! HOWTO (R_M32R_SDA16_RELA, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_signed, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_SDA16_RELA", /* name */ ! TRUE, /* partial_inplace */ /* FIXME: correct? */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* GNU extension to record C++ vtable hierarchy */ ! HOWTO (R_M32R_RELA_GNU_VTINHERIT, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 0, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! NULL, /* special_function */ ! "R_M32R_RELA_GNU_VTINHERIT", /* name */ ! FALSE, /* partial_inplace */ ! 0, /* src_mask */ ! 0, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* GNU extension to record C++ vtable member usage */ ! HOWTO (R_M32R_RELA_GNU_VTENTRY, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 0, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! _bfd_elf_rel_vtable_reloc_fn, /* special_function */ ! "R_M32R_RELA_GNU_VTENTRY", /* name */ ! FALSE, /* partial_inplace */ ! 0, /* src_mask */ ! 0, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! EMPTY_HOWTO (45), ! EMPTY_HOWTO (46), ! EMPTY_HOWTO (47), ! ! /* Like R_M32R_24, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOT24, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 24, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_unsigned, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOT24", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffff, /* src_mask */ ! 0xffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! /* Like R_M32R_PCREL, but referring to the procedure linkage table ! entry for the symbol. */ ! HOWTO (R_M32R_26_PLTREL, /* type */ ! 2, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 24, /* bitsize */ ! TRUE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_signed, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_26_PLTREL", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffff, /* src_mask */ ! 0xffffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! ! /* This is used only by the dynamic linker. The symbol should exist ! both in the object being run and in some shared library. The ! dynamic linker copies the data addressed by the symbol from the ! shared library into the object, because the object being ! run has to have the data at some particular address. */ ! HOWTO (R_M32R_COPY, /* 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_M32R_COPY", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* Like R_M32R_24, but used when setting global offset table ! entries. */ ! HOWTO (R_M32R_GLOB_DAT, /* 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_M32R_GLOB_DAT", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* Marks a procedure linkage table entry for a symbol. */ ! HOWTO (R_M32R_JMP_SLOT, /* 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_M32R_JMP_SLOT", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* Used only by the dynamic linker. When the object is run, this ! longword is set to the load address of the object, plus the ! addend. */ ! HOWTO (R_M32R_RELATIVE, /* 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_M32R_RELATIVE", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! HOWTO (R_M32R_GOTOFF, /* 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_M32R_GOTOFF", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffffff, /* src_mask */ ! 0xffffffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* An PC Relative 24-bit relocation used when setting PIC offset ! table register. */ ! HOWTO (R_M32R_GOTPC24, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 24, /* bitsize */ ! TRUE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_unsigned, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOTPC24", /* name */ ! FALSE, /* partial_inplace */ ! 0xffffff, /* src_mask */ ! 0xffffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! ! /* Like R_M32R_HI16_ULO, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOT16_HI_ULO, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOT16_HI_ULO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* Like R_M32R_HI16_SLO, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOT16_HI_SLO, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOT16_HI_SLO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* Like R_M32R_LO16, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOT16_LO, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOT16_LO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! FALSE), /* pcrel_offset */ ! ! /* An PC Relative relocation used when setting PIC offset table register. ! Like R_M32R_HI16_ULO, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOTPC_HI_ULO, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOTPC_HI_ULO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! ! /* An PC Relative relocation used when setting PIC offset table register. ! Like R_M32R_HI16_SLO, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOTPC_HI_SLO, /* type */ ! 16, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOTPC_HI_SLO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! ! /* An PC Relative relocation used when setting PIC offset table register. ! Like R_M32R_LO16, but referring to the GOT table entry for ! the symbol. */ ! HOWTO (R_M32R_GOTPC_LO, /* type */ ! 0, /* rightshift */ ! 2, /* size (0 = byte, 1 = short, 2 = long) */ ! 16, /* bitsize */ ! FALSE, /* pc_relative */ ! 0, /* bitpos */ ! complain_overflow_dont, /* complain_on_overflow */ ! bfd_elf_generic_reloc, /* special_function */ ! "R_M32R_GOTPC_LO", /* name */ ! FALSE, /* partial_inplace */ ! 0x0000ffff, /* src_mask */ ! 0x0000ffff, /* dst_mask */ ! TRUE), /* pcrel_offset */ ! }; ! ! /* Handle the R_M32R_10_PCREL reloc. */ ! ! static bfd_reloc_status_type ! m32r_elf_10_pcrel_reloc (abfd, reloc_entry, symbol, data, ! input_section, output_bfd, error_message) ! bfd * abfd; ! arelent * reloc_entry; ! asymbol * symbol; ! PTR data; ! asection * input_section; ! bfd * output_bfd; ! char ** error_message ATTRIBUTE_UNUSED; ! { ! /* This part is from bfd_elf_generic_reloc. */ ! if (output_bfd != (bfd *) NULL ! && (symbol->flags & BSF_SECTION_SYM) == 0 ! && (! reloc_entry->howto->partial_inplace ! || reloc_entry->addend == 0)) ! { ! reloc_entry->address += input_section->output_offset; ! return bfd_reloc_ok; ! } ! ! if (output_bfd != NULL) ! { ! /* FIXME: See bfd_perform_relocation. Is this right? */ ! return bfd_reloc_continue; ! } ! ! return m32r_elf_do_10_pcrel_reloc (abfd, reloc_entry->howto, ! input_section, ! data, reloc_entry->address, ! symbol->section, ! (symbol->value ! + symbol->section->output_section->vma ! + symbol->section->output_offset), ! reloc_entry->addend); ! } ! ! /* Utility to actually perform an R_M32R_10_PCREL reloc. */ ! ! static bfd_reloc_status_type ! m32r_elf_do_10_pcrel_reloc (abfd, howto, input_section, data, offset, ! symbol_section, symbol_value, addend) ! bfd *abfd; ! reloc_howto_type *howto; ! asection *input_section; ! bfd_byte *data; ! bfd_vma offset; ! asection *symbol_section ATTRIBUTE_UNUSED; ! bfd_vma symbol_value; ! bfd_vma addend; ! { ! bfd_signed_vma relocation; ! unsigned long x; ! bfd_reloc_status_type status; ! ! /* Sanity check the address (offset in section). */ ! if (offset > input_section->_cooked_size) ! return bfd_reloc_outofrange; ! ! relocation = symbol_value + addend; ! /* Make it pc relative. */ ! relocation -= (input_section->output_section->vma ! + input_section->output_offset); ! /* These jumps mask off the lower two bits of the current address ! before doing pcrel calculations. */ ! relocation -= (offset & -(bfd_vma) 4); ! ! if (relocation < -0x200 || relocation > 0x1ff) ! status = bfd_reloc_overflow; ! else ! status = bfd_reloc_ok; ! ! x = bfd_get_16 (abfd, data + offset); ! relocation >>= howto->rightshift; ! relocation <<= howto->bitpos; ! x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask); ! bfd_put_16 (abfd, (bfd_vma) x, data + offset); ! ! return status; ! } ! ! /* Handle the R_M32R_HI16_[SU]LO relocs. ! HI16_SLO is for the add3 and load/store with displacement instructions. ! HI16_ULO is for the or3 instruction. ! For R_M32R_HI16_SLO, the lower 16 bits are sign extended when added to ! the high 16 bytes so if the lower 16 bits are negative (bit 15 == 1) then ! we must add one to the high 16 bytes (which will get subtracted off when ! the low 16 bits are added). ! These relocs have to be done in combination with an R_M32R_LO16 reloc ! because there is a carry from the LO16 to the HI16. Here we just save ! the information we need; we do the actual relocation when we see the LO16. ! This code is copied from the elf32-mips.c. We also support an arbitrary ! number of HI16 relocs to be associated with a single LO16 reloc. The ! assembler sorts the relocs to ensure each HI16 immediately precedes its ! LO16. However if there are multiple copies, the assembler may not find ! the real LO16 so it picks the first one it finds. */ ! ! struct m32r_hi16 ! { ! struct m32r_hi16 *next; ! bfd_byte *addr; ! bfd_vma addend; ! }; ! ! /* FIXME: This should not be a static variable. */ ! ! static struct m32r_hi16 *m32r_hi16_list; ! ! static bfd_reloc_status_type m32r_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; *************** *** 715,721 **** unsigned char elf_reloc_val; }; ! static const struct m32r_reloc_map m32r_reloc_map[] = { { BFD_RELOC_NONE, R_M32R_NONE }, { BFD_RELOC_16, R_M32R_16 }, --- 1216,1222 ---- unsigned char elf_reloc_val; }; ! static const struct m32r_reloc_map m32r_reloc_map_old[] = { { BFD_RELOC_NONE, R_M32R_NONE }, { BFD_RELOC_16, R_M32R_16 }, *************** *** 732,737 **** --- 1233,1270 ---- { BFD_RELOC_VTABLE_ENTRY, R_M32R_GNU_VTENTRY }, }; + static const struct m32r_reloc_map m32r_reloc_map[] = + { + { BFD_RELOC_NONE, R_M32R_NONE }, + { BFD_RELOC_16, R_M32R_16_RELA }, + { BFD_RELOC_32, R_M32R_32_RELA }, + { BFD_RELOC_M32R_24, R_M32R_24_RELA }, + { BFD_RELOC_M32R_10_PCREL, R_M32R_10_PCREL_RELA }, + { BFD_RELOC_M32R_18_PCREL, R_M32R_18_PCREL_RELA }, + { BFD_RELOC_M32R_26_PCREL, R_M32R_26_PCREL_RELA }, + { BFD_RELOC_M32R_HI16_ULO, R_M32R_HI16_ULO_RELA }, + { BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO_RELA }, + { BFD_RELOC_M32R_LO16, R_M32R_LO16_RELA }, + { BFD_RELOC_M32R_SDA16, R_M32R_SDA16_RELA }, + { BFD_RELOC_VTABLE_INHERIT, R_M32R_RELA_GNU_VTINHERIT }, + { BFD_RELOC_VTABLE_ENTRY, R_M32R_RELA_GNU_VTENTRY }, + + { BFD_RELOC_M32R_GOT24, R_M32R_GOT24 }, + { BFD_RELOC_M32R_26_PLTREL, R_M32R_26_PLTREL }, + { BFD_RELOC_M32R_COPY, R_M32R_COPY }, + { BFD_RELOC_M32R_GLOB_DAT, R_M32R_GLOB_DAT }, + { BFD_RELOC_M32R_JMP_SLOT, R_M32R_JMP_SLOT }, + { BFD_RELOC_M32R_RELATIVE, R_M32R_RELATIVE }, + { BFD_RELOC_M32R_GOTOFF, R_M32R_GOTOFF }, + { BFD_RELOC_M32R_GOTPC24, R_M32R_GOTPC24 }, + { BFD_RELOC_M32R_GOT16_HI_ULO, R_M32R_GOT16_HI_ULO }, + { BFD_RELOC_M32R_GOT16_HI_SLO, R_M32R_GOT16_HI_SLO }, + { BFD_RELOC_M32R_GOT16_LO, R_M32R_GOT16_LO }, + { BFD_RELOC_M32R_GOTPC_HI_ULO, R_M32R_GOTPC_HI_ULO }, + { BFD_RELOC_M32R_GOTPC_HI_SLO, R_M32R_GOTPC_HI_SLO }, + { BFD_RELOC_M32R_GOTPC_LO, R_M32R_GOTPC_LO }, + }; + static reloc_howto_type * bfd_elf32_bfd_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; *************** *** 739,744 **** --- 1272,1287 ---- { unsigned int i; + #ifdef USE_M32R_OLD_RELOC + for (i = 0; + i < sizeof (m32r_reloc_map_old) / sizeof (struct m32r_reloc_map); + i++) + { + if (m32r_reloc_map_old[i].bfd_reloc_val == code) + return &m32r_elf_howto_table[m32r_reloc_map_old[i].elf_reloc_val]; + } + #else /* ! USE_M32R_OLD_RELOC */ + for (i = 0; i < sizeof (m32r_reloc_map) / sizeof (struct m32r_reloc_map); i++) *************** *** 746,751 **** --- 1289,1295 ---- if (m32r_reloc_map[i].bfd_reloc_val == code) return &m32r_elf_howto_table[m32r_reloc_map[i].elf_reloc_val]; } + #endif return NULL; } *************** *** 753,769 **** /* Set the howto pointer for an M32R ELF reloc. */ static void ! m32r_info_to_howto_rel (abfd, cache_ptr, dst) bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf_Internal_Rela *dst; { ! unsigned int r_type; ! ! r_type = ELF32_R_TYPE (dst->r_info); ! BFD_ASSERT (r_type < (unsigned int) R_M32R_max); ! cache_ptr->howto = &m32r_elf_howto_table[r_type]; } /* Given a BFD section, try to locate the corresponding ELF section index. */ --- 1297,1326 ---- /* Set the howto pointer for an M32R ELF reloc. */ static void ! m32r_info_to_howto_rel (abfd, cache_ptr, dst) ! bfd *abfd ATTRIBUTE_UNUSED; ! arelent *cache_ptr; ! Elf_Internal_Rela *dst; ! { ! unsigned int r_type; ! ! r_type = ELF32_R_TYPE (dst->r_info); ! BFD_ASSERT (ELF32_R_TYPE(dst->r_info) <= (unsigned int) R_M32R_GNU_VTENTRY) ! cache_ptr->howto = &m32r_elf_howto_table[r_type]; ! } ! ! static void ! m32r_info_to_howto (abfd, cache_ptr, dst) bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf_Internal_Rela *dst; { ! BFD_ASSERT ((ELF32_R_TYPE(dst->r_info) == (unsigned int) R_M32R_NONE) ! || ((ELF32_R_TYPE(dst->r_info) > (unsigned int) R_M32R_GNU_VTENTRY) ! && (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_M32R_max))); ! cache_ptr->howto = &m32r_elf_howto_table[ELF32_R_TYPE(dst->r_info)]; } + /* Given a BFD section, try to locate the corresponding ELF section index. */ *************** *** 854,940 **** struct bfd_link_hash_entry *bh; asection *s = bfd_get_section_by_name (abfd, ".sdata"); ! /* The following code was cobbled from elf32-ppc.c and elflink.c. */ ! if (s == NULL) ! { ! flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS ! | SEC_IN_MEMORY | SEC_LINKER_CREATED); ! s = bfd_make_section_anyway (abfd, ".sdata"); ! if (s == NULL) ! return FALSE; ! bfd_set_section_flags (abfd, s, flags); ! bfd_set_section_alignment (abfd, s, 2); ! } ! bh = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", ! FALSE, FALSE, FALSE); ! if ((bh == NULL || bh->type == bfd_link_hash_undefined) ! && !(_bfd_generic_link_add_one_symbol (info, ! abfd, ! "_SDA_BASE_", ! BSF_GLOBAL, ! s, ! (bfd_vma) 32768, ! (const char *) NULL, ! FALSE, ! get_elf_backend_data (abfd)->collect, ! &bh))) ! return FALSE; ! h = (struct elf_link_hash_entry *) bh; ! h->type = STT_OBJECT; ! } ! switch (sym->st_shndx) { ! case SHN_M32R_SCOMMON: ! *secp = bfd_make_section_old_way (abfd, ".scommon"); ! (*secp)->flags |= SEC_IS_COMMON; ! *valp = sym->st_size; ! break; } ! return TRUE; ! } ! /* We have to figure out the SDA_BASE value, so that we can adjust the ! symbol value correctly. We look up the symbol _SDA_BASE_ in the output ! BFD. If we can't find it, we're stuck. We cache it in the ELF ! target data. We don't need to adjust the symbol value for an ! external symbol if we are producing relocatable output. */ ! static bfd_reloc_status_type ! m32r_elf_final_sda_base (output_bfd, info, error_message, psb) ! bfd *output_bfd; ! struct bfd_link_info *info; ! const char **error_message; ! bfd_vma *psb; ! { ! if (elf_gp (output_bfd) == 0) { ! struct bfd_link_hash_entry *h; ! h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE); ! if (h != (struct bfd_link_hash_entry *) NULL ! && h->type == bfd_link_hash_defined) ! elf_gp (output_bfd) = (h->u.def.value ! + h->u.def.section->output_section->vma ! + h->u.def.section->output_offset); else { ! /* Only get the error once. */ ! *psb = elf_gp (output_bfd) = 4; ! *error_message = ! (const char *) _("SDA relocation when _SDA_BASE_ not defined"); ! return bfd_reloc_dangerous; } } ! *psb = elf_gp (output_bfd); ! return bfd_reloc_ok; } - /* Relocate an M32R/D ELF section. There is some attempt to make this function usable for many architectures, both for RELA and REL type relocs, if only to serve as a learning tool. --- 1411,2488 ---- struct bfd_link_hash_entry *bh; asection *s = bfd_get_section_by_name (abfd, ".sdata"); ! /* The following code was cobbled from elf32-ppc.c and elflink.c. */ ! ! if (s == NULL) ! { ! flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS ! | SEC_IN_MEMORY | SEC_LINKER_CREATED); ! ! s = bfd_make_section_anyway (abfd, ".sdata"); ! if (s == NULL) ! return FALSE; ! bfd_set_section_flags (abfd, s, flags); ! bfd_set_section_alignment (abfd, s, 2); ! } ! ! bh = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", ! FALSE, FALSE, FALSE); ! ! if ((bh == NULL || bh->type == bfd_link_hash_undefined) ! && !(_bfd_generic_link_add_one_symbol (info, ! abfd, ! "_SDA_BASE_", ! BSF_GLOBAL, ! s, ! (bfd_vma) 32768, ! (const char *) NULL, ! FALSE, ! get_elf_backend_data (abfd)->collect, ! &bh))) ! return FALSE; ! h = (struct elf_link_hash_entry *) bh; ! h->type = STT_OBJECT; ! } ! ! switch (sym->st_shndx) ! { ! case SHN_M32R_SCOMMON: ! *secp = bfd_make_section_old_way (abfd, ".scommon"); ! (*secp)->flags |= SEC_IS_COMMON; ! *valp = sym->st_size; ! break; ! } ! ! return TRUE; ! } ! ! /* We have to figure out the SDA_BASE value, so that we can adjust the ! symbol value correctly. We look up the symbol _SDA_BASE_ in the output ! BFD. If we can't find it, we're stuck. We cache it in the ELF ! target data. We don't need to adjust the symbol value for an ! external symbol if we are producing relocatable output. */ ! ! static bfd_reloc_status_type ! m32r_elf_final_sda_base (output_bfd, info, error_message, psb) ! bfd *output_bfd; ! struct bfd_link_info *info; ! const char **error_message; ! bfd_vma *psb; ! { ! if (elf_gp (output_bfd) == 0) ! { ! struct bfd_link_hash_entry *h; ! ! h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE); ! if (h != (struct bfd_link_hash_entry *) NULL ! && h->type == bfd_link_hash_defined) ! elf_gp (output_bfd) = (h->u.def.value ! + h->u.def.section->output_section->vma ! + h->u.def.section->output_offset); ! else ! { ! /* Only get the error once. */ ! *psb = elf_gp (output_bfd) = 4; ! *error_message = ! (const char *) _("SDA relocation when _SDA_BASE_ not defined"); ! return bfd_reloc_dangerous; ! } ! } ! *psb = elf_gp (output_bfd); ! return bfd_reloc_ok; ! } ! ! /* Return size of a PLT entry. */ ! #define elf_m32r_sizeof_plt(info) PLT_ENTRY_SIZE ! ! /* The m32r linker needs to keep track of the number of relocs that it ! decides to copy in check_relocs for each symbol. This is so that ! it can discard PC relative relocs if it doesn't need them when ! linking with -Bsymbolic. We store the information in a field ! extending the regular ELF linker hash table. */ ! ! /* This structure keeps track of the number of PC relative relocs we ! have copied for a given symbol. */ ! ! struct elf_m32r_pcrel_relocs_copied ! { ! /* Next section. */ ! struct elf_m32r_pcrel_relocs_copied *next; ! /* A section in dynobj. */ ! asection *section; ! /* Number of relocs copied in this section. */ ! bfd_size_type count; ! }; ! ! /* The sh linker needs to keep track of the number of relocs that it ! decides to copy as dynamic relocs in check_relocs for each symbol. ! This is so that it can later discard them if they are found to be ! unnecessary. We store the information in a field extending the ! regular ELF linker hash table. */ ! ! struct elf_m32r_dyn_relocs ! { ! struct elf_m32r_dyn_relocs *next; ! ! /* The input section of the reloc. */ ! asection *sec; ! ! /* Total number of relocs copied for the input section. */ ! bfd_size_type count; ! ! /* Number of pc-relative relocs copied for the input section. */ ! bfd_size_type pc_count; ! }; ! ! ! /* m32r ELF linker hash entry. */ ! ! struct elf_m32r_link_hash_entry ! { ! struct elf_link_hash_entry root; ! ! /* Track dynamic relocs copied for this symbol. */ ! struct elf_m32r_dyn_relocs *dyn_relocs; ! ! // bfd_signed_vma gotplt_refcount; ! ! /* Number of PC relative relocs copied for this symbol. */ ! /* struct elf_m32r_pcrel_relocs_copied *pcrel_relocs_copied; FIXME */ ! }; ! ! /* m32r ELF linker hash table. */ ! ! struct elf_m32r_link_hash_table ! { ! struct elf_link_hash_table root; ! ! /* Short-cuts to get to dynamic linker sections. */ ! asection *sgot; ! asection *sgotplt; ! asection *srelgot; ! asection *splt; ! asection *srelplt; ! asection *sdynbss; ! asection *srelbss; ! ! /* Small local sym to section mapping cache. */ ! struct sym_sec_cache sym_sec; ! }; ! ! /* Traverse an m32r ELF linker hash table. */ ! ! #define m32r_elf_link_hash_traverse(table, func, info) \ ! (elf_link_hash_traverse \ ! (&(table)->root, \ ! (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ ! (info))) ! ! /* Get the m32r ELF linker hash table from a link_info structure. */ ! ! ! #define m32r_elf_hash_table(p) \ ! ((struct elf_m32r_link_hash_table *) ((p)->hash)) ! ! /* Create an entry in an m32r ELF linker hash table. */ ! static struct bfd_hash_entry * ! m32r_elf_link_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, ! const char * ); ! ! static struct bfd_hash_entry * ! m32r_elf_link_hash_newfunc (entry, table, string) ! struct bfd_hash_entry *entry; ! struct bfd_hash_table *table; ! const char *string; ! { ! struct elf_m32r_link_hash_entry *ret = ! (struct elf_m32r_link_hash_entry *) entry; ! ! /* Allocate the structure if it has not already been allocated by a ! subclass. */ ! if (ret == (struct elf_m32r_link_hash_entry *) NULL) ! ret = ((struct elf_m32r_link_hash_entry *) ! bfd_hash_allocate (table, ! sizeof (struct elf_m32r_link_hash_entry))); ! if (ret == (struct elf_m32r_link_hash_entry *) NULL) ! return (struct bfd_hash_entry *) ret; ! ! /* Call the allocation method of the superclass. */ ! ret = ((struct elf_m32r_link_hash_entry *) ! _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, ! table, string)); ! if (ret != (struct elf_m32r_link_hash_entry *) NULL) ! { ! struct elf_m32r_link_hash_entry *eh; ! ! eh = (struct elf_m32r_link_hash_entry *) ret; ! eh->dyn_relocs = NULL; ! // eh->gotplt_refcount = 0; ! /* eh->pcrel_relocs_copied = NULL; FIXME */ ! } ! ! return (struct bfd_hash_entry *) ret; ! } ! ! /* Create an m32r ELF linker hash table. */ ! static struct bfd_link_hash_table *m32r_elf_link_hash_table_create (bfd *); ! ! static struct bfd_link_hash_table * ! m32r_elf_link_hash_table_create (abfd) ! bfd *abfd; ! { ! struct elf_m32r_link_hash_table *ret; ! bfd_size_type amt = sizeof (struct elf_m32r_link_hash_table); ! ! ret = (struct elf_m32r_link_hash_table *) bfd_malloc (amt); ! if (ret == (struct elf_m32r_link_hash_table *) NULL) ! return NULL; ! ! if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, ! m32r_elf_link_hash_newfunc)) ! { ! free (ret); ! return NULL; ! } ! ! ret->sgot = NULL; ! ret->sgotplt = NULL; ! ret->srelgot = NULL; ! ret->splt = NULL; ! ret->srelplt = NULL; ! ret->sdynbss = NULL; ! ret->srelbss = NULL; ! ret->sym_sec.abfd = NULL; ! ! return &ret->root.root; ! } ! ! /* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up ! shortcuts to them in our hash table. */ ! static bfd_boolean create_got_section (bfd *, struct bfd_link_info *); ! ! static bfd_boolean ! create_got_section (dynobj, info) ! bfd *dynobj; ! struct bfd_link_info *info; ! { ! struct elf_m32r_link_hash_table *htab; ! ! if (! _bfd_elf_create_got_section (dynobj, info)) ! return FALSE; ! ! htab = m32r_elf_hash_table (info); ! htab->sgot = bfd_get_section_by_name (dynobj, ".got"); ! htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); ! if (! htab->sgot || ! htab->sgotplt) ! abort (); ! ! htab->srelgot = bfd_make_section (dynobj, ".rela.got"); ! if (htab->srelgot == NULL ! || ! bfd_set_section_flags (dynobj, htab->srelgot, ! (SEC_ALLOC ! | SEC_LOAD ! | SEC_HAS_CONTENTS ! | SEC_IN_MEMORY ! | SEC_LINKER_CREATED ! | SEC_READONLY)) ! || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) ! return FALSE; ! ! return TRUE; ! } ! ! /* Create dynamic sections when linking against a dynamic object. */ ! ! static bfd_boolean ! m32r_elf_create_dynamic_sections (abfd, info) ! bfd *abfd; ! struct bfd_link_info *info; ! { ! struct elf_m32r_link_hash_table *htab; ! flagword flags, pltflags; ! register asection *s; ! const struct elf_backend_data *bed = get_elf_backend_data (abfd); ! int ptralign = 2; /* 32bit */ ! ! htab = m32r_elf_hash_table (info); ! ! /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and ! .rel[a].bss sections. */ ! ! flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ! | SEC_LINKER_CREATED); ! ! pltflags = flags; ! pltflags |= SEC_CODE; ! if (bed->plt_not_loaded) ! pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS); ! if (bed->plt_readonly) ! pltflags |= SEC_READONLY; ! ! s = bfd_make_section (abfd, ".plt"); ! htab->splt = s; ! if (s == NULL ! || ! bfd_set_section_flags (abfd, s, pltflags) ! || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) ! return FALSE; ! ! if (bed->want_plt_sym) ! { ! /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the ! .plt section. */ ! struct elf_link_hash_entry *h = NULL; ! if (! (_bfd_generic_link_add_one_symbol ! (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, ! (bfd_vma) 0, (const char *) NULL, FALSE, ! get_elf_backend_data (abfd)->collect, ! (struct bfd_link_hash_entry **) &h))) ! return FALSE; ! h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; ! h->type = STT_OBJECT; ! ! if (info->shared ! && ! _bfd_elf_link_record_dynamic_symbol (info, h)) ! return FALSE; ! } ! ! s = bfd_make_section (abfd, ! bed->default_use_rela_p ? ".rela.plt" : ".rel.plt"); ! htab->srelplt = s; ! if (s == NULL ! || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) ! || ! bfd_set_section_alignment (abfd, s, ptralign)) ! return FALSE; ! ! if (htab->sgot == NULL ! && ! create_got_section (abfd, info)) ! return FALSE; ! ! { ! const char *secname; ! char *relname; ! flagword secflags; ! asection *sec; ! ! for (sec = abfd->sections; sec; sec = sec->next) ! { ! secflags = bfd_get_section_flags (abfd, sec); ! if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) ! || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) ! continue; ! secname = bfd_get_section_name (abfd, sec); ! relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); ! strcpy (relname, ".rela"); ! strcat (relname, secname); ! if (bfd_get_section_by_name (abfd, secname)) ! continue; ! s = bfd_make_section (abfd, relname); ! if (s == NULL ! || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) ! || ! bfd_set_section_alignment (abfd, s, ptralign)) ! return FALSE; ! } ! } ! ! if (bed->want_dynbss) ! { ! /* The .dynbss section is a place to put symbols which are defined ! by dynamic objects, are referenced by regular objects, and are ! not functions. We must allocate space for them in the process ! image and use a R_*_COPY reloc to tell the dynamic linker to ! initialize them at run time. The linker script puts the .dynbss ! section into the .bss section of the final image. */ ! s = bfd_make_section (abfd, ".dynbss"); ! htab->sdynbss = s; ! if (s == NULL ! || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) ! return FALSE; ! /* The .rel[a].bss section holds copy relocs. This section is not ! normally needed. We need to create it here, though, so that the ! linker will map it to an output section. We can't just create it ! only if we need it, because we will not know whether we need it ! until we have seen all the input files, and the first time the ! main linker code calls BFD after examining all the input files ! (size_dynamic_sections) the input sections have already been ! mapped to the output sections. If the section turns out not to ! be needed, we can discard it later. We will never need this ! section when generating a shared object, since they do not use ! copy relocs. */ ! if (! info->shared) ! { ! s = bfd_make_section (abfd, ! (bed->default_use_rela_p ! ? ".rela.bss" : ".rel.bss")); ! htab->srelbss = s; ! if (s == NULL ! || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) ! || ! bfd_set_section_alignment (abfd, s, ptralign)) ! return FALSE; ! } ! } ! ! return TRUE; ! } ! ! /* Copy the extra info we tack onto an elf_link_hash_entry. */ ! static void m32r_elf_copy_indirect_symbol (const struct elf_backend_data *, ! struct elf_link_hash_entry *, ! struct elf_link_hash_entry *); ! ! static void ! m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed, ! struct elf_link_hash_entry *dir, ! struct elf_link_hash_entry *ind) ! { ! struct elf_m32r_link_hash_entry *edir, *eind; ! ! edir = (struct elf_m32r_link_hash_entry *) dir; ! eind = (struct elf_m32r_link_hash_entry *) ind; ! ! if (eind->dyn_relocs != NULL) ! { ! if (edir->dyn_relocs != NULL) ! { ! struct elf_m32r_dyn_relocs **pp; ! struct elf_m32r_dyn_relocs *p; ! ! if (ind->root.type == bfd_link_hash_indirect) ! abort (); ! ! /* Add reloc counts against the weak sym to the strong sym ! list. Merge any entries against the same section. */ ! for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) ! { ! struct elf_m32r_dyn_relocs *q; ! ! for (q = edir->dyn_relocs; q != NULL; q = q->next) ! if (q->sec == p->sec) ! { ! q->pc_count += p->pc_count; ! q->count += p->count; ! *pp = p->next; ! break; ! } ! if (q == NULL) ! pp = &p->next; ! } ! *pp = edir->dyn_relocs; ! } ! ! edir->dyn_relocs = eind->dyn_relocs; ! eind->dyn_relocs = NULL; ! } ! ! // if (ind->root.type == bfd_link_hash_indirect ! // && dir->got.refcount <= 0) ! // { ! // edir->tls_type = eind->tls_type; ! // eind->tls_type = GOT_UNKNOWN; ! // } ! _bfd_elf_link_hash_copy_indirect (bed, dir, ind); ! } ! ! ! /* Adjust a symbol defined by a dynamic object and referenced by a ! regular object. The current definition is in some section of the ! dynamic object, but we're not including those sections. We have to ! change the definition to something the rest of the link can ! understand. */ ! ! static bfd_boolean ! m32r_elf_adjust_dynamic_symbol (info, h) ! struct bfd_link_info *info; ! struct elf_link_hash_entry *h; ! { ! struct elf_m32r_link_hash_table *htab; ! struct elf_m32r_link_hash_entry *eh; ! struct elf_m32r_dyn_relocs *p; ! bfd *dynobj; ! asection *s; ! unsigned int power_of_two; ! ! #ifdef DEBUG_PIC ! printf("m32r_elf_adjust_dynamic_symbol()\n"); ! #endif ! ! dynobj = elf_hash_table (info)->dynobj; ! ! /* Make sure we know what is going on here. */ ! BFD_ASSERT (dynobj != NULL ! && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) ! || h->weakdef != NULL ! || ((h->elf_link_hash_flags ! & ELF_LINK_HASH_DEF_DYNAMIC) != 0 ! && (h->elf_link_hash_flags ! & ELF_LINK_HASH_REF_REGULAR) != 0 ! && (h->elf_link_hash_flags ! & ELF_LINK_HASH_DEF_REGULAR) == 0))); ! ! ! /* If this is a function, put it in the procedure linkage table. We ! will fill in the contents of the procedure linkage table later, ! when we know the address of the .got section. */ ! if (h->type == STT_FUNC ! || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) ! { ! if (! info->shared ! && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 ! && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 ! && h->root.type != bfd_link_hash_undefweak ! && h->root.type != bfd_link_hash_undefined) ! { ! /* This case can occur if we saw a PLT reloc in an input ! file, but the symbol was never referred to by a dynamic ! object. In such a case, we don't actually need to build ! a procedure linkage table, and we can just do a PCREL ! reloc instead. */ ! h->plt.offset = (bfd_vma) -1; ! h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; ! } ! ! return TRUE; ! } ! else ! h->plt.offset = (bfd_vma) -1; ! ! /* If this is a weak symbol, and there is a real definition, the ! processor independent code will have arranged for us to see the ! real definition first, and we can just use the same value. */ ! if (h->weakdef != NULL) ! { ! BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined ! || h->weakdef->root.type == bfd_link_hash_defweak); ! h->root.u.def.section = h->weakdef->root.u.def.section; ! h->root.u.def.value = h->weakdef->root.u.def.value; ! return TRUE; ! } ! ! /* This is a reference to a symbol defined by a dynamic object which ! is not a function. */ ! ! /* If we are creating a shared library, we must presume that the ! only references to the symbol are via the global offset table. ! For such cases we need not do anything here; the relocations will ! be handled correctly by relocate_section. */ ! if (info->shared) ! return TRUE; ! ! /* If there are no references to this symbol that do not use the ! GOT, we don't need to generate a copy reloc. */ ! if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) ! return TRUE; ! ! /* If -z nocopyreloc was given, we won't generate them either. */ ! if (info->nocopyreloc) ! { ! h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; ! return TRUE; ! } ! ! eh = (struct elf_m32r_link_hash_entry *) h; ! for (p = eh->dyn_relocs; p != NULL; p = p->next) ! { ! s = p->sec->output_section; ! if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0) ! break; ! } ! ! /* If we didn't find any dynamic relocs in sections which needs the ! copy reloc, then we'll be keeping the dynamic relocs and avoiding ! the copy reloc. */ ! if (p == NULL) ! { ! h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; ! return TRUE; ! } ! ! /* We must allocate the symbol in our .dynbss section, which will ! become part of the .bss section of the executable. There will be ! an entry for this symbol in the .dynsym section. The dynamic ! object will contain position independent code, so all references ! from the dynamic object to this symbol will go through the global ! offset table. The dynamic linker will use the .dynsym entry to ! determine the address it must put in the global offset table, so ! both the dynamic object and the regular object will refer to the ! same memory location for the variable. */ ! ! htab = m32r_elf_hash_table (info); ! s = htab->sdynbss; ! BFD_ASSERT (s != NULL); ! ! /* We must generate a R_M32R_COPY reloc to tell the dynamic linker ! to copy the initial value out of the dynamic object and into the ! runtime process image. We need to remember the offset into the ! .rela.bss section we are going to use. */ ! if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) ! { ! asection *srel; ! ! srel = htab->srelbss; ! BFD_ASSERT (srel != NULL); ! srel->_raw_size += sizeof (Elf32_External_Rela); ! h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; ! } ! ! /* We need to figure out the alignment required for this symbol. I ! have no idea how ELF linkers handle this. */ ! power_of_two = bfd_log2 (h->size); ! if (power_of_two > 3) ! power_of_two = 3; ! ! /* Apply the required alignment. */ ! s->_raw_size = BFD_ALIGN (s->_raw_size, ! (bfd_size_type) (1 << power_of_two)); ! if (power_of_two > bfd_get_section_alignment (dynobj, s)) ! { ! if (! bfd_set_section_alignment (dynobj, s, power_of_two)) ! return FALSE; ! } ! ! /* Define the symbol as being at this point in the section. */ ! h->root.u.def.section = s; ! h->root.u.def.value = s->_raw_size; ! ! /* Increment the section size to make room for the symbol. */ ! s->_raw_size += h->size; ! ! return TRUE; ! } ! ! /* This is the condition under which finish_dynamic_symbol will be called ! from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol ! routine, we'll need to do something about initializing any .plt and .got ! entries in relocate_section. */ ! #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ ! ((DYN) \ ! && ((INFO)->shared \ ! || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ ! && ((H)->dynindx != -1 \ ! || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) ! ! /* Allocate space in .plt, .got and associated reloc sections for ! dynamic relocs. */ ! ! static bfd_boolean ! allocate_dynrelocs (h, inf) ! struct elf_link_hash_entry *h; ! PTR inf; ! { ! struct bfd_link_info *info; ! struct elf_m32r_link_hash_table *htab; ! struct elf_m32r_link_hash_entry *eh; ! struct elf_m32r_dyn_relocs *p; ! ! if (h->root.type == bfd_link_hash_indirect) ! return TRUE; ! ! if (h->root.type == bfd_link_hash_warning) ! /* When warning symbols are created, they **replace** the "real" ! entry in the hash table, thus we never get to see the real ! symbol in a hash traversal. So look at it now. */ ! h = (struct elf_link_hash_entry *) h->root.u.i.link; ! ! info = (struct bfd_link_info *) inf; ! htab = m32r_elf_hash_table (info); ! ! eh = (struct elf_m32r_link_hash_entry *) h; ! // if ((h->got.refcount > 0 ! // || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) ! // && eh->gotplt_refcount > 0) ! // { ! // /* The symbol has been forced local, or we have some direct got refs, ! // so treat all the gotplt refs as got refs. */ ! // h->got.refcount += eh->gotplt_refcount; ! // if (h->plt.refcount >= eh->gotplt_refcount) ! // h->plt.refcount -= eh->gotplt_refcount; ! // } ! ! if (htab->root.dynamic_sections_created ! && h->plt.refcount > 0) ! { ! /* Make sure this symbol is output as a dynamic symbol. ! Undefined weak syms won't yet be marked as dynamic. */ ! if (h->dynindx == -1 ! && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) ! { ! if (! bfd_elf32_link_record_dynamic_symbol (info, h)) ! return FALSE; ! } ! ! if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) ! { ! asection *s = htab->splt; ! ! /* If this is the first .plt entry, make room for the special ! first entry. */ ! if (s->_raw_size == 0) ! s->_raw_size += PLT_ENTRY_SIZE; ! ! h->plt.offset = s->_raw_size; ! ! /* If this symbol is not defined in a regular file, and we are ! not generating a shared library, then set the symbol to this ! location in the .plt. This is required to make function ! pointers compare as equal between the normal executable and ! the shared library. */ ! if (! info->shared ! && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) ! { ! h->root.u.def.section = s; ! h->root.u.def.value = h->plt.offset; ! } ! ! /* Make room for this entry. */ ! s->_raw_size += PLT_ENTRY_SIZE; ! ! /* We also need to make an entry in the .got.plt section, which ! will be placed in the .got section by the linker script. */ ! htab->sgotplt->_raw_size += 4; ! ! /* We also need to make an entry in the .rel.plt section. */ ! htab->srelplt->_raw_size += sizeof (Elf32_External_Rela); ! } ! else ! { ! h->plt.offset = (bfd_vma) -1; ! h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; ! } ! } ! else ! { ! h->plt.offset = (bfd_vma) -1; ! h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; ! } ! ! if (h->got.refcount > 0) ! { ! asection *s; ! bfd_boolean dyn; ! ! /* Make sure this symbol is output as a dynamic symbol. ! Undefined weak syms won't yet be marked as dynamic. */ ! if (h->dynindx == -1 ! && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) ! { ! if (! bfd_elf32_link_record_dynamic_symbol (info, h)) ! return FALSE; ! } ! ! s = htab->sgot; ! ! h->got.offset = s->_raw_size; ! s->_raw_size += 4; ! dyn = htab->root.dynamic_sections_created; ! if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) ! htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); ! } ! else ! h->got.offset = (bfd_vma) -1; ! ! if (eh->dyn_relocs == NULL) ! return TRUE; ! ! /* In the shared -Bsymbolic case, discard space allocated for ! dynamic pc-relative relocs against symbols which turn out to be ! defined in regular objects. For the normal shared case, discard ! space for pc-relative relocs that have become local due to symbol ! visibility changes. */ ! ! if (info->shared) ! { ! if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 ! && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 ! || info->symbolic)) ! { ! struct elf_m32r_dyn_relocs **pp; ! for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) ! { ! p->count -= p->pc_count; ! p->pc_count = 0; ! if (p->count == 0) ! *pp = p->next; ! else ! pp = &p->next; ! } ! } ! } ! else ! { ! /* For the non-shared case, discard space for relocs against ! symbols which turn out to need copy relocs or are not ! dynamic. */ ! ! if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 ! && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 ! && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) ! || (htab->root.dynamic_sections_created ! && (h->root.type == bfd_link_hash_undefweak ! || h->root.type == bfd_link_hash_undefined)))) ! { ! /* Make sure this symbol is output as a dynamic symbol. ! Undefined weak syms won't yet be marked as dynamic. */ ! if (h->dynindx == -1 ! && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) ! { ! if (! bfd_elf32_link_record_dynamic_symbol (info, h)) ! return FALSE; ! } ! ! /* If that succeeded, we know we'll be keeping all the ! relocs. */ ! if (h->dynindx != -1) ! goto keep; ! } ! ! eh->dyn_relocs = NULL; ! ! keep: ; ! } ! ! /* Finally, allocate space. */ ! for (p = eh->dyn_relocs; p != NULL; p = p->next) ! { ! asection *sreloc = elf_section_data (p->sec)->sreloc; ! sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela); ! } ! ! return TRUE; ! } ! /* Find any dynamic relocs that apply to read-only sections. */ ! ! static bfd_boolean ! readonly_dynrelocs (h, inf) ! struct elf_link_hash_entry *h; ! PTR inf; ! { ! struct elf_m32r_link_hash_entry *eh; ! struct elf_m32r_dyn_relocs *p; ! ! if (h->root.type == bfd_link_hash_warning) ! h = (struct elf_link_hash_entry *) h->root.u.i.link; ! ! eh = (struct elf_m32r_link_hash_entry *) h; ! for (p = eh->dyn_relocs; p != NULL; p = p->next) ! { ! asection *s = p->sec->output_section; ! ! if (s != NULL && (s->flags & SEC_READONLY) != 0) ! { ! struct bfd_link_info *info = (struct bfd_link_info *) inf; ! ! info->flags |= DF_TEXTREL; ! /* Not an error, just cut short the traversal. */ ! return FALSE; ! } ! } ! return TRUE; ! } ! /* Set the sizes of the dynamic sections. */ ! ! static bfd_boolean ! m32r_elf_size_dynamic_sections (output_bfd, info) ! bfd *output_bfd ATTRIBUTE_UNUSED; ! struct bfd_link_info *info; ! { ! struct elf_m32r_link_hash_table *htab; ! bfd *dynobj; ! asection *s; ! bfd_boolean relocs; ! bfd *ibfd; ! #ifdef DEBUG_PIC ! printf("m32r_elf_size_dynamic_sections()\n"); ! #endif ! htab = m32r_elf_hash_table (info); ! dynobj = htab->root.dynobj; ! BFD_ASSERT (dynobj != NULL); ! if (htab->root.dynamic_sections_created) { ! /* Set the contents of the .interp section to the interpreter. */ ! if (! info->shared) ! { ! s = bfd_get_section_by_name (dynobj, ".interp"); ! BFD_ASSERT (s != NULL); ! s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; ! s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; ! } } ! /* Set up .got offsets for local syms, and space for local dynamic ! relocs. */ ! for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) ! { ! bfd_signed_vma *local_got; ! bfd_signed_vma *end_local_got; ! bfd_size_type locsymcount; ! Elf_Internal_Shdr *symtab_hdr; ! asection *srel; ! if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) ! continue; ! for (s = ibfd->sections; s != NULL; s = s->next) ! { ! struct elf_m32r_dyn_relocs *p; ! ! for (p = ((struct elf_m32r_dyn_relocs *) ! elf_section_data (s)->local_dynrel); ! p != NULL; ! p = p->next) ! { ! if (! bfd_is_abs_section (p->sec) ! && bfd_is_abs_section (p->sec->output_section)) ! { ! /* Input section has been discarded, either because ! it is a copy of a linkonce section or due to ! linker script /DISCARD/, so we'll be discarding ! the relocs too. */ ! } ! else if (p->count != 0) ! { ! srel = elf_section_data (p->sec)->sreloc; ! srel->_raw_size += p->count * sizeof (Elf32_External_Rela); ! if ((p->sec->output_section->flags & SEC_READONLY) != 0) ! info->flags |= DF_TEXTREL; ! } ! } ! } ! ! local_got = elf_local_got_refcounts (ibfd); ! if (!local_got) ! continue; ! ! symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; ! locsymcount = symtab_hdr->sh_info; ! end_local_got = local_got + locsymcount; ! s = htab->sgot; ! srel = htab->srelgot; ! for (; local_got < end_local_got; ++local_got) ! { ! if (*local_got > 0) ! { ! *local_got = s->_raw_size; ! s->_raw_size += 4; ! if (info->shared) ! srel->_raw_size += sizeof (Elf32_External_Rela); ! } ! else ! *local_got = (bfd_vma) -1; ! } ! } ! ! /* Allocate global sym .plt and .got entries, and space for global ! sym dynamic relocs. */ ! elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info); ! ! /* We now have determined the sizes of the various dynamic sections. ! Allocate memory for them. */ ! relocs = FALSE; ! for (s = dynobj->sections; s != NULL; s = s->next) { ! if ((s->flags & SEC_LINKER_CREATED) == 0) ! continue; ! if (s == htab->splt ! || s == htab->sgot ! || s == htab->sgotplt) ! { ! /* Strip this section if we don't need it; see the ! comment below. */ ! } ! else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) ! { ! if (s->_raw_size != 0 && s != htab->srelplt) ! relocs = TRUE; ! ! /* We use the reloc_count field as a counter if we need ! to copy relocs into the output file. */ ! s->reloc_count = 0; ! } else + { + /* It's not one of our sections, so don't allocate space. */ + continue; + } + + if (s->_raw_size == 0) + { + /* If we don't need this section, strip it from the + output file. This is mostly to handle .rela.bss and + .rela.plt. We must create both sections in + create_dynamic_sections, because they must be created + before the linker maps input sections to output + sections. The linker does that before + adjust_dynamic_symbol is called, and it is that + function which decides whether anything needs to go + into these sections. */ + _bfd_strip_section_from_output (info, s); + continue; + } + + /* Allocate memory for the section contents. We use bfd_zalloc + here in case unused entries are not reclaimed before the + section's contents are written out. This should not happen, + but this way if it does, we get a R_M32R_NONE reloc instead + of garbage. */ + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); + if (s->contents == NULL) + return FALSE; + } + + if (htab->root.dynamic_sections_created) + { + /* Add some entries to the .dynamic section. We fill in the + values later, in m32r_elf_finish_dynamic_sections, but we + must add the entries now so that we get the correct size for + the .dynamic section. The DT_DEBUG entry is filled in by the + dynamic linker and used by the debugger. */ + #define add_dynamic_entry(TAG, VAL) \ + bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) + + if (! info->shared) { ! if (! add_dynamic_entry (DT_DEBUG, 0)) ! return FALSE; } + + if (htab->splt->_raw_size != 0) + { + if (! add_dynamic_entry (DT_PLTGOT, 0) + || ! add_dynamic_entry (DT_PLTRELSZ, 0) + || ! add_dynamic_entry (DT_PLTREL, DT_RELA) + || ! add_dynamic_entry (DT_JMPREL, 0)) + return FALSE; + } + + if (relocs) + { + if (! add_dynamic_entry (DT_RELA, 0) + || ! add_dynamic_entry (DT_RELASZ, 0) + || ! add_dynamic_entry (DT_RELAENT, + sizeof (Elf32_External_Rela))) + return FALSE; + + /* If any dynamic relocs apply to a read-only section, + then we need a DT_TEXTREL entry. */ + if ((info->flags & DF_TEXTREL) == 0) + elf_link_hash_traverse (&htab->root, readonly_dynrelocs, + (PTR) info); + + if ((info->flags & DF_TEXTREL) != 0) + { + if (! add_dynamic_entry (DT_TEXTREL, 0)) + return FALSE; + } + } } ! #undef add_dynamic_entry ! ! return TRUE; } /* Relocate an M32R/D ELF section. There is some attempt to make this function usable for many architectures, both for RELA and REL type relocs, if only to serve as a learning tool. *************** *** 986,995 **** /* Assume success. */ bfd_boolean ret = TRUE; ! #if !USE_REL ! if (info->relocatable) ! return TRUE; ! #endif rel = relocs; relend = relocs + input_section->reloc_count; --- 2534,2550 ---- /* Assume success. */ bfd_boolean ret = TRUE; ! struct elf_m32r_link_hash_table *htab = m32r_elf_hash_table (info); ! bfd *dynobj; ! bfd_vma *local_got_offsets; ! asection *sgot, *splt, *sreloc; ! ! dynobj = htab->root.dynobj; ! local_got_offsets = elf_local_got_offsets (input_bfd); ! ! sgot = htab->sgot; ! splt = htab->splt; ! sreloc = NULL; rel = relocs; relend = relocs + input_section->reloc_count; *************** *** 998,1015 **** int r_type; reloc_howto_type *howto; unsigned long r_symndx; /* We can't modify r_addend here as elf_link_input_bfd has an assert to ! ensure it's zero (we use REL relocs, not RELA). Therefore this ! should be assigning zero to `addend', but for clarity we use ! `r_addend'. */ bfd_vma addend = rel->r_addend; bfd_vma offset = rel->r_offset; - struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; const char *sym_name; bfd_reloc_status_type r; const char *errmsg = NULL; h = NULL; r_type = ELF32_R_TYPE (rel->r_info); --- 2553,2571 ---- int r_type; reloc_howto_type *howto; unsigned long r_symndx; + struct elf_link_hash_entry *h; /* We can't modify r_addend here as elf_link_input_bfd has an assert to ! ensure it's zero (we use REL relocs, not RELA). Therefore this ! should be assigning zero to `addend', but for clarity we use ! `r_addend'. */ bfd_vma addend = rel->r_addend; bfd_vma offset = rel->r_offset; Elf_Internal_Sym *sym; asection *sec; const char *sym_name; bfd_reloc_status_type r; const char *errmsg = NULL; + bfd_boolean use_rel = FALSE; h = NULL; r_type = ELF32_R_TYPE (rel->r_info); *************** *** 1024,1037 **** } if (r_type == R_M32R_GNU_VTENTRY ! || r_type == R_M32R_GNU_VTINHERIT) continue; howto = m32r_elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); ! #if USE_REL ! if (info->relocatable) { /* This is a relocatable link. We don't have to change anything, unless the reloc is against a section symbol, --- 2580,2598 ---- } if (r_type == R_M32R_GNU_VTENTRY ! || r_type == R_M32R_GNU_VTINHERIT ! || r_type == R_M32R_NONE ! || r_type == R_M32R_RELA_GNU_VTENTRY ! || r_type == R_M32R_RELA_GNU_VTINHERIT) continue; + if (r_type <= R_M32R_GNU_VTENTRY) + use_rel = TRUE; + howto = m32r_elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); ! if (info->relocatable && (use_rel == TRUE)) { /* This is a relocatable link. We don't have to change anything, unless the reloc is against a section symbol, *************** *** 1092,1104 **** } } else - #endif /* USE_REL */ { bfd_vma relocation; /* This is a final link. */ sym = NULL; sec = NULL; if (r_symndx < symtab_hdr->sh_info) { --- 2653,2665 ---- } } else { bfd_vma relocation; /* This is a final link. */ sym = NULL; sec = NULL; + h = NULL; if (r_symndx < symtab_hdr->sh_info) { *************** *** 1106,1125 **** sym = local_syms + r_symndx; sec = local_sections[r_symndx]; sym_name = ""; ! #if !USE_REL ! relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); ! addend = rel->r_addend; ! #else ! /* FIXME: This won't handle local relocations against SEC_MERGE ! symbols. See elf32-i386.c for how to do this. */ ! relocation = (sec->output_section->vma ! + sec->output_offset ! + sym->st_value); ! #endif } else { /* External symbol. */ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) --- 2667,2703 ---- sym = local_syms + r_symndx; sec = local_sections[r_symndx]; sym_name = ""; ! ! if (use_rel == FALSE) ! { ! relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); ! addend = rel->r_addend; ! ! if (info->relocatable) ! { ! /* This is a relocatable link. We don't have to change ! anything, unless the reloc is against a section symbol, ! in which case we have to adjust according to where the ! section symbol winds up in the output section. */ ! if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) ! rel->r_addend += sec->output_offset + sym->st_value; ! ! continue; ! } ! } ! else ! { ! relocation = (sec->output_section->vma ! + sec->output_offset ! + sym->st_value); ! } } else { /* External symbol. */ + if (info->relocatable && (use_rel == FALSE)) + continue; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) *************** *** 1129,1137 **** if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; ! if (sec->output_section == NULL) ! relocation = 0; else relocation = (h->root.u.def.value + sec->output_section->vma --- 2707,2770 ---- if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { + bfd_boolean dyn; sec = h->root.u.def.section; ! ! dyn = htab->root.dynamic_sections_created; ! sec = h->root.u.def.section; ! if (r_type == R_M32R_GOTPC24 ! || (r_type == R_M32R_GOTPC_HI_ULO ! || r_type == R_M32R_GOTPC_HI_SLO ! || r_type == R_M32R_GOTPC_LO) ! || (r_type == R_M32R_26_PLTREL ! && h->plt.offset != (bfd_vma) -1) ! || ((r_type == R_M32R_GOT24 ! || r_type == R_M32R_GOT16_HI_ULO ! || r_type == R_M32R_GOT16_HI_SLO ! || r_type == R_M32R_GOT16_LO) ! && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) ! && (! info->shared ! || (! info->symbolic && h->dynindx != -1) ! || (h->elf_link_hash_flags ! & ELF_LINK_HASH_DEF_REGULAR) == 0)) ! || (info->shared ! && ((! info->symbolic && h->dynindx != -1) ! || (h->elf_link_hash_flags ! & ELF_LINK_HASH_DEF_REGULAR) == 0) ! && (((r_type == R_M32R_16_RELA ! || r_type == R_M32R_32_RELA ! || r_type == R_M32R_24_RELA ! || r_type == R_M32R_HI16_ULO_RELA ! || r_type == R_M32R_HI16_SLO_RELA ! || r_type == R_M32R_LO16_RELA) ! && (h->elf_link_hash_flags ! & ELF_LINK_FORCED_LOCAL) == 0) ! || r_type == R_M32R_10_PCREL_RELA ! || r_type == R_M32R_18_PCREL_RELA ! || r_type == R_M32R_26_PCREL_RELA) ! && ((input_section->flags & SEC_ALLOC) != 0 ! /* DWARF will emit R_M32R_16(24,32) relocations ! in its sections against symbols defined ! externally in shared libraries. We can't do ! anything with them here. */ ! || ((input_section->flags & SEC_DEBUGGING) != 0 ! && (h->elf_link_hash_flags ! & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))) ! { ! /* In these cases, we don't need the relocation ! value. We check specially because in some ! obscure cases sec->output_section will be NULL. */ ! relocation = 0; ! } ! else if (sec->output_section == NULL) ! { ! (*_bfd_error_handler) ! (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), ! bfd_get_filename (input_bfd), h->root.root.string, ! bfd_get_section_name (input_bfd, input_section)); ! ! relocation = 0; ! } else relocation = (h->root.u.def.value + sec->output_section->vma *************** *** 1139,1149 **** } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, ! input_section, offset, TRUE))) return FALSE; relocation = 0; } --- 2772,2788 ---- } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; + else if (info->shared + && (!info->symbolic) + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) + relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, ! input_section, offset, ! (!info->shared ! || ELF_ST_VISIBILITY (h->other))))) return FALSE; relocation = 0; } *************** *** 1158,1168 **** switch ((int) r_type) { case (int) R_M32R_10_PCREL : r = m32r_elf_do_10_pcrel_reloc (input_bfd, howto, input_section, contents, offset, sec, relocation, addend); ! break; case (int) R_M32R_HI16_SLO : case (int) R_M32R_HI16_ULO : --- 2797,3079 ---- switch ((int) r_type) { + case R_M32R_GOTPC24: + /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation + ld24 rx,#_GLOBAL_OFFSET_TABLE_ + */ + relocation = sgot->output_section->vma; + break; + + case R_M32R_GOTPC_HI_ULO: + case R_M32R_GOTPC_HI_SLO: + case R_M32R_GOTPC_LO: + { + /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation + bl .+4 + seth rx,#high(_GLOBAL_OFFSET_TABLE_) + or3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) + or + bl .+4 + seth rx,#shigh(_GLOBAL_OFFSET_TABLE_) + add3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) + */ + relocation = sgot->output_section->vma; + relocation -= (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); + if ((r_type == R_M32R_GOTPC_HI_SLO) + && ((relocation + rel->r_addend) & 0x8000)) + rel->r_addend += 0x10000; + + break; + } + case R_M32R_GOT16_HI_ULO: + case R_M32R_GOT16_HI_SLO: + case R_M32R_GOT16_LO: + /* Fall through. */ + case R_M32R_GOT24: + /* Relocation is to the entry for this symbol in the global + offset table. */ + BFD_ASSERT (sgot != NULL); + + if (h != NULL) + { + bfd_boolean dyn; + bfd_vma off; + + off = h->got.offset; + BFD_ASSERT (off != (bfd_vma) -1); + + dyn = htab->root.dynamic_sections_created; + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) + || (info->shared + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + { + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of 4, we use the + least significant bit to record whether we have + initialized it already. + + When doing a dynamic link, we create a .rela.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, + sgot->contents + off); + h->got.offset |= 1; + } + } + + relocation = sgot->output_offset + off; + } + else + { + bfd_vma off; + bfd_byte *loc; + + BFD_ASSERT (local_got_offsets != NULL + && local_got_offsets[r_symndx] != (bfd_vma) -1); + + off = local_got_offsets[r_symndx]; + + /* The offset must always be a multiple of 4. We use + the least significant bit to record whether we have + already processed this entry. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, sgot->contents + off); + + if (info->shared) + { + asection *srelgot; + Elf_Internal_Rela outrel; + + /* We need to generate a R_M32R_RELATIVE reloc + for the dynamic linker. */ + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (srelgot != NULL); + + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + off); + outrel.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); + outrel.r_addend = relocation; + loc = srelgot->contents; + loc += srelgot->reloc_count * sizeof(Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc); + ++srelgot->reloc_count; + } + + local_got_offsets[r_symndx] |= 1; + } + + relocation = sgot->output_offset + off; + } + if ((r_type == R_M32R_GOT16_HI_SLO) + && ((relocation + rel->r_addend) & 0x8000)) + rel->r_addend += 0x10000; + + break; + + case R_M32R_26_PLTREL: + /* Relocation is to the entry for this symbol in the + procedure linkage table. */ + + /* The native assembler will generate a 26_PLTREL reloc + for a local symbol if you assemble a call from one + section to another when using -K pic. */ + if (h == NULL) + break; + + //if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL + // || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + // break; + if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) + break; + + if (h->plt.offset == (bfd_vma) -1) + { + /* We didn't make a PLT entry for this symbol. This + happens when statically linking PIC code, or when + using -Bsymbolic. */ + break; + } + + relocation = (splt->output_section->vma + + splt->output_offset + + h->plt.offset); + break; + + case R_M32R_HI16_SLO_RELA: + { + if ((relocation + rel->r_addend) & 0x8000) + { + rel->r_addend += 0x10000; + } + } + /* Fall through. */ + case R_M32R_16_RELA: + case R_M32R_24_RELA: + case R_M32R_32_RELA: + case R_M32R_18_PCREL_RELA: + case R_M32R_26_PCREL_RELA: + case R_M32R_HI16_ULO_RELA: + case R_M32R_LO16_RELA: + case R_M32R_SDA16_RELA: + if (info->shared + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC) != 0 + && ((r_type != R_M32R_18_PCREL_RELA + && r_type != R_M32R_26_PCREL_RELA) + || (h != NULL + && h->dynindx != -1 + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + { + Elf_Internal_Rela outrel; + bfd_boolean skip, relocate; + bfd_byte *loc; + + /* When generating a shared object, these relocations + are copied into the output file to be resolved at run + time. */ + + if (sreloc == NULL) + { + const char *name; + + name = (bfd_elf_string_from_elf_section + (input_bfd, + elf_elfheader (input_bfd)->e_shstrndx, + elf_section_data (input_section)->rel_hdr.sh_name)); + if (name == NULL) + return FALSE; + + BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + && strcmp (bfd_get_section_name (input_bfd, + input_section), + name + 5) == 0); + + sreloc = bfd_get_section_by_name (dynobj, name); + BFD_ASSERT (sreloc != NULL); + } + + skip = FALSE; + relocate = FALSE; + + outrel.r_offset = _bfd_elf_section_offset (output_bfd, + info, + input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1) + skip = TRUE; + else if (outrel.r_offset == (bfd_vma) -2) + skip = TRUE, relocate = TRUE; + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); + + if (skip) + memset (&outrel, 0, sizeof outrel); + else if (r_type == R_M32R_18_PCREL_RELA + || r_type == R_M32R_26_PCREL_RELA) + { + BFD_ASSERT (h != NULL && h->dynindx != -1); + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + outrel.r_addend = rel->r_addend; + } + else + { + /* h->dynindx may be -1 if this symbol was marked to + become local. */ + if (h == NULL + || ((info->symbolic || h->dynindx == -1) + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0)) + { + relocate = TRUE; + outrel.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); + outrel.r_addend = relocation + rel->r_addend; + } + else + { + BFD_ASSERT (h->dynindx != -1); + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + outrel.r_addend = relocation + rel->r_addend; + } + } + + loc = sreloc->contents; + loc += sreloc->reloc_count * sizeof(Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc); + ++sreloc->reloc_count; + + /* If this reloc is against an external symbol, we do + not want to fiddle with the addend. Otherwise, we + need to include the symbol value so that it becomes + an addend for the dynamic reloc. */ + if (! relocate) + continue; + } + break; + case (int) R_M32R_10_PCREL : r = m32r_elf_do_10_pcrel_reloc (input_bfd, howto, input_section, contents, offset, sec, relocation, addend); ! goto check_reloc; case (int) R_M32R_HI16_SLO : case (int) R_M32R_HI16_ULO : *************** *** 1190,1196 **** contents, offset, relocation, addend); } ! break; case (int) R_M32R_SDA16 : { --- 3101,3108 ---- contents, offset, relocation, addend); } ! ! goto check_reloc; case (int) R_M32R_SDA16 : { *************** *** 1233,1246 **** continue; } } ! /* fall through */ - default : r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, offset, relocation, addend); ! break; } } check_reloc: --- 3145,3164 ---- continue; } } ! /* fall through */ ! ! default : /* OLD_M32R_RELOC */ r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, offset, relocation, addend); ! goto check_reloc; } + + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, rel->r_addend); + } check_reloc: *************** *** 1307,1312 **** --- 3225,3577 ---- return ret; } + + /* Finish up dynamic symbol handling. We set the contents of various + dynamic sections here. */ + static bfd_boolean + m32r_elf_finish_dynamic_symbol (output_bfd, info, h, sym) + bfd *output_bfd; + struct bfd_link_info *info; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + { + struct elf_m32r_link_hash_table *htab; + bfd *dynobj; + bfd_byte *loc; + + #ifdef DEBUG_PIC + printf("m32r_elf_finish_dynamic_symbol()\n"); + #endif + + htab = m32r_elf_hash_table (info); + dynobj = htab->root.dynobj; + + if (h->plt.offset != (bfd_vma) -1) + { + asection *splt; + asection *sgot; + asection *srela; + + bfd_vma plt_index; + bfd_vma got_offset; + Elf_Internal_Rela rela; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ + + BFD_ASSERT (h->dynindx != -1); + + splt = htab->splt; + sgot = htab->sgotplt; + srela = htab->srelplt; + BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); + + /* Get the index in the procedure linkage table which + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table is reserved. */ + plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; + + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ + got_offset = (plt_index + 3) * 4; + + /* Fill in the entry in the procedure linkage table. */ + if (! info->shared) + { + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD0b + + (((sgot->output_section->vma + + sgot->output_offset + + got_offset) >> 16) & 0xffff)), + splt->contents + h->plt.offset); + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD1b + + ((sgot->output_section->vma + + sgot->output_offset + + got_offset) & 0xffff)), + splt->contents + h->plt.offset + 4); + bfd_put_32 (output_bfd, PLT_ENTRY_WORD2, + splt->contents + h->plt.offset + 8); + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD3 + + plt_index * sizeof (Elf32_External_Rela)), + splt->contents + h->plt.offset + 12); + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD4 + + (((unsigned int) ((- (h->plt.offset + 16)) >> 2)) & 0xffffff)), + splt->contents + h->plt.offset + 16); + } + else + { + bfd_put_32 (output_bfd, + PLT_ENTRY_WORD0 + got_offset, + splt->contents + h->plt.offset); + bfd_put_32 (output_bfd, PLT_ENTRY_WORD1, + splt->contents + h->plt.offset + 4); + bfd_put_32 (output_bfd, PLT_ENTRY_WORD2, + splt->contents + h->plt.offset + 8); + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD3 + + plt_index * sizeof (Elf32_External_Rela)), + splt->contents + h->plt.offset + 12); + bfd_put_32 (output_bfd, + (PLT_ENTRY_WORD4 + + (((unsigned int) ((- (h->plt.offset + 16)) >> 2)) & 0xffffff)), + splt->contents + h->plt.offset + 16); + } + + /* Fill in the entry in the global offset table. */ + bfd_put_32 (output_bfd, + (splt->output_section->vma + + splt->output_offset + + h->plt.offset + + 12), /* same offset */ + sgot->contents + got_offset); + + /* Fill in the entry in the .rela.plt section. */ + rela.r_offset = (sgot->output_section->vma + + sgot->output_offset + + got_offset); + rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_JMP_SLOT); + rela.r_addend = 0; + loc = srela->contents; + loc += plt_index * sizeof(Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + { + /* Mark the symbol as undefined, rather than as defined in + the .plt section. Leave the value alone. */ + sym->st_shndx = SHN_UNDEF; + } + } + + if (h->got.offset != (bfd_vma) -1) + { + asection *sgot; + asection *srela; + Elf_Internal_Rela rela; + + /* This symbol has an entry in the global offset table. Set it + up. */ + + sgot = htab->sgot; + srela = htab->srelgot; + BFD_ASSERT (sgot != NULL && srela != NULL); + + rela.r_offset = (sgot->output_section->vma + + sgot->output_offset + + (h->got.offset &~ 1)); + + /* If this is a -Bsymbolic link, and the symbol is defined + locally, we just want to emit a RELATIVE reloc. Likewise if + the symbol was forced to be local because of a version file. + The entry in the global offset table will already have been + initialized in the relocate_section function. */ + if (info->shared + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + { + rela.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); + rela.r_addend = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + BFD_ASSERT((h->got.offset & 1) == 0); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); + rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_GLOB_DAT); + rela.r_addend = 0; + } + + loc = srela->contents; + loc += srela->reloc_count * sizeof(Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + ++srela->reloc_count; + } + + if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) + { + asection *s; + Elf_Internal_Rela rela; + + /* This symbols needs a copy reloc. Set it up. */ + + BFD_ASSERT (h->dynindx != -1 + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak)); + + s = bfd_get_section_by_name (h->root.u.def.section->owner, + ".rela.bss"); + BFD_ASSERT (s != NULL); + + rela.r_offset = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_COPY); + rela.r_addend = 0; + loc = s->contents; + loc += s->reloc_count * sizeof(Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + ++s->reloc_count; + } + + /* Mark some specially defined symbols as absolute. */ + if (strcmp (h->root.root.string, "_DYNAMIC") == 0 + || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + sym->st_shndx = SHN_ABS; + + return TRUE; + } + + + /* Finish up the dynamic sections. */ + + static bfd_boolean + m32r_elf_finish_dynamic_sections (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; + { + struct elf_m32r_link_hash_table *htab; + bfd *dynobj; + asection *sdyn; + asection *sgot; + + #ifdef DEBUG_PIC + printf("m32r_elf_finish_dynamic_sections()\n"); + #endif + + htab = m32r_elf_hash_table (info); + dynobj = htab->root.dynobj; + + sgot = htab->sgotplt; + sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + + if (htab->root.dynamic_sections_created) + { + asection *splt; + Elf32_External_Dyn *dyncon, *dynconend; + + BFD_ASSERT (sgot != NULL && sdyn != NULL); + + dyncon = (Elf32_External_Dyn *) sdyn->contents; + dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); + + for (; dyncon < dynconend; dyncon++) + { + Elf_Internal_Dyn dyn; + const char *name; + asection *s; + + bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); + + switch (dyn.d_tag) + { + default: + break; + + case DT_PLTGOT: + name = ".got"; + s = htab->sgot->output_section; + goto get_vma; + case DT_JMPREL: + name = ".rela.plt"; + s = htab->srelplt->output_section; + get_vma: + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_PLTRELSZ: + s = htab->srelplt->output_section; + BFD_ASSERT (s != NULL); + if (s->_cooked_size != 0) + dyn.d_un.d_val = s->_cooked_size; + else + dyn.d_un.d_val = s->_raw_size; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_RELASZ: + /* My reading of the SVR4 ABI indicates that the + procedure linkage table relocs (DT_JMPREL) should be + included in the overall relocs (DT_RELA). This is + what Solaris does. However, UnixWare can not handle + that case. Therefore, we override the DT_RELASZ entry + here to make it not include the JMPREL relocs. Since + the linker script arranges for .rela.plt to follow all + other relocation sections, we don't have to worry + about changing the DT_RELA entry. */ + if (htab->srelplt != NULL) + { + s = htab->srelplt->output_section; + if (s->_cooked_size != 0) + dyn.d_un.d_val -= s->_cooked_size; + else + dyn.d_un.d_val -= s->_raw_size; + } + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + } + } + + /* Fill in the first entry in the procedure linkage table. */ + splt = htab->splt; + if (splt && splt->_raw_size > 0) + { + if (info->shared) + { + bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD0, splt->contents); + bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD1, splt->contents + 4); + bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD2, splt->contents + 8); + bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD3, splt->contents + 12); + bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD4, splt->contents + 16); + } + else + { + unsigned long addr; + /* addr = .got + 4 */ + addr = sgot->output_section->vma + sgot->output_offset + 4; + bfd_put_32 (output_bfd, + PLT0_ENTRY_WORD0 | ((addr >> 16) & 0xffff), + splt->contents); + bfd_put_32 (output_bfd, + PLT0_ENTRY_WORD1 | (addr & 0xffff), + splt->contents + 4); + bfd_put_32 (output_bfd, PLT0_ENTRY_WORD2, splt->contents + 8); + bfd_put_32 (output_bfd, PLT0_ENTRY_WORD3, splt->contents + 12); + bfd_put_32 (output_bfd, PLT0_ENTRY_WORD4, splt->contents + 16); + } + + elf_section_data (splt->output_section)->this_hdr.sh_entsize = + PLT_ENTRY_SIZE; + } + } + + /* Fill in the first three entries in the global offset table. */ + if (sgot && sgot->_raw_size > 0) + { + if (sdyn == NULL) + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); + else + bfd_put_32 (output_bfd, + sdyn->output_section->vma + sdyn->output_offset, + sgot->contents); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); + + elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + } + + return TRUE; + } + #if 0 /* relaxing not supported yet */ *************** *** 2005,2010 **** --- 4270,4277 ---- { case R_M32R_GNU_VTINHERIT: case R_M32R_GNU_VTENTRY: + case R_M32R_RELA_GNU_VTINHERIT: + case R_M32R_RELA_GNU_VTENTRY: break; default: *************** *** 2035,2041 **** asection *sec ATTRIBUTE_UNUSED; const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; { ! /* we don't use got and plt entries for m32r */ return TRUE; } --- 4302,4398 ---- asection *sec ATTRIBUTE_UNUSED; const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; { ! /* Update the got entry reference counts for the section being removed. */ ! Elf_Internal_Shdr *symtab_hdr; ! struct elf_link_hash_entry **sym_hashes; ! bfd_signed_vma *local_got_refcounts; ! const Elf_Internal_Rela *rel, *relend; ! unsigned long r_symndx; ! struct elf_link_hash_entry *h; ! ! elf_section_data (sec)->local_dynrel = NULL; ! ! symtab_hdr = &elf_tdata (abfd)->symtab_hdr; ! sym_hashes = elf_sym_hashes (abfd); ! local_got_refcounts = elf_local_got_refcounts (abfd); ! ! relend = relocs + sec->reloc_count; ! for (rel = relocs; rel < relend; rel++) ! switch (ELF32_R_TYPE (rel->r_info)) ! { ! case R_M32R_GOT16_HI_ULO: ! case R_M32R_GOT16_HI_SLO: ! case R_M32R_GOT16_LO: ! case R_M32R_GOT24: ! case R_M32R_GOTPC_HI_ULO: ! case R_M32R_GOTPC_HI_SLO: ! case R_M32R_GOTPC_LO: ! case R_M32R_GOTPC24: ! r_symndx = ELF32_R_SYM (rel->r_info); ! if (r_symndx >= symtab_hdr->sh_info) ! { ! h = sym_hashes[r_symndx - symtab_hdr->sh_info]; ! if (h->got.refcount > 0) ! h->got.refcount--; ! } ! else ! { ! if (local_got_refcounts && local_got_refcounts[r_symndx] > 0) ! local_got_refcounts[r_symndx]--; ! } ! break; ! ! case R_M32R_16_RELA: ! case R_M32R_24_RELA: ! case R_M32R_32_RELA: ! case R_M32R_HI16_ULO_RELA: ! case R_M32R_HI16_SLO_RELA: ! case R_M32R_LO16_RELA: ! case R_M32R_SDA16_RELA: ! case R_M32R_18_PCREL_RELA: ! case R_M32R_26_PCREL_RELA: ! r_symndx = ELF32_R_SYM (rel->r_info); ! if (r_symndx >= symtab_hdr->sh_info) ! { ! struct elf_m32r_link_hash_entry *eh; ! struct elf_m32r_dyn_relocs **pp; ! struct elf_m32r_dyn_relocs *p; ! ! h = sym_hashes[r_symndx - symtab_hdr->sh_info]; ! ! if (!info->shared && h->plt.refcount > 0) ! h->plt.refcount -= 1; ! ! eh = (struct elf_m32r_link_hash_entry *) h; ! ! for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) ! if (p->sec == sec) ! { ! if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA ! || ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA) ! p->pc_count -= 1; ! p->count -= 1; ! if (p->count == 0) ! *pp = p->next; ! break; ! } ! } ! break; ! ! case R_M32R_26_PLTREL: ! r_symndx = ELF32_R_SYM (rel->r_info); ! if (r_symndx >= symtab_hdr->sh_info) ! { ! h = sym_hashes[r_symndx - symtab_hdr->sh_info]; ! if (h->plt.refcount > 0) ! h->plt.refcount--; ! } ! break; ! ! default: ! break; ! } ! return TRUE; } *************** *** 2054,2085 **** struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; if (info->relocatable) return TRUE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { struct elf_link_hash_entry *h; unsigned long r_symndx; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; ! switch (ELF32_R_TYPE (rel->r_info)) { /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_M32R_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return FALSE; --- 4411,4660 ---- struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; + struct elf_m32r_link_hash_table *htab; + bfd *dynobj; + bfd_vma *local_got_offsets; + asection *sgot, *srelgot, *sreloc; if (info->relocatable) return TRUE; + sgot = srelgot = sreloc = NULL; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; + htab = m32r_elf_hash_table (info); + dynobj = htab->root.dynobj; + local_got_offsets = elf_local_got_offsets (abfd); + rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { + int r_type; struct elf_link_hash_entry *h; unsigned long r_symndx; r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; ! /* Some relocs require a global offset table. */ ! if (htab->sgot == NULL) ! { ! switch (r_type) ! { ! case R_M32R_GOT16_HI_ULO: ! case R_M32R_GOT16_HI_SLO: ! case R_M32R_GOT16_LO: ! case R_M32R_GOTPC24: ! case R_M32R_GOTPC_HI_ULO: ! case R_M32R_GOTPC_HI_SLO: ! case R_M32R_GOTPC_LO: ! case R_M32R_GOT24: ! if (dynobj == NULL) ! htab->root.dynobj = dynobj = abfd; ! if (! create_got_section (dynobj, info)) ! return FALSE; ! break; ! ! default: ! break; ! } ! } ! ! switch (r_type) { + case R_M32R_GOT16_HI_ULO: + case R_M32R_GOT16_HI_SLO: + case R_M32R_GOT16_LO: + case R_M32R_GOT24: + + if (h != NULL) + h->got.refcount += 1; + else + { + bfd_signed_vma *local_got_refcounts; + + /* This is a global offset table entry for a local + symbol. */ + local_got_refcounts = elf_local_got_refcounts (abfd); + if (local_got_refcounts == NULL) + { + bfd_size_type size; + + size = symtab_hdr->sh_info; + size *= sizeof (bfd_signed_vma); + local_got_refcounts = ((bfd_signed_vma *) + bfd_zalloc (abfd, size)); + if (local_got_refcounts == NULL) + return FALSE; + elf_local_got_refcounts (abfd) = local_got_refcounts; + } + local_got_refcounts[r_symndx] += 1; + } + break; + + case R_M32R_26_PLTREL: + /* This symbol requires a procedure linkage table entry. We + actually build the entry in adjust_dynamic_symbol, + because this might be a case of linking PIC code without + linking in any dynamic objects, in which case we don't + need to generate a procedure linkage table after all. */ + + /* If this is a local symbol, we resolve it directly without + creating a procedure linkage table entry. */ + if (h == NULL) + continue; + + if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) + break; + + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount += 1; + break; + + case R_M32R_16_RELA: + case R_M32R_24_RELA: + case R_M32R_32_RELA: + case R_M32R_HI16_ULO_RELA: + case R_M32R_HI16_SLO_RELA: + case R_M32R_LO16_RELA: + case R_M32R_SDA16_RELA: + case R_M32R_18_PCREL_RELA: + case R_M32R_26_PCREL_RELA: + + if (h != NULL && !info->shared) + { + h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + h->plt.refcount += 1; + } + + /* If we are creating a shared library, and this is a reloc + against a global symbol, or a non PC relative reloc + against a local symbol, then we need to copy the reloc + into the shared library. However, if we are linking with + -Bsymbolic, we do not need to copy a reloc against a + global symbol which is defined in an object we are + including in the link (i.e., DEF_REGULAR is set). At + this point we have not seen all the input files, so it is + possible that DEF_REGULAR is not set now but will be set + later (it is never cleared). We account for that + possibility below by storing information in the + dyn_relocs field of the hash table entry. A similar + situation occurs when creating shared libraries and symbol + visibility changes render the symbol local. + + If on the other hand, we are creating an executable, we + may need to keep relocations for symbols satisfied by a + dynamic library if we manage to avoid copy relocs for the + symbol. */ + if ((info->shared + && (sec->flags & SEC_ALLOC) != 0 + && ((r_type != R_M32R_26_PCREL_RELA + && r_type != R_M32R_18_PCREL_RELA) + || (h != NULL + && (! info->symbolic + || h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (!info->shared + && (sec->flags & SEC_ALLOC) != 0 + && h != NULL + && (h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0))) + { + struct elf_m32r_dyn_relocs *p; + struct elf_m32r_dyn_relocs **head; + + if (dynobj == NULL) + htab->root.dynobj = dynobj = abfd; + + /* When creating a shared object, we must copy these + relocs into the output file. We create a reloc + section in dynobj and make room for the reloc. */ + if (sreloc == NULL) + { + const char *name; + + name = (bfd_elf_string_from_elf_section + (abfd, + elf_elfheader (abfd)->e_shstrndx, + elf_section_data (sec)->rel_hdr.sh_name)); + if (name == NULL) + return FALSE; + + BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + && strcmp (bfd_get_section_name (abfd, sec), + name + 5) == 0); + + sreloc = bfd_get_section_by_name (dynobj, name); + if (sreloc == NULL) + { + flagword flags; + + sreloc = bfd_make_section (dynobj, name); + flags = (SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if ((sec->flags & SEC_ALLOC) != 0) + flags |= SEC_ALLOC | SEC_LOAD; + if (sreloc == NULL + || ! bfd_set_section_flags (dynobj, sreloc, flags) + || ! bfd_set_section_alignment (dynobj, sreloc, 2)) + return FALSE; + } + elf_section_data (sec)->sreloc = sreloc; + } + + /* If this is a global symbol, we count the number of + relocations we need for this symbol. */ + if (h != NULL) + head = &((struct elf_m32r_link_hash_entry *) h)->dyn_relocs; + else + { + asection *s; + + /* Track dynamic relocs needed for local syms too. */ + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); + if (s == NULL) + return FALSE; + + head = ((struct elf_m32r_dyn_relocs **) + &elf_section_data (s)->local_dynrel); + } + + p = *head; + if (p == NULL || p->sec != sec) + { + bfd_size_type amt = sizeof (*p); + p = ((struct elf_m32r_dyn_relocs *) bfd_alloc (dynobj, amt)); + if (p == NULL) + return FALSE; + p->next = *head; + *head = p; + p->sec = sec; + p->count = 0; + p->pc_count = 0; + } + + p->count += 1; + if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA) + p->pc_count += 1; + } + break; + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ + case R_M32R_RELA_GNU_VTINHERIT: case R_M32R_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return FALSE; *************** *** 2091,2096 **** --- 4666,4675 ---- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return FALSE; break; + case R_M32R_RELA_GNU_VTENTRY: + if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; + break; } } *************** *** 2103,2108 **** --- 4682,4742 ---- { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { NULL, 0, 0, 0, 0 } }; + + static bfd_boolean + m32r_elf_fake_sections (abfd, hdr, sec) + bfd *abfd; + Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED; + asection *sec; + { + register const char *name; + + name = bfd_get_section_name (abfd, sec); + + /* The generic elf_fake_sections will set up REL_HDR using the + default kind of relocations. But, we may actually need both + kinds of relocations, so we set up the second header here. + + This is not necessary for the O32 ABI since that only uses Elf32_Rel + relocations (cf. System V ABI, MIPS RISC Processor Supplement, + 3rd Edition, p. 4-17). It breaks the IRIX 5/6 32-bit ld, since one + of the resulting empty .rela.
sections starts with + sh_offset == object size, and ld doesn't allow that. While the check + is arguably bogus for empty or SHT_NOBITS sections, it can easily be + avoided by not emitting those useless sections in the first place. */ + if ((sec->flags & SEC_RELOC) != 0) + { + struct bfd_elf_section_data *esd; + bfd_size_type amt = sizeof (Elf_Internal_Shdr); + + esd = elf_section_data (sec); + BFD_ASSERT (esd->rel_hdr2 == NULL); + esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt); + if (!esd->rel_hdr2) + return FALSE; + _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, + !sec->use_rela_p); + } + + return TRUE; + } + + static enum elf_reloc_type_class + m32r_elf_reloc_type_class (rela) + const Elf_Internal_Rela *rela; + { + switch ((int) ELF32_R_TYPE (rela->r_info)) + { + case R_M32R_RELATIVE: + return reloc_class_relative; + case R_M32R_JMP_SLOT: + return reloc_class_plt; + case R_M32R_COPY: + return reloc_class_copy; + default: + return reloc_class_normal; + } + } #define ELF_ARCH bfd_arch_m32r #define ELF_MACHINE_CODE EM_M32R *************** *** 2111,2118 **** #define TARGET_BIG_SYM bfd_elf32_m32r_vec #define TARGET_BIG_NAME "elf32-m32r" ! #define elf_info_to_howto 0 #define elf_info_to_howto_rel m32r_info_to_howto_rel #define elf_backend_section_from_bfd_section _bfd_m32r_elf_section_from_bfd_section #define elf_backend_symbol_processing _bfd_m32r_elf_symbol_processing --- 4745,4754 ---- #define TARGET_BIG_SYM bfd_elf32_m32r_vec #define TARGET_BIG_NAME "elf32-m32r" + #define TARGET_LITTLE_SYM bfd_elf32_m32rle_vec + #define TARGET_LITTLE_NAME "elf32-m32rle" ! #define elf_info_to_howto m32r_info_to_howto #define elf_info_to_howto_rel m32r_info_to_howto_rel #define elf_backend_section_from_bfd_section _bfd_m32r_elf_section_from_bfd_section #define elf_backend_symbol_processing _bfd_m32r_elf_symbol_processing *************** *** 2122,2131 **** #define elf_backend_gc_sweep_hook m32r_elf_gc_sweep_hook #define elf_backend_check_relocs m32r_elf_check_relocs #define elf_backend_can_gc_sections 1 ! #if !USE_REL #define elf_backend_rela_normal 1 #endif #if 0 /* not yet */ /* relax support */ #define bfd_elf32_bfd_relax_section m32r_elf_relax_section --- 4758,4792 ---- #define elf_backend_gc_sweep_hook m32r_elf_gc_sweep_hook #define elf_backend_check_relocs m32r_elf_check_relocs + #define elf_backend_create_dynamic_sections m32r_elf_create_dynamic_sections + #define bfd_elf32_bfd_link_hash_table_create m32r_elf_link_hash_table_create + #define elf_backend_size_dynamic_sections m32r_elf_size_dynamic_sections + #define elf_backend_finish_dynamic_sections m32r_elf_finish_dynamic_sections + #define elf_backend_adjust_dynamic_symbol m32r_elf_adjust_dynamic_symbol + #define elf_backend_finish_dynamic_symbol m32r_elf_finish_dynamic_symbol + #define elf_backend_reloc_type_class m32r_elf_reloc_type_class + #define elf_backend_copy_indirect_symbol m32r_elf_copy_indirect_symbol + #define elf_backend_can_gc_sections 1 ! /*#if !USE_REL #define elf_backend_rela_normal 1 + #endif*/ + #define elf_backend_can_refcount 1 + #define elf_backend_want_got_plt 1 + #define elf_backend_plt_readonly 1 + #define elf_backend_want_plt_sym 0 + #define elf_backend_got_header_size 12 + + #define elf_backend_may_use_rel_p 1 + #ifdef USE_M32R_OLD_RELOC + #define elf_backend_default_use_rela_p 0 + #define elf_backend_may_use_rela_p 0 + #else + #define elf_backend_default_use_rela_p 1 + #define elf_backend_may_use_rela_p 1 + #define elf_backend_fake_sections m32r_elf_fake_sections #endif + #if 0 /* not yet */ /* relax support */ #define bfd_elf32_bfd_relax_section m32r_elf_relax_section *************** *** 2141,2143 **** --- 4802,4821 ---- #define elf_backend_special_sections m32r_elf_special_sections #include "elf32-target.h" + + #undef ELF_MAXPAGESIZE + #define ELF_MAXPAGESIZE 0x1000 + + #undef TARGET_BIG_SYM + #define TARGET_BIG_SYM bfd_elf32_m32rlin_vec + #undef TARGET_BIG_NAME + #define TARGET_BIG_NAME "elf32-m32r-linux" + #undef TARGET_LITTLE_SYM + #define TARGET_LITTLE_SYM bfd_elf32_m32rlelin_vec + #undef TARGET_LITTLE_NAME + #define TARGET_LITTLE_NAME "elf32-m32rle-linux" + #undef elf32_bed + #define elf32_bed elf32_m32r_lin_bed + + #include "elf32-target.h" + Index: bfd/reloc.c =================================================================== RCS file: /cvs/src/src/bfd/reloc.c,v retrieving revision 1.96 diff -c -r1.96 reloc.c *** bfd/reloc.c 30 Nov 2003 18:40:41 -0000 1.96 --- bfd/reloc.c 18 Dec 2003 10:04:33 -0000 *************** *** 2911,2916 **** --- 2911,2947 ---- ENUMDOC This is a 16-bit reloc containing the small data area offset for use in add3, load, and store instructions. + ENUM + BFD_RELOC_M32R_GOT24 + ENUMX + BFD_RELOC_M32R_26_PLTREL + ENUMX + BFD_RELOC_M32R_COPY + ENUMX + BFD_RELOC_M32R_GLOB_DAT + ENUMX + BFD_RELOC_M32R_JMP_SLOT + ENUMX + BFD_RELOC_M32R_RELATIVE + ENUMX + BFD_RELOC_M32R_GOTOFF + ENUMX + BFD_RELOC_M32R_GOTPC24 + ENUMX + BFD_RELOC_M32R_GOT16_HI_ULO + ENUMX + BFD_RELOC_M32R_GOT16_HI_SLO + ENUMX + BFD_RELOC_M32R_GOT16_LO + ENUMX + BFD_RELOC_M32R_GOTPC_HI_ULO + ENUMX + BFD_RELOC_M32R_GOTPC_HI_SLO + ENUMX + BFD_RELOC_M32R_GOTPC_LO + ENUMDOC + For PIC. + ENUM BFD_RELOC_V850_9_PCREL Index: bfd/targets.c =================================================================== RCS file: /cvs/src/src/bfd/targets.c,v retrieving revision 1.102 diff -c -r1.102 targets.c *** bfd/targets.c 30 Nov 2003 18:40:41 -0000 1.102 --- bfd/targets.c 18 Dec 2003 10:04:34 -0000 *************** *** 542,547 **** --- 542,550 ---- extern const bfd_target bfd_elf32_littlearm_vec; extern const bfd_target bfd_elf32_littlemips_vec; extern const bfd_target bfd_elf32_m32r_vec; + extern const bfd_target bfd_elf32_m32rle_vec; + extern const bfd_target bfd_elf32_m32rlin_vec; + extern const bfd_target bfd_elf32_m32rlelin_vec; extern const bfd_target bfd_elf32_m68hc11_vec; extern const bfd_target bfd_elf32_m68hc12_vec; extern const bfd_target bfd_elf32_m68k_vec; *************** *** 831,836 **** --- 834,842 ---- &bfd_elf32_littlearm_vec, &bfd_elf32_littlemips_vec, &bfd_elf32_m32r_vec, + &bfd_elf32_m32rle_vec, + &bfd_elf32_m32rlin_vec, + &bfd_elf32_m32rlelin_vec, &bfd_elf32_m68hc11_vec, &bfd_elf32_m68hc12_vec, &bfd_elf32_m68k_vec, Index: gas/configure.in =================================================================== RCS file: /cvs/src/src/gas/configure.in,v retrieving revision 1.145 diff -c -r1.145 configure.in *** gas/configure.in 3 Dec 2003 15:07:16 -0000 1.145 --- gas/configure.in 18 Dec 2003 10:04:36 -0000 *************** *** 164,169 **** --- 164,171 ---- sparc*) cpu_type=sparc arch=sparclite ;; # ??? See tc-sparc.c. v850*) cpu_type=v850 ;; xtensa*) cpu_type=xtensa arch=xtensa ;; + m32r) cpu_type=m32r target_cpu=m32r endian=big ;; + m32rle) cpu_type=m32r target_cpu=m32r endian=little ;; *) cpu_type=${cpu} ;; esac *************** *** 337,343 **** iq2000-*-elf) fmt=elf bfd_gas=yes ;; ! m32r-*-*) fmt=elf ;; m68hc11-*-* | m6811-*-*) fmt=elf ;; m68hc12-*-* | m6812-*-*) fmt=elf ;; --- 339,346 ---- iq2000-*-elf) fmt=elf bfd_gas=yes ;; ! m32r-*-elf*) fmt=elf ;; ! m32r-*-linux*) fmt=elf em=linux;; m68hc11-*-* | m6811-*-*) fmt=elf ;; m68hc12-*-* | m6812-*-*) fmt=elf ;; Index: gas/config/tc-m32r.c =================================================================== RCS file: /cvs/src/src/gas/config/tc-m32r.c,v retrieving revision 1.33 diff -c -r1.33 tc-m32r.c *** gas/config/tc-m32r.c 17 Dec 2003 09:41:06 -0000 1.33 --- gas/config/tc-m32r.c 18 Dec 2003 10:04:37 -0000 *************** *** 70,75 **** --- 70,78 ---- alignment request. */ static int seen_relaxable_p = 0; + /* Non-zero if we are generating PIC code. */ + int pic_code; + /* Non-zero if -relax specified, in which case sufficient relocs are output for the linker to do relaxing. We do simple forms of relaxing internally, but they are always done. *************** *** 194,200 **** gas_cgen_cpu_desc->machs = mach_table[on].mach_flags; } ! #define M32R_SHORTOPTS "O" const char *md_shortopts = M32R_SHORTOPTS; --- 197,203 ---- gas_cgen_cpu_desc->machs = mach_table[on].mach_flags; } ! #define M32R_SHORTOPTS "O::K:" const char *md_shortopts = M32R_SHORTOPTS; *************** *** 362,367 **** --- 365,377 ---- warn_unmatched_high = 0; break; + case 'K': + if (strcmp (arg, "PIC") != 0) + as_warn (_("Unrecognized option following -K")); + else + pic_code = 1; + break; + #if 0 /* Not supported yet. */ case OPTION_RELAX: *************** *** 436,441 **** --- 446,454 ---- fprintf (stream, _("\ -Wnuh synonym for -no-warn-unmatched-high\n")); + fprintf (stream, _("\ + -KPIC generate PIC\n")); + #if 0 fprintf (stream, _("\ -relax create linker relaxable code\n")); *************** *** 558,564 **** } symbol_table_insert (symbolP); ! if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section) /* xgettext:c-format */ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); --- 571,579 ---- } symbol_table_insert (symbolP); ! if (S_IS_DEFINED (symbolP) && (S_GET_SEGMENT (symbolP) != reg_section ! || S_IS_EXTERNAL (symbolP) ! || S_IS_WEAK (symbolP))) /* xgettext:c-format */ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); *************** *** 1710,1716 **** However, we can't finish the fragment here and emit the reloc as insn alignment requirements may move the insn about. */ ! if (S_GET_SEGMENT (fragP->fr_symbol) != segment) { #if 0 int old_fr_fix = fragP->fr_fix; --- 1725,1733 ---- However, we can't finish the fragment here and emit the reloc as insn alignment requirements may move the insn about. */ ! if (S_GET_SEGMENT (fragP->fr_symbol) != segment ! || S_IS_EXTERNAL (fragP->fr_symbol) ! || S_IS_WEAK (fragP->fr_symbol)) { #if 0 int old_fr_fix = fragP->fr_fix; *************** *** 1816,1827 **** abort (); } ! if (S_GET_SEGMENT (fragP->fr_symbol) != sec) { /* Symbol must be resolved by linker. */ if (fragP->fr_offset & 3) as_warn (_("Addend to unresolved symbol not on word boundary.")); ! addend = fragP->fr_offset >> 2; } else { --- 1833,1850 ---- abort (); } ! if (S_GET_SEGMENT (fragP->fr_symbol) != sec ! || S_IS_EXTERNAL (fragP->fr_symbol) ! || S_IS_WEAK (fragP->fr_symbol)) { /* Symbol must be resolved by linker. */ if (fragP->fr_offset & 3) as_warn (_("Addend to unresolved symbol not on word boundary.")); ! #ifdef USE_M32R_OLD_RELOC ! addend = fragP->fr_offset >> 2; /* Old M32R used USE_REL. */ ! #else ! addend = 0; ! #endif } else { *************** *** 1833,1839 **** /* Create a relocation for symbols that must be resolved by the linker. Otherwise output the completed insn. */ ! if (S_GET_SEGMENT (fragP->fr_symbol) != sec) { assert (fragP->fr_subtype != 1); assert (fragP->fr_cgen.insn != 0); --- 1856,1864 ---- /* Create a relocation for symbols that must be resolved by the linker. Otherwise output the completed insn. */ ! if (S_GET_SEGMENT (fragP->fr_symbol) != sec ! || S_IS_EXTERNAL (fragP->fr_symbol) ! || S_IS_WEAK (fragP->fr_symbol)) { assert (fragP->fr_subtype != 1); assert (fragP->fr_cgen.insn != 0); *************** *** 1874,1880 **** { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) ! || S_GET_SEGMENT (fixP->fx_addsy) != sec)) { /* The symbol is undefined (or is defined but not in this section). Let the linker figure it out. */ --- 1899,1907 ---- { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) ! || S_GET_SEGMENT (fixP->fx_addsy) != sec ! || S_IS_EXTERNAL (fixP->fx_addsy) ! || S_IS_WEAK (fixP->fx_addsy))) { /* The symbol is undefined (or is defined but not in this section). Let the linker figure it out. */ *************** *** 2189,2194 **** --- 2216,2238 ---- else reloc_type = fixP->fx_r_type; + if (fixP->fx_addsy == NULL) + return 1; + + /* Prevent all adjustments to global symbols. */ + if (S_IS_EXTERN (fixP->fx_addsy)) + return 0; + if (S_IS_WEAK (fixP->fx_addsy)) + return 0; + + if (pic_code + && (reloc_type == BFD_RELOC_M32R_24 + || reloc_type == BFD_RELOC_M32R_26_PCREL + || reloc_type == BFD_RELOC_M32R_HI16_SLO + || reloc_type == BFD_RELOC_M32R_HI16_ULO + || reloc_type == BFD_RELOC_M32R_LO16)) + return 0; + /* We need the symbol name for the VTABLE entries. */ if (reloc_type == BFD_RELOC_VTABLE_INHERIT || reloc_type == BFD_RELOC_VTABLE_ENTRY) *************** *** 2203,2206 **** --- 2247,2346 ---- if (use_parallel) m32r_flags |= E_M32R_HAS_PARALLEL; elf_elfheader (stdoutput)->e_flags |= m32r_flags; + } + + #define GOT_NAME "_GLOBAL_OFFSET_TABLE_" + + /* Translate internal representation of relocation info to BFD target + format. */ + arelent * + tc_gen_reloc (section, fixP) + asection * section; + fixS * fixP; + { + arelent * reloc; + bfd_reloc_code_real_type code; + + reloc = (arelent *) xmalloc (sizeof (arelent)); + + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); + reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; + + code = fixP->fx_r_type; + if (pic_code) + { + #ifdef DEBUG_PIC + printf("%s",bfd_get_reloc_code_name(code)); + #endif + switch (code) + { + case BFD_RELOC_M32R_26_PCREL: + code = BFD_RELOC_M32R_26_PLTREL; + break; + case BFD_RELOC_M32R_24: + if (fixP->fx_addsy != NULL + && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) + code = BFD_RELOC_M32R_GOTPC24; + else + code = BFD_RELOC_M32R_GOT24; + break; + case BFD_RELOC_M32R_HI16_ULO: + if (fixP->fx_addsy != NULL + && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) + code = BFD_RELOC_M32R_GOTPC_HI_ULO; + else + code = BFD_RELOC_M32R_GOT16_HI_ULO; + break; + case BFD_RELOC_M32R_HI16_SLO: + if (fixP->fx_addsy != NULL + && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) + code = BFD_RELOC_M32R_GOTPC_HI_SLO; + else + code = BFD_RELOC_M32R_GOT16_HI_SLO; + break; + case BFD_RELOC_M32R_LO16: + if (fixP->fx_addsy != NULL + && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) + code = BFD_RELOC_M32R_GOTPC_LO; + else + code = BFD_RELOC_M32R_GOT16_LO; + break; + default: + break; + } + #ifdef DEBUG_PIC + printf(" => %s",bfd_get_reloc_code_name(code)); + #endif + } + + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + #ifdef DEBUG_PIC + printf(" => %s\n",reloc->howto->name); + #endif + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("internal error: can't export reloc type %d (`%s')"), + fixP->fx_r_type, bfd_get_reloc_code_name (code)); + return NULL; + } + + /* Use fx_offset for these cases */ + if ( fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT) + reloc->addend = fixP->fx_offset; + else if (!pic_code + && fixP->fx_pcrel + && fixP->fx_addsy != NULL + && (S_GET_SEGMENT(fixP->fx_addsy) != section) + && S_IS_DEFINED (fixP->fx_addsy) + && ! S_IS_EXTERNAL(fixP->fx_addsy) + && ! S_IS_WEAK(fixP->fx_addsy)) + /* already used fx_offset in the opcode field itseld. */ + reloc->addend = 0; + else + reloc->addend = fixP->fx_addnumber; + + return reloc; } Index: gas/config/tc-m32r.h =================================================================== RCS file: /cvs/src/src/gas/config/tc-m32r.h,v retrieving revision 1.10 diff -c -r1.10 tc-m32r.h *** gas/config/tc-m32r.h 3 Dec 2003 17:38:45 -0000 1.10 --- gas/config/tc-m32r.h 18 Dec 2003 10:04:37 -0000 *************** *** 87,100 **** HI16 relocs and queue them up for later sorting. */ #define md_cgen_record_fixup_exp m32r_cgen_record_fixup_exp ! #define tc_gen_reloc gas_cgen_tc_gen_reloc #define tc_frob_file_before_fix() m32r_frob_file () extern void m32r_frob_file PARAMS ((void)); /* No shared lib support, so we don't need to ensure externally ! visible symbols can be overridden. */ ! #define EXTERN_FORCE_RELOC 0 /* When relaxing, we need to emit various relocs we otherwise wouldn't. */ #define TC_FORCE_RELOCATION(fix) m32r_force_relocation (fix) --- 87,117 ---- HI16 relocs and queue them up for later sorting. */ #define md_cgen_record_fixup_exp m32r_cgen_record_fixup_exp ! /* #define tc_gen_reloc gas_cgen_tc_gen_reloc */ ! ! #define TC_HANDLES_FX_DONE ! ! extern int pic_code; ! ! extern bfd_boolean m32r_fix_adjustable PARAMS ((struct fix *)); ! ! /* This arranges for gas/write.c to not apply a relocation if ! obj_fix_adjustable() says it is not adjustable. */ ! #define TC_FIX_ADJUSTABLE(fixP) obj_fix_adjustable (fixP) ! ! #define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \ ! ((FIX)->fx_addsy == NULL \ ! || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \ ! && ! S_IS_WEAK ((FIX)->fx_addsy) \ ! && S_IS_DEFINED ((FIX)->fx_addsy) \ ! && ! S_IS_COMMON ((FIX)->fx_addsy))) #define tc_frob_file_before_fix() m32r_frob_file () extern void m32r_frob_file PARAMS ((void)); /* No shared lib support, so we don't need to ensure externally ! visible symbols can be overridden. ! #define EXTERN_FORCE_RELOC 0 */ /* When relaxing, we need to emit various relocs we otherwise wouldn't. */ #define TC_FORCE_RELOCATION(fix) m32r_force_relocation (fix) Index: gdb/configure.host =================================================================== RCS file: /cvs/src/src/gdb/configure.host,v retrieving revision 1.61 diff -c -r1.61 configure.host *** gdb/configure.host 1 Dec 2003 21:10:46 -0000 1.61 --- gdb/configure.host 18 Dec 2003 10:04:39 -0000 *************** *** 22,27 **** --- 22,28 ---- sh*) gdb_host_cpu=sh ;; x86_64*) gdb_host_cpu=i386 ;; xscale*) gdb_host_cpu=arm ;; + m32r*) gdb_host_cpu=m32r ;; *) gdb_host_cpu=$host_cpu ;; esac *************** *** 146,150 **** --- 147,153 ---- x86_64-*-linux*) gdb_host=x86-64linux ;; x86_64-*-freebsd*) gdb_host=fbsd64 ;; x86_64-*-netbsd*) gdb_host=nbsd64 ;; + + m32r*-*-linux*) gdb_host=linux ;; esac Index: include/elf/m32r.h =================================================================== RCS file: /cvs/src/src/include/elf/m32r.h,v retrieving revision 1.6 diff -c -r1.6 m32r.h *** include/elf/m32r.h 3 Dec 2003 17:38:48 -0000 1.6 --- include/elf/m32r.h 18 Dec 2003 10:04:41 -0000 *************** *** 25,42 **** /* Relocations. */ START_RELOC_NUMBERS (elf_m32r_reloc_type) RELOC_NUMBER (R_M32R_NONE, 0) ! RELOC_NUMBER (R_M32R_16, 1) ! RELOC_NUMBER (R_M32R_32, 2) ! RELOC_NUMBER (R_M32R_24, 3) ! RELOC_NUMBER (R_M32R_10_PCREL, 4) ! RELOC_NUMBER (R_M32R_18_PCREL, 5) ! RELOC_NUMBER (R_M32R_26_PCREL, 6) ! RELOC_NUMBER (R_M32R_HI16_ULO, 7) ! RELOC_NUMBER (R_M32R_HI16_SLO, 8) ! RELOC_NUMBER (R_M32R_LO16, 9) ! RELOC_NUMBER (R_M32R_SDA16, 10) ! RELOC_NUMBER (R_M32R_GNU_VTINHERIT, 11) ! RELOC_NUMBER (R_M32R_GNU_VTENTRY, 12) END_RELOC_NUMBERS (R_M32R_max) /* Processor specific section indices. These sections do not actually --- 25,72 ---- /* Relocations. */ START_RELOC_NUMBERS (elf_m32r_reloc_type) RELOC_NUMBER (R_M32R_NONE, 0) ! /* REL relocations */ ! RELOC_NUMBER (R_M32R_16, 1) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_32, 2) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_24, 3) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_10_PCREL, 4) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_18_PCREL, 5) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_26_PCREL, 6) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_HI16_ULO, 7) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_HI16_SLO, 8) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_LO16, 9) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_SDA16, 10) /* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_GNU_VTINHERIT, 11)/* For backwards compatibility. */ ! RELOC_NUMBER (R_M32R_GNU_VTENTRY, 12) /* For backwards compatibility. */ ! ! /* RELA relocations */ ! RELOC_NUMBER (R_M32R_16_RELA, 33) ! RELOC_NUMBER (R_M32R_32_RELA, 34) ! RELOC_NUMBER (R_M32R_24_RELA, 35) ! RELOC_NUMBER (R_M32R_10_PCREL_RELA, 36) ! RELOC_NUMBER (R_M32R_18_PCREL_RELA, 37) ! RELOC_NUMBER (R_M32R_26_PCREL_RELA, 38) ! RELOC_NUMBER (R_M32R_HI16_ULO_RELA, 39) ! RELOC_NUMBER (R_M32R_HI16_SLO_RELA, 40) ! RELOC_NUMBER (R_M32R_LO16_RELA, 41) ! RELOC_NUMBER (R_M32R_SDA16_RELA, 42) ! RELOC_NUMBER (R_M32R_RELA_GNU_VTINHERIT, 43) ! RELOC_NUMBER (R_M32R_RELA_GNU_VTENTRY, 44) ! ! RELOC_NUMBER (R_M32R_GOT24, 48) ! RELOC_NUMBER (R_M32R_26_PLTREL, 49) ! RELOC_NUMBER (R_M32R_COPY, 50) ! RELOC_NUMBER (R_M32R_GLOB_DAT, 51) ! RELOC_NUMBER (R_M32R_JMP_SLOT, 52) ! RELOC_NUMBER (R_M32R_RELATIVE, 53) ! RELOC_NUMBER (R_M32R_GOTOFF, 54) ! RELOC_NUMBER (R_M32R_GOTPC24, 55) ! RELOC_NUMBER (R_M32R_GOT16_HI_ULO, 56) ! RELOC_NUMBER (R_M32R_GOT16_HI_SLO, 57) ! RELOC_NUMBER (R_M32R_GOT16_LO, 58) ! RELOC_NUMBER (R_M32R_GOTPC_HI_ULO, 59) ! RELOC_NUMBER (R_M32R_GOTPC_HI_SLO, 60) ! RELOC_NUMBER (R_M32R_GOTPC_LO, 61) END_RELOC_NUMBERS (R_M32R_max) /* Processor specific section indices. These sections do not actually Index: ld/Makefile.am =================================================================== RCS file: /cvs/src/src/ld/Makefile.am,v retrieving revision 1.147 diff -c -r1.147 Makefile.am *** ld/Makefile.am 4 Dec 2003 12:09:25 -0000 1.147 --- ld/Makefile.am 18 Dec 2003 10:04:41 -0000 *************** *** 230,235 **** --- 230,238 ---- ei386pe_posix.o \ elnk960.o \ em32relf.o \ + em32rlelf.o \ + em32relf_linux.o \ + em32rlelf_linux.o \ em68hc11elf.o \ em68hc11elfb.o \ em68hc12elf.o \ *************** *** 603,608 **** --- 606,620 ---- em32relf.c: $(srcdir)/emulparams/m32relf.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} m32relf "$(tdir_m32r)" + em32rlelf.c: $(srcdir)/emulparams/m32rlelf.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m32rlelf "$(tdir_m32rlelf)" + em32relf_linux.c: $(srcdir)/emulparams/m32relf_linux.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m32relf_linux "$(tdir_m32relf_linux)" + em32rlelf_linux.c: $(srcdir)/emulparams/m32rlelf_linux.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m32rlelf_linux "$(tdir_m32rlelf_linux)" eelf32_sparc.c: $(srcdir)/emulparams/elf32_sparc.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_sparc "$(tdir_elf32_sparc)" Index: ld/configure.tgt =================================================================== RCS file: /cvs/src/src/ld/configure.tgt,v retrieving revision 1.141 diff -c -r1.141 configure.tgt *** ld/configure.tgt 3 Dec 2003 15:07:17 -0000 1.141 --- ld/configure.tgt 18 Dec 2003 10:04:41 -0000 *************** *** 115,121 **** ia64-*-netbsd*) targ_emul=elf64_ia64 ;; ia64-*-linux*) targ_emul=elf64_ia64 ;; ia64-*-aix*) targ_emul=elf64_aix ;; ! m32r-*-*) targ_emul=m32relf ;; m68hc11-*-*|m6811-*-*) targ_emul=m68hc11elf targ_extra_emuls="m68hc11elfb m68hc12elf m68hc12elfb" ;; m68hc12-*-*|m6812-*-*) targ_emul=m68hc12elf --- 115,124 ---- ia64-*-netbsd*) targ_emul=elf64_ia64 ;; ia64-*-linux*) targ_emul=elf64_ia64 ;; ia64-*-aix*) targ_emul=elf64_aix ;; ! m32r*le-*-elf*) targ_emul=m32rlelf ;; ! m32r*-*-elf*) targ_emul=m32relf ;; ! m32r*le-*-linux-gnu*) targ_emul=m32rlelf_linux ;; ! m32r*-*-linux-gnu*) targ_emul=m32relf_linux ;; m68hc11-*-*|m6811-*-*) targ_emul=m68hc11elf targ_extra_emuls="m68hc11elfb m68hc12elf m68hc12elfb" ;; m68hc12-*-*|m6812-*-*) targ_emul=m68hc12elf Index: sim/common/sim-core.c =================================================================== RCS file: /cvs/src/src/sim/common/sim-core.c,v retrieving revision 1.3 diff -c -r1.3 sim-core.c *** sim/common/sim-core.c 23 Nov 2002 01:12:05 -0000 1.3 --- sim/common/sim-core.c 18 Dec 2003 10:04:47 -0000 *************** *** 801,806 **** --- 801,825 ---- } #endif + #if EXTERN_SIM_CORE_P + void * + sim_core_trans_addr (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + address_word addr) + { + sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common); + sim_core_mapping *mapping = + sim_core_find_mapping (core, map, + addr, /*nr-bytes*/1, + write_transfer, + 0 /*dont-abort*/, NULL, NULL_CIA); + if (mapping == NULL) + return NULL; + return sim_core_translate(mapping, addr); + } + #endif + /* define the read/write 1/2/4/8/16/word functions */ Index: sim/m32r/Makefile.in =================================================================== RCS file: /cvs/src/src/sim/m32r/Makefile.in,v retrieving revision 1.9 diff -c -r1.9 Makefile.in *** sim/m32r/Makefile.in 11 Dec 2003 11:33:44 -0000 1.9 --- sim/m32r/Makefile.in 18 Dec 2003 10:04:47 -0000 *************** *** 23,28 **** --- 23,29 ---- M32R_OBJS = m32r.o cpu.o decode.o sem.o model.o mloop.o M32RX_OBJS = m32rx.o cpux.o decodex.o modelx.o mloopx.o M32R2_OBJS = m32r2.o cpu2.o decode2.o model2.o mloop2.o + TRAPS_OBJ = @traps_obj@ CONFIG_DEVICES = dv-sockser.o CONFIG_DEVICES = *************** *** 40,46 **** $(M32R_OBJS) \ $(M32RX_OBJS) \ $(M32R2_OBJS) \ ! traps.o devices.o \ $(CONFIG_DEVICES) # Extra headers included by sim-main.h. --- 41,48 ---- $(M32R_OBJS) \ $(M32RX_OBJS) \ $(M32R2_OBJS) \ ! $(TRAPS_OBJ) \ ! devices.o \ $(CONFIG_DEVICES) # Extra headers included by sim-main.h. *************** *** 48,54 **** $(CGEN_INCLUDE_DEPS) \ arch.h cpuall.h m32r-sim.h $(srcdir)/../../opcodes/m32r-desc.h ! SIM_EXTRA_CFLAGS = SIM_RUN_OBJS = nrun.o SIM_EXTRA_CLEAN = m32r-clean --- 50,56 ---- $(CGEN_INCLUDE_DEPS) \ arch.h cpuall.h m32r-sim.h $(srcdir)/../../opcodes/m32r-desc.h ! SIM_EXTRA_CFLAGS = @sim_extra_cflags@ SIM_RUN_OBJS = nrun.o SIM_EXTRA_CLEAN = m32r-clean *************** *** 65,70 **** --- 67,73 ---- arch.o: arch.c $(SIM_MAIN_DEPS) traps.o: traps.c targ-vals.h $(SIM_MAIN_DEPS) + traps-linux.o: traps.c syscall.h targ-vals.h $(SIM_MAIN_DEPS) devices.o: devices.c $(SIM_MAIN_DEPS) # M32R objs Index: sim/m32r/configure.in =================================================================== RCS file: /cvs/src/src/sim/m32r/configure.in,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 configure.in *** sim/m32r/configure.in 16 Apr 1999 01:35:05 -0000 1.1.1.1 --- sim/m32r/configure.in 18 Dec 2003 10:04:47 -0000 *************** *** 14,17 **** --- 14,31 ---- SIM_AC_OPTION_INLINE() SIM_AC_OPTION_CGEN_MAINT + case "${target_alias}" in + m32r*-linux*) + traps_obj=traps-linux.o + sim_extra_cflags="-DM32R_LINUX" + ;; + *) + traps_obj=traps.o + sim_extra_cflags="-DM32R_ELF" + ;; + esac + AC_SUBST(traps_obj) + AC_SUBST(sim_extra_cflags) + + SIM_AC_OUTPUT Index: sim/m32r/sim-if.c =================================================================== RCS file: /cvs/src/src/sim/m32r/sim-if.c,v retrieving revision 1.6 diff -c -r1.6 sim-if.c *** sim/m32r/sim-if.c 11 Dec 2003 11:33:44 -0000 1.6 --- sim/m32r/sim-if.c 18 Dec 2003 10:04:47 -0000 *************** *** 214,219 **** --- 214,226 ---- addr = 0; sim_pc_set (current_cpu, addr); + #ifdef M32R_LINUX + m32rbf_h_cr_set (current_cpu, + m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000); + m32rbf_h_cr_set (current_cpu, + m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000); + #endif + #if 0 STATE_ARGV (sd) = sim_copy_argv (argv); STATE_ENVP (sd) = sim_copy_argv (envp); Index: sim/m32r/sim-main.h =================================================================== RCS file: /cvs/src/src/sim/m32r/sim-main.h,v retrieving revision 1.5 diff -c -r1.5 sim-main.h *** sim/m32r/sim-main.h 11 Dec 2003 11:33:44 -0000 1.5 --- sim/m32r/sim-main.h 18 Dec 2003 10:04:47 -0000 *************** *** 85,90 **** --- 85,94 ---- (TRANSFER), (ERROR)) /* Default memory size. */ + #ifdef M32R_LINUX + #define M32R_DEFAULT_MEM_SIZE 0x2000000 /* 32M */ + #else #define M32R_DEFAULT_MEM_SIZE 0x800000 /* 8M */ + #endif #endif /* SIM_MAIN_H */