X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-m68k.c;h=a3df85d5b5944e7b9e9e7b4490e9e902c1161a76;hb=5a0a214415f6190b75ffe8b807008009e5d70ad6;hp=36f62797566f283e33c03bd8dda79de797e2c659;hpb=121089cbf08a912591115bbeeb181eb09ccee448;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 36f6279756..a3df85d5b5 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -1,5 +1,6 @@ /* Motorola 68k series support for 32-bit ELF - Copyright 1993, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -43,8 +44,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 @@ -183,7 +182,6 @@ reloc_type_lookup (abfd, code) /* end code generated by elf.el */ #define USE_RELA - /* Functions for the m68k ELF linker. */ @@ -226,20 +224,20 @@ static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] = /* 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 */ + 0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */ 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. */ + 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */ + 0, 0, 0, 0, /* replace with offset to .got +8. */ + 0x4e, 0xd1, /* jmp %a1@ */ 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 */ + 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */ 0, 0, 0, 0, /* replaced with offset to symbol's .got entry. */ - 0x4e, 0xd0, /* jmp %a0@ */ + 0x4e, 0xd1, /* jmp %a1@ */ 0x2f, 0x3c, /* move.l #offset,-(%sp) */ 0, 0, 0, 0, /* replaced with offset into relocation table. */ 0x60, 0xff, /* bra.l .plt */ @@ -378,12 +376,12 @@ elf32_m68k_copy_private_bfd_data (ibfd, obfd) 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; } @@ -857,11 +855,11 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) local_got_refcounts = elf_local_got_refcounts (abfd); dynobj = elf_hash_table (info)->dynobj; - if (dynobj) - { - sgot = bfd_get_section_by_name (dynobj, ".got"); - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - } + if (dynobj == NULL) + return true; + + sgot = bfd_get_section_by_name (dynobj, ".got"); + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) @@ -889,7 +887,7 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) } } } - else + else if (local_got_refcounts != NULL) { if (local_got_refcounts[r_symndx] > 0) { @@ -934,7 +932,6 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) return true; } - /* 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 @@ -1264,12 +1261,17 @@ elf_m68k_size_dynamic_sections (output_bfd, info) if (strip) { - _bfd_strip_section_from_output (s); + _bfd_strip_section_from_output (info, s); continue; } /* Allocate memory for the section contents. */ - s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size); + /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. + Unused entries should be reclaimed before the section's contents + are written out, but at the moment this does not happen. Thus in + order to prevent writing out garbage, we initialise the section's + contents to zero. */ + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); if (s->contents == NULL && s->_raw_size != 0) return false; } @@ -1309,54 +1311,10 @@ elf_m68k_size_dynamic_sections (output_bfd, info) { if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0)) return false; + info->flags |= DF_TEXTREL; } } - /* 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; } @@ -1366,7 +1324,6 @@ elf_m68k_adjust_dynindx (h, cparg) in regular objects. We allocated space for them in the check_relocs routine, but we won't fill them in in the relocate_section routine. */ -/*ARGSUSED*/ static boolean elf_m68k_discard_copies (h, ignore) struct elf_m68k_link_hash_entry *h; @@ -1506,7 +1463,14 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, && ((! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - && (input_section->flags & SEC_ALLOC) != 0 + && ((input_section->flags & SEC_ALLOC) != 0 + /* DWARF will emit R_68K_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)) && (r_type == R_68K_8 || r_type == R_68K_16 || r_type == R_68K_32 @@ -1526,13 +1490,17 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; - else if (info->shared && !info->symbolic && !info->no_undefined) + else if (info->shared && !info->symbolic + && !info->no_undefined + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; else { if (!(info->callbacks->undefined_symbol (info, h->root.root.string, input_bfd, - input_section, rel->r_offset))) + input_section, rel->r_offset, + (!info->shared || info->no_undefined + || ELF_ST_VISIBILITY (h->other))))) return false; relocation = 0; } @@ -2176,7 +2144,7 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) + sgot->output_offset + 8 - (splt->output_section->vma + 10)), splt->contents + 12); - elf_section_data (splt->output_section)->this_hdr.sh_entsize + elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; } else /* cpu32 */ @@ -2191,8 +2159,8 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) (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 + splt->contents + 12); + elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_CPU32_ENTRY_SIZE; } } @@ -2213,51 +2181,145 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - if (info->shared) + return true; +} + +/* Given a .data section and a .emreloc in-memory section, store + relocation information into the .emreloc section which can be + used at runtime to relocate the section. This is called by the + linker when the --embedded-relocs switch is used. This is called + after the add_symbols entry point has been called for all the + objects, and before the final_link entry point is called. */ + +boolean +bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) + bfd *abfd; + struct bfd_link_info *info; + asection *datasec; + asection *relsec; + char **errmsg; +{ + Elf_Internal_Shdr *symtab_hdr; + Elf32_External_Sym *extsyms; + Elf32_External_Sym *free_extsyms = NULL; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Rela *irel, *irelend; + bfd_byte *p; + + BFD_ASSERT (! info->relocateable); + + *errmsg = NULL; + + if (datasec->reloc_count == 0) + return true; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + /* Read this BFD's symbols if we haven't done so already, or get the cached + copy if it exists. */ + if (symtab_hdr->contents != NULL) + extsyms = (Elf32_External_Sym *) symtab_hdr->contents; + else { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; + /* Go get them off disk. */ + if (info->keep_memory) + extsyms = ((Elf32_External_Sym *) + bfd_alloc (abfd, symtab_hdr->sh_size)); + else + extsyms = ((Elf32_External_Sym *) + bfd_malloc (symtab_hdr->sh_size)); + if (extsyms == NULL) + goto error_return; + if (! info->keep_memory) + free_extsyms = extsyms; + if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd) + != symtab_hdr->sh_size)) + goto error_return; + if (info->keep_memory) + symtab_hdr->contents = extsyms; + } - /* Set up the section symbols for the output sections. */ + /* Get a copy of the native relocations. */ + internal_relocs = (_bfd_elf32_link_read_relocs + (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + info->keep_memory)); + if (internal_relocs == NULL) + goto error_return; + if (! info->keep_memory) + free_relocs = internal_relocs; - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); + relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12); + if (relsec->contents == NULL) + goto error_return; - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; + p = relsec->contents; - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; + irelend = internal_relocs + datasec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++, p += 12) + { + asection *targetsec; - if (elf_section_data (s)->dynindx == 0) - continue; + /* We are going to write a four byte longword into the runtime + reloc section. The longword will be the address in the data + section which must be relocated. It is followed by the name + of the target section NUL-padded or truncated to 8 + characters. */ - sym.st_value = s->vma; + /* We can only relocate absolute longword relocs at run time. */ + if (ELF32_R_TYPE (irel->r_info) != (int) R_68K_32) + { + *errmsg = _("unsupported reloc type"); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; + /* Get the target section referred to by the reloc. */ + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + Elf_Internal_Sym isym; - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); + /* A local symbol. */ + bfd_elf32_swap_symbol_in (abfd, + extsyms + ELF32_R_SYM (irel->r_info), + &isym); - ++c; + targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + } + else + { + unsigned long indx; + struct elf_link_hash_entry *h; + + /* An external symbol. */ + indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + BFD_ASSERT (h != NULL); + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + targetsec = h->root.u.def.section; + else + targetsec = NULL; } - /* 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; + bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p); + memset (p + 4, 0, 8); + if (targetsec != NULL) + strncpy (p + 4, targetsec->output_section->name, 8); } + if (free_extsyms != NULL) + free (free_extsyms); + if (free_relocs != NULL) + free (free_relocs); return true; + +error_return: + if (free_extsyms != NULL) + free (free_extsyms); + if (free_relocs != NULL) + free (free_relocs); + return false; } #define TARGET_BIG_SYM bfd_elf32_m68k_vec