X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-m68k.c;h=a3df85d5b5944e7b9e9e7b4490e9e902c1161a76;hb=5a0a214415f6190b75ffe8b807008009e5d70ad6;hp=38e6e9cb395411d4c6db5a09407ecc3d8f483332;hpb=dd5724d5231bacd3bdb04bb8572fb9201ee5538e;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 38e6e9cb39..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. @@ -181,7 +182,6 @@ reloc_type_lookup (abfd, code) /* end code generated by elf.el */ #define USE_RELA - /* Functions for the m68k ELF linker. */ @@ -224,11 +224,11 @@ 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] = { - 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */ + 0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */ 0, 0, 0, 0, /* replaced with offset to .got + 4. */ + 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, /* 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 }; @@ -376,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; } @@ -932,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 @@ -1267,7 +1266,12 @@ elf_m68k_size_dynamic_sections (output_bfd, info) } /* 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; } @@ -1307,6 +1311,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) { if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0)) return false; + info->flags |= DF_TEXTREL; } } @@ -1319,7 +1324,6 @@ elf_m68k_size_dynamic_sections (output_bfd, info) 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; @@ -1459,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 @@ -1479,14 +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, - (!info->shared || info->no_undefined)))) + (!info->shared || info->no_undefined + || ELF_ST_VISIBILITY (h->other))))) return false; relocation = 0; } @@ -2130,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 */ @@ -2145,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; } } @@ -2170,6 +2184,144 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) 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 + { + /* 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; + } + + /* 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; + + relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12); + if (relsec->contents == NULL) + goto error_return; + + p = relsec->contents; + + irelend = internal_relocs + datasec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++, p += 12) + { + asection *targetsec; + + /* 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. */ + + /* 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; + } + + /* Get the target section referred to by the reloc. */ + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + Elf_Internal_Sym isym; + + /* A local symbol. */ + bfd_elf32_swap_symbol_in (abfd, + extsyms + ELF32_R_SYM (irel->r_info), + &isym); + + 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; + } + + 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 #define TARGET_BIG_NAME "elf32-m68k" #define ELF_MACHINE_CODE EM_68K