diff options
Diffstat (limited to 'bfd/elf32-m68k.c')
-rw-r--r-- | bfd/elf32-m68k.c | 321 |
1 files changed, 201 insertions, 120 deletions
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 2d0aba2..709057b 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -43,8 +43,6 @@ static boolean elf_m68k_gc_sweep_hook const Elf_Internal_Rela *)); static boolean elf_m68k_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); -static boolean elf_m68k_adjust_dynindx - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_m68k_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf_m68k_relocate_section @@ -56,6 +54,15 @@ static boolean elf_m68k_finish_dynamic_symbol static boolean elf_m68k_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); +static boolean elf32_m68k_set_private_flags + PARAMS ((bfd *, flagword)); +static boolean elf32_m68k_copy_private_bfd_data + PARAMS ((bfd *, bfd *)); +static boolean elf32_m68k_merge_private_bfd_data + PARAMS ((bfd *, bfd *)); +static boolean elf32_m68k_print_private_bfd_data + PARAMS ((bfd *, PTR)); + static reloc_howto_type howto_table[] = { HOWTO(R_68K_NONE, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", false, 0, 0x00000000,false), HOWTO(R_68K_32, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", false, 0, 0xffffffff,false), @@ -112,7 +119,7 @@ static reloc_howto_type howto_table[] = { static void rtype_to_howto (abfd, cache_ptr, dst) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf_Internal_Rela *dst; { @@ -157,7 +164,7 @@ static const struct static reloc_howto_type * reloc_type_lookup (abfd, code) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { unsigned int i; @@ -211,6 +218,33 @@ static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] = 0, 0, 0, 0 /* replaced with offset to start of .plt. */ }; +#define CPU32_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_CPU32) + +#define PLT_CPU32_ENTRY_SIZE 24 +/* Procedure linkage table entries for the cpu32 */ +static const bfd_byte elf_cpu32_plt0_entry[PLT_CPU32_ENTRY_SIZE] = +{ + 0x20, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a0 */ + 0, 0, 0, 0, /* replaced with offset to .got + 4. */ + 0x4e, 0xd0, /* jmp %a0@ */ + 0, 0, 0, 0, /* replace with offset to .got +8. */ + 0, 0, 0, 0, /* pad out to 24 bytes. */ + 0, 0, 0, 0, /* pad out to 24 bytes. */ + 0, 0 +}; + +static const bfd_byte elf_cpu32_plt_entry[PLT_CPU32_ENTRY_SIZE] = +{ + 0x20, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a0 */ + 0, 0, 0, 0, /* replaced with offset to symbol's .got entry. */ + 0x4e, 0xd0, /* jmp %a0@ */ + 0x2f, 0x3c, /* move.l #offset,-(%sp) */ + 0, 0, 0, 0, /* replaced with offset into relocation table. */ + 0x60, 0xff, /* bra.l .plt */ + 0, 0, 0, 0, /* replaced with offset to start of .plt. */ + 0, 0 +}; + /* The m68k 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 @@ -320,6 +354,88 @@ elf_m68k_link_hash_table_create (abfd) return &ret->root.root; } +/* Keep m68k-specific flags in the ELF header */ +static boolean +elf32_m68k_set_private_flags (abfd, flags) + bfd *abfd; + flagword flags; +{ + elf_elfheader (abfd)->e_flags = flags; + elf_flags_init (abfd) = true; + return true; +} + +/* Copy m68k-specific data from one module to another */ +static boolean +elf32_m68k_copy_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + flagword in_flags; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return true; + + in_flags = elf_elfheader (ibfd)->e_flags; + + elf_elfheader (obfd)->e_flags = in_flags; + elf_flags_init (obfd) = true; + + return true; +} + +/* Merge backend specific data from an object file to the output + object file when linking. */ +static boolean +elf32_m68k_merge_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + flagword out_flags; + flagword in_flags; + + if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return true; + + in_flags = elf_elfheader (ibfd)->e_flags; + out_flags = elf_elfheader (obfd)->e_flags; + + if (!elf_flags_init (obfd)) + { + elf_flags_init (obfd) = true; + elf_elfheader (obfd)->e_flags = in_flags; + } + + return true; +} + +/* Display the flags field */ +static boolean +elf32_m68k_print_private_bfd_data (abfd, ptr) + bfd *abfd; + PTR ptr; +{ + FILE *file = (FILE *) ptr; + + BFD_ASSERT (abfd != NULL && ptr != NULL); + + /* Print normal ELF private data. */ + _bfd_elf_print_private_bfd_data (abfd, ptr); + + /* Ignore init flag - it may not be set, despite the flags field containing valid data. */ + + /* xgettext:c-format */ + fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags); + + if (elf_elfheader (abfd)->e_flags & EF_CPU32) + fprintf (file, _ (" [cpu32]")); + + fputc ('\n', file); + + return true; +} /* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */ @@ -673,7 +789,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) static asection * elf_m68k_gc_mark_hook (abfd, info, rel, h, sym) bfd *abfd; - struct bfd_link_info *info; + struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; @@ -890,7 +1006,12 @@ elf_m68k_adjust_dynamic_symbol (info, h) /* 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; + { + if (CPU32_FLAG (dynobj)) + s->_raw_size += PLT_CPU32_ENTRY_SIZE; + else + s->_raw_size += PLT_ENTRY_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 @@ -907,7 +1028,10 @@ elf_m68k_adjust_dynamic_symbol (info, h) h->plt.offset = s->_raw_size; /* Make room for this entry. */ - s->_raw_size += PLT_ENTRY_SIZE; + if (CPU32_FLAG (dynobj)) + s->_raw_size += PLT_CPU32_ENTRY_SIZE; + else + 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. */ @@ -1186,51 +1310,6 @@ elf_m68k_size_dynamic_sections (output_bfd, info) } } - /* If we are generating a shared library, we generate a section - symbol for each output section for which we might need to copy - relocs. These are local symbols, which means that they must come - first in the dynamic symbol table. That means we must increment - the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - int c; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - continue; - - elf_section_data (s)->dynindx = c + 1; - - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - - ++c; - } - - elf_link_hash_traverse (elf_hash_table (info), - elf_m68k_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - } - - return true; -} - -/* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - -static boolean -elf_m68k_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; -{ - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; return true; } @@ -1244,7 +1323,7 @@ elf_m68k_adjust_dynindx (h, cparg) static boolean elf_m68k_discard_copies (h, ignore) struct elf_m68k_link_hash_entry *h; - PTR ignore; + PTR ignore ATTRIBUTE_UNUSED; { struct elf_m68k_pcrel_relocs_copied *s; @@ -1776,6 +1855,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Sym *sym; { bfd *dynobj; + int plt_off1, plt_off2, plt_off3; dynobj = elf_hash_table (info)->dynobj; @@ -1802,16 +1882,35 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) 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; + if ( CPU32_FLAG (output_bfd)) + plt_index = h->plt.offset / PLT_CPU32_ENTRY_SIZE - 1; + else + 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. */ - memcpy (splt->contents + h->plt.offset, elf_m68k_plt_entry, - PLT_ENTRY_SIZE); + if ( CPU32_FLAG (output_bfd)) + { + /* Fill in the entry in the procedure linkage table. */ + memcpy (splt->contents + h->plt.offset, elf_cpu32_plt_entry, + PLT_CPU32_ENTRY_SIZE); + plt_off1 = 4; + plt_off2 = 12; + plt_off3 = 18; + } + else + { + /* Fill in the entry in the procedure linkage table. */ + memcpy (splt->contents + h->plt.offset, elf_m68k_plt_entry, + PLT_ENTRY_SIZE); + plt_off1 = 4; + plt_off2 = 10; + plt_off3 = 16; + } + /* The offset is relative to the first extension word. */ bfd_put_32 (output_bfd, (sgot->output_section->vma @@ -1819,12 +1918,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) + got_offset - (splt->output_section->vma + h->plt.offset + 2)), - splt->contents + h->plt.offset + 4); + splt->contents + h->plt.offset + plt_off1); bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela), - splt->contents + h->plt.offset + 10); - bfd_put_32 (output_bfd, - (h->plt.offset + 16), - splt->contents + h->plt.offset + 16); + splt->contents + h->plt.offset + plt_off2); + bfd_put_32 (output_bfd, - (h->plt.offset + plt_off3), + splt->contents + h->plt.offset + plt_off3); /* Fill in the entry in the global offset table. */ bfd_put_32 (output_bfd, @@ -2017,21 +2116,39 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) /* Fill in the first entry in the procedure linkage table. */ if (splt->_raw_size > 0) { - memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE); - bfd_put_32 (output_bfd, - (sgot->output_section->vma - + sgot->output_offset + 4 - - (splt->output_section->vma + 2)), - splt->contents + 4); - bfd_put_32 (output_bfd, - (sgot->output_section->vma - + sgot->output_offset + 8 - - (splt->output_section->vma + 10)), - splt->contents + 12); + if (!CPU32_FLAG (output_bfd)) + { + memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE); + bfd_put_32 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + 4 + - (splt->output_section->vma + 2)), + splt->contents + 4); + bfd_put_32 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + 8 + - (splt->output_section->vma + 10)), + splt->contents + 12); + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_ENTRY_SIZE; + } + else /* cpu32 */ + { + memcpy (splt->contents, elf_cpu32_plt0_entry, PLT_CPU32_ENTRY_SIZE); + bfd_put_32 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + 4 + - (splt->output_section->vma + 2)), + splt->contents + 4); + bfd_put_32 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + 8 + - (splt->output_section->vma + 10)), + splt->contents + 10); + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_CPU32_ENTRY_SIZE; + } } - - elf_section_data (splt->output_section)->this_hdr.sh_entsize - = PLT_ENTRY_SIZE; } /* Fill in the first three entries in the global offset table. */ @@ -2049,50 +2166,6 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - if (elf_section_data (s)->dynindx == 0) - continue; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - - ++c; - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1; - } - return true; } @@ -2118,11 +2191,19 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) elf_m68k_finish_dynamic_sections #define elf_backend_gc_mark_hook elf_m68k_gc_mark_hook #define elf_backend_gc_sweep_hook elf_m68k_gc_sweep_hook +#define bfd_elf32_bfd_copy_private_bfd_data \ + elf32_m68k_copy_private_bfd_data +#define bfd_elf32_bfd_merge_private_bfd_data \ + elf32_m68k_merge_private_bfd_data +#define bfd_elf32_bfd_set_private_flags \ + elf32_m68k_set_private_flags +#define bfd_elf32_bfd_print_private_bfd_data \ + elf32_m68k_print_private_bfd_data + #define elf_backend_can_gc_sections 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_plt_header_size PLT_ENTRY_SIZE #include "elf32-target.h" |