diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2002-10-22 21:00:10 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@redhat.com> | 2002-10-22 21:00:10 +0000 |
commit | 033fd5f9ae6a7a915ee0f1263469f594d0dabb8d (patch) | |
tree | a83e7b2ba7e3b49ebc4f9f6a25cbe7c7aa43fcbf /bfd/elflink.h | |
parent | 1045b512db9224ba2b5b239336537b1141b46388 (diff) | |
download | gdb-033fd5f9ae6a7a915ee0f1263469f594d0dabb8d.zip gdb-033fd5f9ae6a7a915ee0f1263469f594d0dabb8d.tar.gz gdb-033fd5f9ae6a7a915ee0f1263469f594d0dabb8d.tar.bz2 |
* elflink.h (struct elf_link_sort_rela): Turn rel and rela
into arrays.
(elf_link_sort_cmp1, elf_link_sort_cmp2): Adjust.
(elf_link_sort_relocs): Likewise. Take int_rels_per_ext_rel
into account.
* elfxx-mips.c (mips_elf_create_dynamic_relocation): Compose
R_MIPS_REL32 with R_MIPS64 if ABI_64_P.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r-- | bfd/elflink.h | 89 |
1 files changed, 56 insertions, 33 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h index 079917e..03be87a 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -4669,8 +4669,9 @@ struct elf_link_sort_rela enum elf_reloc_type_class type; union { - Elf_Internal_Rel rel; - Elf_Internal_Rela rela; + /* We use these as arrays of size int_rels_per_ext_rel. */ + Elf_Internal_Rel rel[1]; + Elf_Internal_Rela rela[1]; } u; }; @@ -4690,13 +4691,13 @@ elf_link_sort_cmp1 (A, B) return 1; if (relativea > relativeb) return -1; - if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info)) + if (ELF_R_SYM (a->u.rel->r_info) < ELF_R_SYM (b->u.rel->r_info)) return -1; - if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info)) + if (ELF_R_SYM (a->u.rel->r_info) > ELF_R_SYM (b->u.rel->r_info)) return 1; - if (a->u.rel.r_offset < b->u.rel.r_offset) + if (a->u.rel->r_offset < b->u.rel->r_offset) return -1; - if (a->u.rel.r_offset > b->u.rel.r_offset) + if (a->u.rel->r_offset > b->u.rel->r_offset) return 1; return 0; } @@ -4720,9 +4721,9 @@ elf_link_sort_cmp2 (A, B) return -1; if (copya > copyb) return 1; - if (a->u.rel.r_offset < b->u.rel.r_offset) + if (a->u.rel->r_offset < b->u.rel->r_offset) return -1; - if (a->u.rel.r_offset > b->u.rel.r_offset) + if (a->u.rel->r_offset > b->u.rel->r_offset) return 1; return 0; } @@ -4740,6 +4741,7 @@ elf_link_sort_relocs (abfd, info, psec) size_t i, j, ret; struct elf_link_sort_rela *rela; struct elf_backend_data *bed = get_elf_backend_data (abfd); + int i2e = bed->s->int_rels_per_ext_rel; reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); if (reldyn == NULL || reldyn->_raw_size == 0) @@ -4763,7 +4765,23 @@ elf_link_sort_relocs (abfd, info, psec) if (size != reldyn->_raw_size) return 0; - rela = (struct elf_link_sort_rela *) bfd_zmalloc (sizeof (*rela) * count); + /* We waste some memory here when N = i2e is greater than 1, since + we allocate space for N * sizeof (*rela) where sizeof (*rela) + + (N - 1) * sizeof (Elf_Internal_Rel/Rela) would do. Also, we use + rela[k] only when k is a multiple of N, and then we index the + array within the union, such that rela[k].u.rel[i], i < N, is the + (i+1)th internal relocation corresponding to the (k/N)th external + relocation. This is done such that the relocation swap-in and + swap-out functions can gen pointers to arrays of internal + relocations that form a single external relocation. + + If C permitted arrays of structures with dynamic sizes, we could + do better, but trying to avoid wasting space at the end of the + chunk from rela[k] to rela[k+N-1] would require us to allocate a + separate array of pointers and since most ports have N == 1, this + would be more wasteful. */ + rela = (struct elf_link_sort_rela *) bfd_zmalloc + (sizeof (*rela) * count * i2e); if (rela == NULL) { (*info->callbacks->warning) @@ -4784,15 +4802,16 @@ elf_link_sort_relocs (abfd, info, psec) erel = (Elf_External_Rel *) o->contents; erelend = (Elf_External_Rel *) (o->contents + o->_raw_size); - s = rela + o->output_offset / sizeof (Elf_External_Rel); - for (; erel < erelend; erel++, s++) + s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e); + for (; erel < erelend; erel++, s += i2e) { if (bed->s->swap_reloc_in) - (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel); + (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, + s->u.rel); else - elf_swap_reloc_in (abfd, erel, &s->u.rel); + elf_swap_reloc_in (abfd, erel, s->u.rel); - s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela); + s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela); } } else @@ -4802,30 +4821,34 @@ elf_link_sort_relocs (abfd, info, psec) erela = (Elf_External_Rela *) o->contents; erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size); - s = rela + o->output_offset / sizeof (Elf_External_Rela); - for (; erela < erelaend; erela++, s++) + s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e); + for (; erela < erelaend; erela++, s += i2e) { if (bed->s->swap_reloca_in) (*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela, - &s->u.rela); + s->u.rela); else - elf_swap_reloca_in (dynobj, erela, &s->u.rela); + elf_swap_reloca_in (dynobj, erela, s->u.rela); - s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela); + s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela); } } } - qsort (rela, (size_t) count, sizeof (*rela), elf_link_sort_cmp1); - for (ret = 0; ret < count && rela[ret].type == reloc_class_relative; ret++) + qsort (rela, (size_t) count, sizeof (*rela) * i2e, elf_link_sort_cmp1); + for (ret = 0; ret < count * i2e && rela[ret].type == reloc_class_relative; + ret += i2e) ; - for (i = ret, j = ret; i < count; i++) + for (i = ret, j = ret; i < count * i2e; i += i2e) { - if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info)) + if (ELF_R_SYM (rela[i].u.rel->r_info) + != ELF_R_SYM (rela[j].u.rel->r_info)) j = i; - rela[i].offset = rela[j].u.rel.r_offset; + rela[i].offset = rela[j].u.rel->r_offset; } - qsort (rela + ret, (size_t) count - ret, sizeof (*rela), elf_link_sort_cmp2); + ret /= i2e; + qsort (rela + ret, (size_t) count - ret, + sizeof (*rela) * i2e, elf_link_sort_cmp2); for (o = dynobj->sections; o != NULL; o = o->next) if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)) @@ -4839,14 +4862,14 @@ elf_link_sort_relocs (abfd, info, psec) erel = (Elf_External_Rel *) o->contents; erelend = (Elf_External_Rel *) (o->contents + o->_raw_size); - s = rela + o->output_offset / sizeof (Elf_External_Rel); - for (; erel < erelend; erel++, s++) + s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e); + for (; erel < erelend; erel++, s += i2e) { if (bed->s->swap_reloc_out) - (*bed->s->swap_reloc_out) (abfd, &s->u.rel, + (*bed->s->swap_reloc_out) (abfd, s->u.rel, (bfd_byte *) erel); else - elf_swap_reloc_out (abfd, &s->u.rel, erel); + elf_swap_reloc_out (abfd, s->u.rel, erel); } } else @@ -4856,14 +4879,14 @@ elf_link_sort_relocs (abfd, info, psec) erela = (Elf_External_Rela *) o->contents; erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size); - s = rela + o->output_offset / sizeof (Elf_External_Rela); - for (; erela < erelaend; erela++, s++) + s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e); + for (; erela < erelaend; erela++, s += i2e) { if (bed->s->swap_reloca_out) - (*bed->s->swap_reloca_out) (dynobj, &s->u.rela, + (*bed->s->swap_reloca_out) (dynobj, s->u.rela, (bfd_byte *) erela); else - elf_swap_reloca_out (dynobj, &s->u.rela, erela); + elf_swap_reloca_out (dynobj, s->u.rela, erela); } } } |