Lines 3021-3027
Link Here
|
3021 |
const struct elf_backend_data *bed; |
3021 |
const struct elf_backend_data *bed; |
3022 |
bfd_byte *extdyn; |
3022 |
bfd_byte *extdyn; |
3023 |
|
3023 |
|
3024 |
_bfd_elf_strtab_finalize (dynstr); |
3024 |
_bfd_elf_strtab_finalize (dynstr, info->dynsort ? |
|
|
3025 |
elf_hash_table (info)->bucketcount : 0); |
3025 |
size = _bfd_elf_strtab_size (dynstr); |
3026 |
size = _bfd_elf_strtab_size (dynstr); |
3026 |
|
3027 |
|
3027 |
bed = get_elf_backend_data (dynobj); |
3028 |
bed = get_elf_backend_data (dynobj); |
Lines 4777-4803
Link Here
|
4777 |
return FALSE; |
4778 |
return FALSE; |
4778 |
} |
4779 |
} |
4779 |
} |
4780 |
} |
4780 |
|
|
|
4781 |
/* This function will be called though elf_link_hash_traverse to store |
4782 |
all hash value of the exported symbols in an array. */ |
4783 |
|
4781 |
|
4784 |
static bfd_boolean |
4782 |
/* |
4785 |
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) |
4783 |
* Compute the elf hash value of the name ignoring the version. |
|
|
4784 |
*/ |
4785 |
unsigned long |
4786 |
_bfd_elf_ver_hash (const char *name) |
4786 |
{ |
4787 |
{ |
4787 |
unsigned long **valuep = data; |
|
|
4788 |
const char *name; |
4789 |
char *p; |
4788 |
char *p; |
4790 |
unsigned long ha; |
4789 |
unsigned long ha; |
4791 |
char *alc = NULL; |
4790 |
char *alc = NULL; |
4792 |
|
4791 |
|
4793 |
if (h->root.type == bfd_link_hash_warning) |
|
|
4794 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4795 |
|
4796 |
/* Ignore indirect symbols. These are added by the versioning code. */ |
4797 |
if (h->dynindx == -1) |
4798 |
return TRUE; |
4799 |
|
4800 |
name = h->root.root.string; |
4801 |
p = strchr (name, ELF_VER_CHR); |
4792 |
p = strchr (name, ELF_VER_CHR); |
4802 |
if (p != NULL) |
4793 |
if (p != NULL) |
4803 |
{ |
4794 |
{ |
Lines 4810-4815
Link Here
|
4810 |
/* Compute the hash value. */ |
4801 |
/* Compute the hash value. */ |
4811 |
ha = bfd_elf_hash (name); |
4802 |
ha = bfd_elf_hash (name); |
4812 |
|
4803 |
|
|
|
4804 |
if (alc != NULL) |
4805 |
free (alc); |
4806 |
|
4807 |
return ha; |
4808 |
} |
4809 |
|
4810 |
|
4811 |
/* This function will be called though elf_link_hash_traverse to store |
4812 |
all hash value of the exported symbols in an array. */ |
4813 |
|
4814 |
static bfd_boolean |
4815 |
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) |
4816 |
{ |
4817 |
unsigned long **valuep = data; |
4818 |
unsigned long ha; |
4819 |
|
4820 |
if (h->root.type == bfd_link_hash_warning) |
4821 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4822 |
|
4823 |
/* Ignore indirect symbols. These are added by the versioning code. */ |
4824 |
if (h->dynindx == -1) |
4825 |
return TRUE; |
4826 |
|
4827 |
ha = _bfd_elf_ver_hash (h->root.root.string); |
4828 |
|
4813 |
/* Store the found hash value in the array given as the argument. */ |
4829 |
/* Store the found hash value in the array given as the argument. */ |
4814 |
*(*valuep)++ = ha; |
4830 |
*(*valuep)++ = ha; |
4815 |
|
4831 |
|
Lines 4817-4825
Link Here
|
4817 |
later. */ |
4833 |
later. */ |
4818 |
h->u.elf_hash_value = ha; |
4834 |
h->u.elf_hash_value = ha; |
4819 |
|
4835 |
|
4820 |
if (alc != NULL) |
|
|
4821 |
free (alc); |
4822 |
|
4823 |
return TRUE; |
4836 |
return TRUE; |
4824 |
} |
4837 |
} |
4825 |
|
4838 |
|
Lines 4982-4987
Link Here
|
4982 |
return best_size; |
4995 |
return best_size; |
4983 |
} |
4996 |
} |
4984 |
|
4997 |
|
|
|
4998 |
void _bfd_elf_link_hash_traverse |
4999 |
(struct elf_link_hash_table *table, |
5000 |
bfd_boolean (*func) (struct elf_link_hash_entry *, void *), |
5001 |
void *info) |
5002 |
{ |
5003 |
if (!table->sorted) |
5004 |
bfd_link_hash_traverse \ |
5005 |
(&(table)->root, \ |
5006 |
(bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \ |
5007 |
(info)); |
5008 |
else |
5009 |
{ |
5010 |
unsigned int i; |
5011 |
for (i = 0; i < table->sorted_size; i++) |
5012 |
{ |
5013 |
if (! func (table->sorted[i], info)) |
5014 |
return; |
5015 |
} |
5016 |
} |
5017 |
} |
5018 |
|
5019 |
/* Sort by elf hash value % buckets */ |
5020 |
static int |
5021 |
elf_sort_dynsym_hash (const void *arg1, const void *arg2, const void *closure) |
5022 |
{ |
5023 |
size_t h1_bucket, h2_bucket; |
5024 |
const struct elf_link_hash_entry *h1; |
5025 |
const struct elf_link_hash_entry *h2; |
5026 |
const bfd_size_type *bucketcount; |
5027 |
|
5028 |
h1 = *(const struct elf_link_hash_entry **) arg1; |
5029 |
h2 = *(const struct elf_link_hash_entry **) arg2; |
5030 |
bucketcount = closure; |
5031 |
|
5032 |
h1_bucket = h1->u.elf_hash_value % *bucketcount; |
5033 |
h2_bucket = h2->u.elf_hash_value % *bucketcount; |
5034 |
|
5035 |
if (h1_bucket > h2_bucket) |
5036 |
return 1; |
5037 |
if (h1_bucket < h2_bucket) |
5038 |
return -1; |
5039 |
|
5040 |
return 0; |
5041 |
} |
5042 |
|
5043 |
struct elf_dynsym_sort_info |
5044 |
{ |
5045 |
bfd_boolean do_dynsym; |
5046 |
unsigned int alloc_size; |
5047 |
unsigned int sorted_size; |
5048 |
struct elf_link_hash_entry **sorted_syms; |
5049 |
}; |
5050 |
|
5051 |
/* collect sym entries into an array for later sorting */ |
5052 |
static bfd_boolean |
5053 |
elf_sort_collect_dynsyms (struct elf_link_hash_entry *h, void *data) |
5054 |
{ |
5055 |
struct elf_dynsym_sort_info *sinfo = data; |
5056 |
|
5057 |
if ((sinfo->do_dynsym && h->dynindx < 0) || |
5058 |
(!sinfo->do_dynsym && h->dynindx >= 0)) |
5059 |
return TRUE; |
5060 |
|
5061 |
if (sinfo->sorted_size >= sinfo->alloc_size) |
5062 |
{ |
5063 |
sinfo->alloc_size *= 2; |
5064 |
/* FIXME: need to free this data too ... */ |
5065 |
sinfo->sorted_syms = bfd_realloc (sinfo->sorted_syms, |
5066 |
sizeof (struct elf_link_hash_entry *) * |
5067 |
sinfo->alloc_size); |
5068 |
} |
5069 |
sinfo->sorted_syms [sinfo->sorted_size++] = h; |
5070 |
|
5071 |
return TRUE; |
5072 |
} |
5073 |
|
5074 |
/* Nasty hack to avoid re-running autoconf / touching generated headers */ |
5075 |
|
5076 |
typedef int(*bfd_qsort_closure_func)(const void *, const void *, const void *); |
5077 |
extern void bfd_qsort (void *base, bfd_size_type nmemb, bfd_size_type size, |
5078 |
bfd_qsort_closure_func cmp, void *closure); |
5079 |
|
5080 |
#include "bfdsort.c" |
5081 |
|
5082 |
/* |
5083 |
* Sort the exported elf symbols by elf_hash % bucketcount to |
5084 |
* improve run-time linker cache behavior. Subsequent |
5085 |
* elf_link_hash_traverse calls will reflect this new order. |
5086 |
*/ |
5087 |
static bfd_boolean |
5088 |
_bfd_elf_sort_dynsyms (struct bfd_link_info *info) |
5089 |
{ |
5090 |
bfd_size_type bucketcount; |
5091 |
struct elf_dynsym_sort_info sinfo; |
5092 |
|
5093 |
sinfo.alloc_size = 8; |
5094 |
sinfo.sorted_syms = bfd_malloc (sizeof (struct elf_link_hash_entry *) * |
5095 |
sinfo.alloc_size); |
5096 |
if (!sinfo.sorted_syms) |
5097 |
return FALSE; |
5098 |
|
5099 |
sinfo.sorted_size = 0; |
5100 |
|
5101 |
/* append dynsyms for sorting */ |
5102 |
sinfo.do_dynsym = TRUE; |
5103 |
elf_link_hash_traverse (elf_hash_table (info), elf_sort_collect_dynsyms, &sinfo); |
5104 |
|
5105 |
/* sort them ... */ |
5106 |
bucketcount = elf_hash_table (info)->bucketcount; |
5107 |
bfd_qsort (sinfo.sorted_syms, sinfo.sorted_size, |
5108 |
sizeof (struct elf_link_hash_entry *), |
5109 |
elf_sort_dynsym_hash, |
5110 |
&bucketcount); |
5111 |
|
5112 |
/* append everything else */ |
5113 |
sinfo.do_dynsym = FALSE; |
5114 |
elf_link_hash_traverse (elf_hash_table (info), elf_sort_collect_dynsyms, &sinfo); |
5115 |
|
5116 |
/* freed in _bfd_elf_link_hash_table_free */ |
5117 |
elf_hash_table (info)->sorted = sinfo.sorted_syms; |
5118 |
elf_hash_table (info)->sorted_size = sinfo.sorted_size; |
5119 |
|
5120 |
return TRUE; |
5121 |
} |
5122 |
|
4985 |
/* Set up the sizes and contents of the ELF dynamic sections. This is |
5123 |
/* Set up the sizes and contents of the ELF dynamic sections. This is |
4986 |
called by the ELF linker emulation before_allocation routine. We |
5124 |
called by the ELF linker emulation before_allocation routine. We |
4987 |
must set the sizes of the sections before the linker sets the |
5125 |
must set the sizes of the sections before the linker sets the |
Lines 5766-5771
Link Here
|
5766 |
section symbol for each output section, which come first. |
5904 |
section symbol for each output section, which come first. |
5767 |
Next come all of the back-end allocated local dynamic syms, |
5905 |
Next come all of the back-end allocated local dynamic syms, |
5768 |
followed by the rest of the global symbols. */ |
5906 |
followed by the rest of the global symbols. */ |
|
|
5907 |
/* To sort these optimally we need the correct bucketcount */ |
5769 |
|
5908 |
|
5770 |
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, |
5909 |
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, |
5771 |
§ion_sym_count); |
5910 |
§ion_sym_count); |
Lines 5872-5877
Link Here
|
5872 |
for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) |
6011 |
for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) |
5873 |
if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0)) |
6012 |
if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0)) |
5874 |
return FALSE; |
6013 |
return FALSE; |
|
|
6014 |
|
6015 |
/* Sort .dynsym to accelerate runtime linking */ |
6016 |
if (info->dynsort) |
6017 |
{ |
6018 |
if (!_bfd_elf_sort_dynsyms (info)) |
6019 |
return FALSE; |
6020 |
|
6021 |
/* renumber to reflect the new sorting order */ |
6022 |
_bfd_elf_link_renumber_dynsyms (output_bfd, info, |
6023 |
§ion_sym_count); |
6024 |
} |
5875 |
} |
6025 |
} |
5876 |
|
6026 |
|
5877 |
return TRUE; |
6027 |
return TRUE; |
Lines 6012-6017
Link Here
|
6012 |
bfd_vma sym_mask; |
6162 |
bfd_vma sym_mask; |
6013 |
} u; |
6163 |
} u; |
6014 |
enum elf_reloc_type_class type; |
6164 |
enum elf_reloc_type_class type; |
|
|
6165 |
unsigned long elf_bucket; |
6015 |
/* We use this as an array of size int_rels_per_ext_rel. */ |
6166 |
/* We use this as an array of size int_rels_per_ext_rel. */ |
6016 |
Elf_Internal_Rela rela[1]; |
6167 |
Elf_Internal_Rela rela[1]; |
6017 |
}; |
6168 |
}; |
Lines 6048-6053
Link Here
|
6048 |
const struct elf_link_sort_rela *b = B; |
6199 |
const struct elf_link_sort_rela *b = B; |
6049 |
int copya, copyb; |
6200 |
int copya, copyb; |
6050 |
|
6201 |
|
|
|
6202 |
if (a->elf_bucket < b->elf_bucket) |
6203 |
return -1; |
6204 |
if (a->elf_bucket > b->elf_bucket) |
6205 |
return 1; |
6051 |
if (a->u.offset < b->u.offset) |
6206 |
if (a->u.offset < b->u.offset) |
6052 |
return -1; |
6207 |
return -1; |
6053 |
if (a->u.offset > b->u.offset) |
6208 |
if (a->u.offset > b->u.offset) |
Lines 6066-6073
Link Here
|
6066 |
} |
6221 |
} |
6067 |
|
6222 |
|
6068 |
static size_t |
6223 |
static size_t |
6069 |
elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) |
6224 |
elf_link_sort_relocs (bfd *abfd, struct elf_final_link_info *finfo, asection **psec) |
6070 |
{ |
6225 |
{ |
|
|
6226 |
struct bfd_link_info *info = finfo->info; |
6071 |
asection *reldyn; |
6227 |
asection *reldyn; |
6072 |
bfd_size_type count, size; |
6228 |
bfd_size_type count, size; |
6073 |
size_t i, ret, sort_elt, ext_size; |
6229 |
size_t i, ret, sort_elt, ext_size; |
Lines 6079-6084
Link Here
|
6079 |
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
6235 |
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
6080 |
struct bfd_link_order *lo; |
6236 |
struct bfd_link_order *lo; |
6081 |
bfd_vma r_sym_mask; |
6237 |
bfd_vma r_sym_mask; |
|
|
6238 |
int r_sym_shift; |
6082 |
|
6239 |
|
6083 |
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); |
6240 |
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); |
6084 |
if (reldyn == NULL || reldyn->size == 0) |
6241 |
if (reldyn == NULL || reldyn->size == 0) |
Lines 6120-6134
Link Here
|
6120 |
} |
6277 |
} |
6121 |
|
6278 |
|
6122 |
if (bed->s->arch_size == 32) |
6279 |
if (bed->s->arch_size == 32) |
6123 |
r_sym_mask = ~(bfd_vma) 0xff; |
6280 |
{ |
|
|
6281 |
r_sym_mask = ~(bfd_vma) 0xff; |
6282 |
r_sym_shift = 8; |
6283 |
} |
6124 |
else |
6284 |
else |
6125 |
r_sym_mask = ~(bfd_vma) 0xffffffff; |
6285 |
{ |
|
|
6286 |
r_sym_mask = ~(bfd_vma) 0xffffffff; |
6287 |
r_sym_shift = 32; |
6288 |
} |
6126 |
|
6289 |
|
6127 |
for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next) |
6290 |
for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next) |
6128 |
if (lo->type == bfd_indirect_link_order) |
6291 |
if (lo->type == bfd_indirect_link_order) |
6129 |
{ |
6292 |
{ |
6130 |
bfd_byte *erel, *erelend; |
6293 |
bfd_byte *erel, *erelend; |
6131 |
asection *o = lo->u.indirect.section; |
6294 |
asection *o = lo->u.indirect.section; |
|
|
6295 |
int base_offset = -1; |
6296 |
int base_max = 0; |
6297 |
|
6298 |
if (elf_hash_table (info)->sorted_size > 0) |
6299 |
{ |
6300 |
base_offset = elf_hash_table (info)->sorted[0]->dynindx; |
6301 |
base_max = base_offset + elf_hash_table (info)->sorted_size; |
6302 |
} |
6132 |
|
6303 |
|
6133 |
if (o->contents == NULL && o->size != 0) |
6304 |
if (o->contents == NULL && o->size != 0) |
6134 |
{ |
6305 |
{ |
Lines 6143-6152
Link Here
|
6143 |
p = sort + o->output_offset / ext_size * sort_elt; |
6314 |
p = sort + o->output_offset / ext_size * sort_elt; |
6144 |
while (erel < erelend) |
6315 |
while (erel < erelend) |
6145 |
{ |
6316 |
{ |
|
|
6317 |
long dyn_idx; |
6318 |
size_t bucketcount = elf_hash_table (info)->bucketcount; |
6146 |
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; |
6319 |
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; |
6147 |
(*swap_in) (abfd, erel, s->rela); |
6320 |
(*swap_in) (abfd, erel, s->rela); |
6148 |
s->type = (*bed->elf_backend_reloc_type_class) (s->rela); |
6321 |
s->type = (*bed->elf_backend_reloc_type_class) (s->rela); |
6149 |
s->u.sym_mask = r_sym_mask; |
6322 |
s->u.sym_mask = r_sym_mask; |
|
|
6323 |
|
6324 |
if (s->type != reloc_class_relative) |
6325 |
dyn_idx = s->rela->r_info >> r_sym_shift; |
6326 |
else |
6327 |
dyn_idx = -1; |
6328 |
|
6329 |
if (info->dynsort && base_offset >= 0 && |
6330 |
dyn_idx < base_max && dyn_idx >= base_offset) |
6331 |
s->elf_bucket = elf_hash_table (info)->sorted [dyn_idx - base_offset]->u.elf_hash_value % bucketcount; |
6332 |
else |
6333 |
s->elf_bucket = 0; |
6334 |
|
6150 |
p += sort_elt; |
6335 |
p += sort_elt; |
6151 |
erel += ext_size; |
6336 |
erel += ext_size; |
6152 |
} |
6337 |
} |
Lines 8612-8618
Link Here
|
8612 |
} |
8797 |
} |
8613 |
|
8798 |
|
8614 |
if (dynamic && info->combreloc && dynobj != NULL) |
8799 |
if (dynamic && info->combreloc && dynobj != NULL) |
8615 |
relativecount = elf_link_sort_relocs (abfd, info, &reldyn); |
8800 |
relativecount = elf_link_sort_relocs (abfd, &finfo, &reldyn); |
8616 |
|
8801 |
|
8617 |
/* If we are linking against a dynamic object, or generating a |
8802 |
/* If we are linking against a dynamic object, or generating a |
8618 |
shared library, finish up the dynamic linking information. */ |
8803 |
shared library, finish up the dynamic linking information. */ |