diff options
author | Nick Clifton <nickc@redhat.com> | 2000-09-15 18:52:52 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2000-09-15 18:52:52 +0000 |
commit | 0752970ef843fa6a9e7ac8bb5a30608eded7f228 (patch) | |
tree | 681414cd31e8fe3f2fb29df4cbcd4c91520f64b3 /bfd/elf32-m68k.c | |
parent | ffcb7aff0f99aaa26b99e04b8258009279096402 (diff) | |
download | gdb-0752970ef843fa6a9e7ac8bb5a30608eded7f228.zip gdb-0752970ef843fa6a9e7ac8bb5a30608eded7f228.tar.gz gdb-0752970ef843fa6a9e7ac8bb5a30608eded7f228.tar.bz2 |
add support for embedded relocs in m68k ELF port
Diffstat (limited to 'bfd/elf32-m68k.c')
-rw-r--r-- | bfd/elf32-m68k.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 96d636c..d53cfdf 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -2179,6 +2179,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 |