diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-07-07 17:50:56 +0000 |
---|---|---|
committer | Mark Mitchell <mark@codesourcery.com> | 1999-07-07 17:50:56 +0000 |
commit | c7ac6ff835615a523fe86575cd5fae3f93f88430 (patch) | |
tree | b3b6c2a0430fa8c023ab019d2e7e0efa8cb141f9 /bfd/elflink.h | |
parent | 9846de1bb5d61521885ef51fa6b99121ec1be577 (diff) | |
download | gdb-c7ac6ff835615a523fe86575cd5fae3f93f88430.zip gdb-c7ac6ff835615a523fe86575cd5fae3f93f88430.tar.gz gdb-c7ac6ff835615a523fe86575cd5fae3f93f88430.tar.bz2 |
* elflink.h (elf_link_create_dynamic_sections): Handle non-standard
hash-entry sizes.
(size_dynamic_sections): Likewise.
(elf_link_output_extsym): Likewise.
* elf.c: (elf_fake_sections): Likewise.
* libbfd.c (bfd_get): New macro.
(bfd_put): Likewise.
* bfd-in2.h: Regenerated.
* elf-bfd.h (elf_size_info): Add hash_entry_size,
int_rels_per_ext_rel, swap_dyn_out, swap_reloc_in, swap_reloc_out,
wap_reloca_in, and swap_reloca_out.
* elflink.h (elf_link_read_relocs_from_section): Adjust to handle
multiple internal relocations per external relocation.
(link_read_relocs): Likewise.
(elf_bfd_final_link): Likewise.
(elf_link_input_bfd): Likewise.
(elf_gc_mark): Likewise.
(elf_gc_smash_unused_vtentry_relocs): Likewise.
* elfcode.h (elf_swap_dyn_out): Adjust type to match
elf_swap_dyn_in.
(size_info): Add entries for new fields.
* elf64-mips.c (mips_elf64_swap_reloc_out): Enable.
(mips_elf64_be_swap_reloc_in): New function.
(mips_elf64_be_swap_reloc_out): Likewise.
(mips_elf64_be_swap_reloca_in): Likewise.
(mips_elf64_be_swap_reloca_out): Likewise.
(mips_elf64_size_info): Add entries for new fields.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r-- | bfd/elflink.h | 88 |
1 files changed, 62 insertions, 26 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h index c2debca..057dc5e 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -1997,16 +1997,18 @@ elf_link_create_dynamic_sections (abfd, info) && ! _bfd_elf_link_record_dynamic_symbol (info, h)) return false; + bed = get_elf_backend_data (abfd); + s = bfd_make_section (abfd, ".hash"); if (s == NULL || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN)) return false; + elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry; /* Let the backend create the rest of the sections. This lets the backend set the right flags. The backend will normally create the .got and .plt sections. */ - bed = get_elf_backend_data (abfd); if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) return false; @@ -2068,6 +2070,8 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, PTR external_relocs; Elf_Internal_Rela *internal_relocs; { + struct elf_backend_data *bed; + /* If there aren't any relocations, that's OK. */ if (!shdr) return true; @@ -2081,24 +2085,36 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, != shdr->sh_size) return false; + bed = get_elf_backend_data (abfd); + /* Convert the external relocations to the internal format. */ if (shdr->sh_entsize == sizeof (Elf_External_Rel)) { Elf_External_Rel *erel; Elf_External_Rel *erelend; Elf_Internal_Rela *irela; + Elf_Internal_Rel *irel; erel = (Elf_External_Rel *) external_relocs; erelend = erel + shdr->sh_size / shdr->sh_entsize; irela = internal_relocs; - for (; erel < erelend; erel++, irela++) + irel = bfd_alloc (abfd, (bed->s->int_rels_per_ext_rel + * sizeof (Elf_Internal_Rel))); + for (; erel < erelend; erel++, irela += bed->s->int_rels_per_ext_rel) { - Elf_Internal_Rel irel; + int i; + + if (bed->s->swap_reloc_in) + (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, irel); + else + elf_swap_reloc_in (abfd, erel, irel); - elf_swap_reloc_in (abfd, erel, &irel); - irela->r_offset = irel.r_offset; - irela->r_info = irel.r_info; - irela->r_addend = 0; + for (i = 0; i < bed->s->int_rels_per_ext_rel; ++i) + { + irela[i].r_offset = irel[i].r_offset; + irela[i].r_info = irel[i].r_info; + irela[i].r_addend = 0; + } } } else @@ -2112,8 +2128,13 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, erela = (Elf_External_Rela *) external_relocs; erelaend = erela + shdr->sh_size / shdr->sh_entsize; irela = internal_relocs; - for (; erela < erelaend; erela++, irela++) - elf_swap_reloca_in (abfd, erela, irela); + for (; erela < erelaend; erela++, irela += bed->s->int_rels_per_ext_rel) + { + if (bed->s->swap_reloca_in) + (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, irela); + else + elf_swap_reloca_in (abfd, erela, irela); + } } return true; @@ -2141,6 +2162,7 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, Elf_Internal_Shdr *rel_hdr; PTR alloc1 = NULL; Elf_Internal_Rela *alloc2 = NULL; + struct elf_backend_data *bed = get_elf_backend_data (abfd); if (elf_section_data (o)->relocs != NULL) return elf_section_data (o)->relocs; @@ -2154,7 +2176,8 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, { size_t size; - size = o->reloc_count * sizeof (Elf_Internal_Rela); + size = (o->reloc_count * bed->s->int_rels_per_ext_rel + * sizeof (Elf_Internal_Rela)); if (keep_memory) internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size); else @@ -2183,7 +2206,8 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, (abfd, elf_section_data (o)->rel_hdr2, ((bfd_byte *) external_relocs) + rel_hdr->sh_size, - internal_relocs + rel_hdr->sh_size / rel_hdr->sh_entsize)) + internal_relocs + (rel_hdr->sh_size / rel_hdr->sh_entsize + * bed->s->int_rels_per_ext_rel))) goto error_return; /* Cache the results for next time, if we can. */ @@ -2699,6 +2723,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, asection *s; size_t bucketcount = 0; Elf_Internal_Sym isym; + size_t hash_entry_size; /* Set up the version definition section. */ s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); @@ -3047,14 +3072,16 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, s = bfd_get_section_by_name (dynobj, ".hash"); BFD_ASSERT (s != NULL); - s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8); + hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize; + s->_raw_size = ((2 + bucketcount + dynsymcount) * hash_entry_size); s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); if (s->contents == NULL) return false; memset (s->contents, 0, (size_t) s->_raw_size); - put_word (output_bfd, bucketcount, s->contents); - put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8)); + bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents); + bfd_put (8 * hash_entry_size, output_bfd, dynsymcount, + s->contents + hash_entry_size); elf_hash_table (info)->bucketcount = bucketcount; @@ -4043,7 +4070,8 @@ elf_bfd_final_link (abfd, info) finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size); finfo.internal_relocs = ((Elf_Internal_Rela *) bfd_malloc (max_internal_reloc_count - * sizeof (Elf_Internal_Rela))); + * sizeof (Elf_Internal_Rela) + * bed->s->int_rels_per_ext_rel)); finfo.external_syms = ((Elf_External_Sym *) bfd_malloc (max_sym_count * sizeof (Elf_External_Sym))); @@ -4738,6 +4766,7 @@ elf_link_output_extsym (h, data) { size_t bucketcount; size_t bucket; + size_t hash_entry_size; bfd_byte *bucketpos; bfd_vma chain; @@ -4750,13 +4779,15 @@ elf_link_output_extsym (h, data) bucketcount = elf_hash_table (finfo->info)->bucketcount; bucket = h->elf_hash_value % bucketcount; + hash_entry_size + = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; bucketpos = ((bfd_byte *) finfo->hash_sec->contents - + (bucket + 2) * (ARCH_SIZE / 8)); - chain = get_word (finfo->output_bfd, bucketpos); - put_word (finfo->output_bfd, h->dynindx, bucketpos); - put_word (finfo->output_bfd, chain, - ((bfd_byte *) finfo->hash_sec->contents - + (bucketcount + 2 + h->dynindx) * (ARCH_SIZE / 8))); + + (bucket + 2) * hash_entry_size); + chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); + bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos); + bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, + ((bfd_byte *) finfo->hash_sec->contents + + (bucketcount + 2 + h->dynindx) * hash_entry_size)); if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) { @@ -4898,10 +4929,11 @@ elf_link_input_bfd (finfo, input_bfd) long *pindex; asection **ppsection; asection *o; + struct elf_backend_data *bed; output_bfd = finfo->output_bfd; - relocate_section = - get_elf_backend_data (output_bfd)->elf_backend_relocate_section; + bed = get_elf_backend_data (output_bfd); + relocate_section = bed->elf_backend_relocate_section; /* If this is a dynamic object, we don't want to do anything here: we don't want the local symbols, and we don't want the section @@ -5138,7 +5170,8 @@ elf_link_input_bfd (finfo, input_bfd) /* Adjust the reloc addresses and symbol indices. */ irela = internal_relocs; - irelaend = irela + o->reloc_count; + irelaend = + irela + o->reloc_count * bed->s->int_rels_per_ext_rel; rel_hash = (elf_section_data (o->output_section)->rel_hashes + elf_section_data (o->output_section)->rel_count); for (; irela < irelaend; irela++, rel_hash++) @@ -5748,6 +5781,7 @@ elf_gc_mark (info, sec, gc_mark_hook) size_t extsymoff; Elf_External_Sym *locsyms, *freesyms = NULL; bfd *input_bfd = sec->owner; + struct elf_backend_data *bed = get_elf_backend_data (input_bfd); /* GCFIXME: how to arrange so that relocs and symbols are not reread continually? */ @@ -5791,7 +5825,7 @@ elf_gc_mark (info, sec, gc_mark_hook) ret = false; goto out1; } - relend = relstart + sec->reloc_count; + relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel; for (rel = relstart; rel < relend; rel++) { @@ -5997,6 +6031,7 @@ elf_gc_smash_unused_vtentry_relocs (h, okp) asection *sec; bfd_vma hstart, hend; Elf_Internal_Rela *relstart, *relend, *rel; + struct elf_backend_data *bed; /* Take care of both those symbols that do not describe vtables as well as those that are not loaded. */ @@ -6014,7 +6049,8 @@ elf_gc_smash_unused_vtentry_relocs (h, okp) (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL, true)); if (!relstart) return *(boolean *)okp = false; - relend = relstart + sec->reloc_count; + bed = get_elf_backend_data (sec->owner); + relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel; for (rel = relstart; rel < relend; ++rel) if (rel->r_offset >= hstart && rel->r_offset < hend) |