Lines 2945-2951
Link Here
|
2945 |
const struct elf_backend_data *bed; |
2945 |
const struct elf_backend_data *bed; |
2946 |
bfd_byte *extdyn; |
2946 |
bfd_byte *extdyn; |
2947 |
|
2947 |
|
2948 |
_bfd_elf_strtab_finalize (dynstr); |
2948 |
_bfd_elf_strtab_finalize (dynstr, info->dynsort ? |
|
|
2949 |
elf_hash_table (info)->bucketcount : 0); |
2949 |
size = _bfd_elf_strtab_size (dynstr); |
2950 |
size = _bfd_elf_strtab_size (dynstr); |
2950 |
|
2951 |
|
2951 |
bed = get_elf_backend_data (dynobj); |
2952 |
bed = get_elf_backend_data (dynobj); |
Lines 4745-4771
Link Here
|
4745 |
return FALSE; |
4746 |
return FALSE; |
4746 |
} |
4747 |
} |
4747 |
} |
4748 |
} |
4748 |
|
|
|
4749 |
/* This function will be called though elf_link_hash_traverse to store |
4750 |
all hash value of the exported symbols in an array. */ |
4751 |
|
4749 |
|
4752 |
static bfd_boolean |
4750 |
/* Compute the elf hash value of the name ignoring the version. */ |
4753 |
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) |
4751 |
unsigned long |
|
|
4752 |
_bfd_elf_ver_hash (const char *name) |
4754 |
{ |
4753 |
{ |
4755 |
unsigned long **valuep = data; |
|
|
4756 |
const char *name; |
4757 |
char *p; |
4754 |
char *p; |
4758 |
unsigned long ha; |
4755 |
unsigned long ha; |
4759 |
char *alc = NULL; |
4756 |
char *alc = NULL; |
4760 |
|
4757 |
|
4761 |
if (h->root.type == bfd_link_hash_warning) |
|
|
4762 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4763 |
|
4764 |
/* Ignore indirect symbols. These are added by the versioning code. */ |
4765 |
if (h->dynindx == -1) |
4766 |
return TRUE; |
4767 |
|
4768 |
name = h->root.root.string; |
4769 |
p = strchr (name, ELF_VER_CHR); |
4758 |
p = strchr (name, ELF_VER_CHR); |
4770 |
if (p != NULL) |
4759 |
if (p != NULL) |
4771 |
{ |
4760 |
{ |
Lines 4778-4783
Link Here
|
4778 |
/* Compute the hash value. */ |
4767 |
/* Compute the hash value. */ |
4779 |
ha = bfd_elf_hash (name); |
4768 |
ha = bfd_elf_hash (name); |
4780 |
|
4769 |
|
|
|
4770 |
if (alc != NULL) |
4771 |
free (alc); |
4772 |
|
4773 |
return ha; |
4774 |
} |
4775 |
|
4776 |
|
4777 |
/* This function will be called though elf_link_hash_traverse to store |
4778 |
all hash value of the exported symbols in an array. */ |
4779 |
|
4780 |
static bfd_boolean |
4781 |
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) |
4782 |
{ |
4783 |
unsigned long **valuep = data; |
4784 |
unsigned long ha; |
4785 |
|
4786 |
if (h->root.type == bfd_link_hash_warning) |
4787 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
4788 |
|
4789 |
/* Ignore indirect symbols. These are added by the versioning code. */ |
4790 |
if (h->dynindx == -1) |
4791 |
return TRUE; |
4792 |
|
4793 |
ha = _bfd_elf_ver_hash (h->root.root.string); |
4794 |
|
4781 |
/* Store the found hash value in the array given as the argument. */ |
4795 |
/* Store the found hash value in the array given as the argument. */ |
4782 |
*(*valuep)++ = ha; |
4796 |
*(*valuep)++ = ha; |
4783 |
|
4797 |
|
Lines 4785-4793
Link Here
|
4785 |
later. */ |
4799 |
later. */ |
4786 |
h->u.elf_hash_value = ha; |
4800 |
h->u.elf_hash_value = ha; |
4787 |
|
4801 |
|
4788 |
if (alc != NULL) |
|
|
4789 |
free (alc); |
4790 |
|
4791 |
return TRUE; |
4802 |
return TRUE; |
4792 |
} |
4803 |
} |
4793 |
|
4804 |
|
Lines 4950-4955
Link Here
|
4950 |
return best_size; |
4961 |
return best_size; |
4951 |
} |
4962 |
} |
4952 |
|
4963 |
|
|
|
4964 |
void _bfd_elf_link_hash_traverse |
4965 |
(struct elf_link_hash_table *table, |
4966 |
bfd_boolean (*func) (struct elf_link_hash_entry *, void *), |
4967 |
void *info) |
4968 |
{ |
4969 |
if (!table->sorted) |
4970 |
bfd_link_hash_traverse |
4971 |
(&(table)->root, |
4972 |
(bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), |
4973 |
(info)); |
4974 |
else |
4975 |
{ |
4976 |
unsigned int i; |
4977 |
for (i = 0; i < table->sorted_size; i++) |
4978 |
{ |
4979 |
if (! func (table->sorted[i], info)) |
4980 |
return; |
4981 |
} |
4982 |
} |
4983 |
} |
4984 |
|
4985 |
/* Sort by elf hash value % buckets. */ |
4986 |
static int |
4987 |
elf_sort_dynsym_hash (const void *arg1, const void *arg2, |
4988 |
const void *closure) |
4989 |
{ |
4990 |
size_t h1_bucket, h2_bucket; |
4991 |
const struct elf_link_hash_entry *h1; |
4992 |
const struct elf_link_hash_entry *h2; |
4993 |
const bfd_size_type *bucketcount; |
4994 |
|
4995 |
h1 = *(const struct elf_link_hash_entry **) arg1; |
4996 |
h2 = *(const struct elf_link_hash_entry **) arg2; |
4997 |
bucketcount = closure; |
4998 |
|
4999 |
h1_bucket = h1->u.elf_hash_value % *bucketcount; |
5000 |
h2_bucket = h2->u.elf_hash_value % *bucketcount; |
5001 |
|
5002 |
if (h1_bucket > h2_bucket) |
5003 |
return 1; |
5004 |
if (h1_bucket < h2_bucket) |
5005 |
return -1; |
5006 |
|
5007 |
return 0; |
5008 |
} |
5009 |
|
5010 |
struct elf_dynsym_sort_info |
5011 |
{ |
5012 |
bfd_boolean do_dynsym; |
5013 |
unsigned int alloc_size; |
5014 |
unsigned int sorted_size; |
5015 |
struct elf_link_hash_entry **sorted_syms; |
5016 |
}; |
5017 |
|
5018 |
/* collect sym entries into an array for later sorting. */ |
5019 |
static bfd_boolean |
5020 |
elf_sort_collect_dynsyms (struct elf_link_hash_entry *h, void *data) |
5021 |
{ |
5022 |
struct elf_dynsym_sort_info *sinfo = data; |
5023 |
|
5024 |
if ((sinfo->do_dynsym && h->dynindx < 0) |
5025 |
|| (!sinfo->do_dynsym && h->dynindx >= 0)) |
5026 |
return TRUE; |
5027 |
|
5028 |
if (sinfo->sorted_size >= sinfo->alloc_size) |
5029 |
{ |
5030 |
sinfo->alloc_size *= 2; |
5031 |
/* FIXME: need to free this data too ... */ |
5032 |
sinfo->sorted_syms = bfd_realloc |
5033 |
(sinfo->sorted_syms, |
5034 |
sizeof (struct elf_link_hash_entry *) * |
5035 |
sinfo->alloc_size); |
5036 |
} |
5037 |
sinfo->sorted_syms [sinfo->sorted_size++] = h; |
5038 |
|
5039 |
return TRUE; |
5040 |
} |
5041 |
|
5042 |
/* |
5043 |
* Sort the exported elf symbols by elf_hash % bucketcount to |
5044 |
* improve run-time linker cache behavior. Subsequent |
5045 |
* elf_link_hash_traverse calls will reflect this new order. |
5046 |
*/ |
5047 |
static bfd_boolean |
5048 |
_bfd_elf_sort_dynsyms (struct bfd_link_info *info) |
5049 |
{ |
5050 |
bfd_size_type bucketcount; |
5051 |
struct elf_dynsym_sort_info sinfo; |
5052 |
|
5053 |
sinfo.alloc_size = 8; |
5054 |
sinfo.sorted_syms = bfd_malloc (sizeof (struct elf_link_hash_entry *) * |
5055 |
sinfo.alloc_size); |
5056 |
if (!sinfo.sorted_syms) |
5057 |
return FALSE; |
5058 |
|
5059 |
sinfo.sorted_size = 0; |
5060 |
|
5061 |
/* append dynsyms for sorting. */ |
5062 |
sinfo.do_dynsym = TRUE; |
5063 |
elf_link_hash_traverse (elf_hash_table (info), |
5064 |
elf_sort_collect_dynsyms, &sinfo); |
5065 |
|
5066 |
/* sort. */ |
5067 |
bucketcount = elf_hash_table (info)->bucketcount; |
5068 |
bfd_qsort (sinfo.sorted_syms, sinfo.sorted_size, |
5069 |
sizeof (struct elf_link_hash_entry *), |
5070 |
elf_sort_dynsym_hash, |
5071 |
&bucketcount); |
5072 |
|
5073 |
/* append everything else. */ |
5074 |
sinfo.do_dynsym = FALSE; |
5075 |
elf_link_hash_traverse (elf_hash_table (info), |
5076 |
elf_sort_collect_dynsyms, &sinfo); |
5077 |
|
5078 |
/* freed in _bfd_elf_link_hash_table_free. */ |
5079 |
elf_hash_table (info)->sorted = sinfo.sorted_syms; |
5080 |
elf_hash_table (info)->sorted_size = sinfo.sorted_size; |
5081 |
|
5082 |
return TRUE; |
5083 |
} |
5084 |
|
4953 |
/* Set up the sizes and contents of the ELF dynamic sections. This is |
5085 |
/* Set up the sizes and contents of the ELF dynamic sections. This is |
4954 |
called by the ELF linker emulation before_allocation routine. We |
5086 |
called by the ELF linker emulation before_allocation routine. We |
4955 |
must set the sizes of the sections before the linker sets the |
5087 |
must set the sizes of the sections before the linker sets the |
Lines 5716-5721
Link Here
|
5716 |
section symbol for each output section, which come first. |
5848 |
section symbol for each output section, which come first. |
5717 |
Next come all of the back-end allocated local dynamic syms, |
5849 |
Next come all of the back-end allocated local dynamic syms, |
5718 |
followed by the rest of the global symbols. */ |
5850 |
followed by the rest of the global symbols. */ |
|
|
5851 |
/* To sort these optimally we need the correct bucketcount. */ |
5719 |
|
5852 |
|
5720 |
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, |
5853 |
dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, |
5721 |
§ion_sym_count); |
5854 |
§ion_sym_count); |
Lines 5786-5791
Link Here
|
5786 |
for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) |
5919 |
for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) |
5787 |
if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0)) |
5920 |
if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0)) |
5788 |
return FALSE; |
5921 |
return FALSE; |
|
|
5922 |
|
5923 |
/* Sort .dynsym to accelerate runtime linking. */ |
5924 |
if (info->dynsort) |
5925 |
{ |
5926 |
if (!_bfd_elf_sort_dynsyms (info)) |
5927 |
return FALSE; |
5928 |
|
5929 |
/* renumber to reflect the new sorting order. */ |
5930 |
_bfd_elf_link_renumber_dynsyms (output_bfd, info, |
5931 |
§ion_sym_count); |
5932 |
} |
5789 |
} |
5933 |
} |
5790 |
|
5934 |
|
5791 |
return TRUE; |
5935 |
return TRUE; |
Lines 5922-5927
Link Here
|
5922 |
bfd_vma sym_mask; |
6066 |
bfd_vma sym_mask; |
5923 |
} u; |
6067 |
} u; |
5924 |
enum elf_reloc_type_class type; |
6068 |
enum elf_reloc_type_class type; |
|
|
6069 |
unsigned long elf_bucket; |
5925 |
/* We use this as an array of size int_rels_per_ext_rel. */ |
6070 |
/* We use this as an array of size int_rels_per_ext_rel. */ |
5926 |
Elf_Internal_Rela rela[1]; |
6071 |
Elf_Internal_Rela rela[1]; |
5927 |
}; |
6072 |
}; |
Lines 5958-5963
Link Here
|
5958 |
const struct elf_link_sort_rela *b = B; |
6103 |
const struct elf_link_sort_rela *b = B; |
5959 |
int copya, copyb; |
6104 |
int copya, copyb; |
5960 |
|
6105 |
|
|
|
6106 |
if (a->elf_bucket < b->elf_bucket) |
6107 |
return -1; |
6108 |
if (a->elf_bucket > b->elf_bucket) |
6109 |
return 1; |
5961 |
if (a->u.offset < b->u.offset) |
6110 |
if (a->u.offset < b->u.offset) |
5962 |
return -1; |
6111 |
return -1; |
5963 |
if (a->u.offset > b->u.offset) |
6112 |
if (a->u.offset > b->u.offset) |
Lines 5976-5983
Link Here
|
5976 |
} |
6125 |
} |
5977 |
|
6126 |
|
5978 |
static size_t |
6127 |
static size_t |
5979 |
elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) |
6128 |
elf_link_sort_relocs (bfd *abfd, struct elf_final_link_info *finfo, |
|
|
6129 |
asection **psec) |
5980 |
{ |
6130 |
{ |
|
|
6131 |
struct bfd_link_info *info = finfo->info; |
5981 |
asection *reldyn; |
6132 |
asection *reldyn; |
5982 |
bfd_size_type count, size; |
6133 |
bfd_size_type count, size; |
5983 |
size_t i, ret, sort_elt, ext_size; |
6134 |
size_t i, ret, sort_elt, ext_size; |
Lines 5989-5994
Link Here
|
5989 |
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
6140 |
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
5990 |
struct bfd_link_order *lo; |
6141 |
struct bfd_link_order *lo; |
5991 |
bfd_vma r_sym_mask; |
6142 |
bfd_vma r_sym_mask; |
|
|
6143 |
int r_sym_shift; |
5992 |
|
6144 |
|
5993 |
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); |
6145 |
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); |
5994 |
if (reldyn == NULL || reldyn->size == 0) |
6146 |
if (reldyn == NULL || reldyn->size == 0) |
Lines 6030-6044
Link Here
|
6030 |
} |
6182 |
} |
6031 |
|
6183 |
|
6032 |
if (bed->s->arch_size == 32) |
6184 |
if (bed->s->arch_size == 32) |
6033 |
r_sym_mask = ~(bfd_vma) 0xff; |
6185 |
{ |
|
|
6186 |
r_sym_mask = ~(bfd_vma) 0xff; |
6187 |
r_sym_shift = 8; |
6188 |
} |
6034 |
else |
6189 |
else |
6035 |
r_sym_mask = ~(bfd_vma) 0xffffffff; |
6190 |
{ |
|
|
6191 |
r_sym_mask = ~(bfd_vma) 0xffffffff; |
6192 |
r_sym_shift = 32; |
6193 |
} |
6036 |
|
6194 |
|
6037 |
for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next) |
6195 |
for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next) |
6038 |
if (lo->type == bfd_indirect_link_order) |
6196 |
if (lo->type == bfd_indirect_link_order) |
6039 |
{ |
6197 |
{ |
6040 |
bfd_byte *erel, *erelend; |
6198 |
bfd_byte *erel, *erelend; |
6041 |
asection *o = lo->u.indirect.section; |
6199 |
asection *o = lo->u.indirect.section; |
|
|
6200 |
int base_offset = -1; |
6201 |
int base_max = 0; |
6202 |
|
6203 |
if (elf_hash_table (info)->sorted_size > 0) |
6204 |
{ |
6205 |
base_offset = elf_hash_table (info)->sorted[0]->dynindx; |
6206 |
base_max = base_offset + elf_hash_table (info)->sorted_size; |
6207 |
} |
6042 |
|
6208 |
|
6043 |
if (o->contents == NULL && o->size != 0) |
6209 |
if (o->contents == NULL && o->size != 0) |
6044 |
{ |
6210 |
{ |
Lines 6053-6062
Link Here
|
6053 |
p = sort + o->output_offset / ext_size * sort_elt; |
6219 |
p = sort + o->output_offset / ext_size * sort_elt; |
6054 |
while (erel < erelend) |
6220 |
while (erel < erelend) |
6055 |
{ |
6221 |
{ |
|
|
6222 |
long dyn_idx; |
6223 |
size_t bucketcount = elf_hash_table (info)->bucketcount; |
6056 |
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; |
6224 |
struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; |
6057 |
(*swap_in) (abfd, erel, s->rela); |
6225 |
(*swap_in) (abfd, erel, s->rela); |
6058 |
s->type = (*bed->elf_backend_reloc_type_class) (s->rela); |
6226 |
s->type = (*bed->elf_backend_reloc_type_class) (s->rela); |
6059 |
s->u.sym_mask = r_sym_mask; |
6227 |
s->u.sym_mask = r_sym_mask; |
|
|
6228 |
|
6229 |
if (s->type != reloc_class_relative) |
6230 |
dyn_idx = s->rela->r_info >> r_sym_shift; |
6231 |
else |
6232 |
dyn_idx = -1; |
6233 |
|
6234 |
if (info->dynsort && base_offset >= 0 |
6235 |
&& dyn_idx < base_max && dyn_idx >= base_offset) |
6236 |
{ |
6237 |
struct elf_link_hash_entry *ent; |
6238 |
ent = elf_hash_table (info)->sorted [dyn_idx - base_offset]; |
6239 |
s->elf_bucket = ent->u.elf_hash_value % bucketcount; |
6240 |
} |
6241 |
else |
6242 |
s->elf_bucket = 0; |
6243 |
|
6060 |
p += sort_elt; |
6244 |
p += sort_elt; |
6061 |
erel += ext_size; |
6245 |
erel += ext_size; |
6062 |
} |
6246 |
} |
Lines 8493-8499
Link Here
|
8493 |
} |
8677 |
} |
8494 |
|
8678 |
|
8495 |
if (dynamic && info->combreloc && dynobj != NULL) |
8679 |
if (dynamic && info->combreloc && dynobj != NULL) |
8496 |
relativecount = elf_link_sort_relocs (abfd, info, &reldyn); |
8680 |
relativecount = elf_link_sort_relocs (abfd, &finfo, &reldyn); |
8497 |
|
8681 |
|
8498 |
/* If we are linking against a dynamic object, or generating a |
8682 |
/* If we are linking against a dynamic object, or generating a |
8499 |
shared library, finish up the dynamic linking information. */ |
8683 |
shared library, finish up the dynamic linking information. */ |