|
|
| |
flags = bed->dynamic_sec_flags; | flags = bed->dynamic_sec_flags; |
| |
|
if (info->hashvals) |
|
{ |
|
s = bfd_make_section (abfd, ".suse.hashvals"); |
|
if (s == NULL |
|
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) |
|
|| ! bfd_set_section_alignment (abfd, s, 2)) |
|
return FALSE; |
|
} |
|
|
/* A dynamically linked executable has a .interp section, but a | /* A dynamically linked executable has a .interp section, but a |
shared library does not. */ | shared library does not. */ |
if (info->executable) | if (info->executable) |
|
|
memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); | memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); |
} | } |
| |
|
/* Create the direct bindings section - 1 entry per dynsym */ |
|
s = bfd_get_section_by_name (dynobj, ".suse.hashvals"); |
|
if (s) |
|
{ |
|
if (dynsymcount == 0) |
|
s->flags |= SEC_EXCLUDE; |
|
else |
|
{ |
|
s->size = dynsymcount * bed->s->sizeof_hash_entry; |
|
s->contents = bfd_zalloc (output_bfd, s->size); |
|
if (s->contents == NULL) |
|
return FALSE; |
|
memset (s->contents, 0xfe, s->size); |
|
if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_HASHVALS, 0)) |
|
return FALSE; |
|
} |
|
} |
|
|
/* Compute the size of the hashing table. As a side effect this | /* Compute the size of the hashing table. As a side effect this |
computes the hash values for all the names we export. */ | computes the hash values for all the names we export. */ |
bucketcount = compute_bucket_count (info); | bucketcount = compute_bucket_count (info); |
|
|
/* Array large enough to hold a section pointer for each local | /* Array large enough to hold a section pointer for each local |
symbol of any input BFD. */ | symbol of any input BFD. */ |
asection **sections; | asection **sections; |
|
/* .suse.hashvals section */ |
|
asection *hashvals_sec; |
/* Buffer to hold swapped out symbols. */ | /* Buffer to hold swapped out symbols. */ |
bfd_byte *symbuf; | bfd_byte *symbuf; |
/* And one for symbol section indices. */ | /* And one for symbol section indices. */ |
|
|
((bfd_byte *) finfo->hash_sec->contents | ((bfd_byte *) finfo->hash_sec->contents |
+ (bucketcount + 2 + h->dynindx) * hash_entry_size)); | + (bucketcount + 2 + h->dynindx) * hash_entry_size)); |
| |
|
if (finfo->hashvals_sec) |
|
{ |
|
bfd_vma offset = hash_entry_size * h->dynindx; |
|
if (offset > finfo->hashvals_sec->size) |
|
fprintf (stderr, "Out of bounds hashvals section index %d size %d\n", |
|
(int) offset, (int) finfo->hashvals_sec->size); |
|
else |
|
bfd_put (8 * hash_entry_size, finfo->output_bfd, |
|
h->u.elf_hash_value, |
|
finfo->hashvals_sec->contents + offset); |
|
} |
|
|
if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) | if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) |
{ | { |
Elf_Internal_Versym iversym; | Elf_Internal_Versym iversym; |
|
|
finfo.dynsym_sec = NULL; | finfo.dynsym_sec = NULL; |
finfo.hash_sec = NULL; | finfo.hash_sec = NULL; |
finfo.symver_sec = NULL; | finfo.symver_sec = NULL; |
|
finfo.hashvals_sec = NULL; |
} | } |
else | else |
{ | { |
|
|
BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL); | BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL); |
finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); | finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); |
/* Note that it is OK if symver_sec is NULL. */ | /* Note that it is OK if symver_sec is NULL. */ |
|
finfo.hashvals_sec = bfd_get_section_by_name (dynobj, ".suse.hashvals"); |
} | } |
| |
finfo.contents = NULL; | finfo.contents = NULL; |
|
|
case DT_HASH: | case DT_HASH: |
name = ".hash"; | name = ".hash"; |
goto get_vma; | goto get_vma; |
|
case DT_SUSE_HASHVALS: |
|
name = ".suse.hashvals"; |
|
goto get_vma; |
case DT_STRTAB: | case DT_STRTAB: |
name = ".dynstr"; | name = ".dynstr"; |
goto get_vma; | goto get_vma; |