diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 2 | ||||
-rw-r--r-- | bfd/elf.c | 194 | ||||
-rw-r--r-- | bfd/elfcode.h | 2 | ||||
-rw-r--r-- | bfd/elflink.c | 174 |
5 files changed, 227 insertions, 156 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8c46cd6..ab001ce 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2004-11-04 Paul Brook <paul@codesourcery.com> + + * elf-bfd.h (_bfd_elf_slurp_version_tables): Update prototype. + * elf.c (_bfd_elf_print_private_bfd_data): Pass extra argument. + (_bfd_elf_slurp_version_tables): Add extra argument. Create extra + default version definition for unversioned symbols. + * elfcode.h (elf_slurp_symbol_table): Pass extra argument. + * elflink.c (elf_link_add_object_symbols): Pass extra argument to + _bfd_elf_slurp_version_tables. Set default version for unversioned + imported symbols. + 2004-11-15 Paul Brook <paul@codesourcery.com> * elflink.c (elf_link_add_object_symbols): Don't assume version diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index ff26613..541ad25 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1419,7 +1419,7 @@ extern bfd_boolean _bfd_elf_link_hash_table_init struct bfd_hash_entry *(*) (struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); extern bfd_boolean _bfd_elf_slurp_version_tables - (bfd *); + (bfd *, bfd_boolean); extern bfd_boolean _bfd_elf_merge_sections (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_is_group_section @@ -1192,7 +1192,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg) if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL) || (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL)) { - if (! _bfd_elf_slurp_version_tables (abfd)) + if (! _bfd_elf_slurp_version_tables (abfd, FALSE)) return FALSE; } @@ -6027,10 +6027,94 @@ _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd, /* Read in the version information. */ bfd_boolean -_bfd_elf_slurp_version_tables (bfd *abfd) +_bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver) { bfd_byte *contents = NULL; bfd_size_type amt; + unsigned int freeidx = 0; + + if (elf_dynverref (abfd) != 0) + { + Elf_Internal_Shdr *hdr; + Elf_External_Verneed *everneed; + Elf_Internal_Verneed *iverneed; + unsigned int i; + + hdr = &elf_tdata (abfd)->dynverref_hdr; + + amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed); + elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt); + if (elf_tdata (abfd)->verref == NULL) + goto error_return; + + elf_tdata (abfd)->cverrefs = hdr->sh_info; + + contents = bfd_malloc (hdr->sh_size); + if (contents == NULL) + goto error_return; + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 + || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size) + goto error_return; + + everneed = (Elf_External_Verneed *) contents; + iverneed = elf_tdata (abfd)->verref; + for (i = 0; i < hdr->sh_info; i++, iverneed++) + { + Elf_External_Vernaux *evernaux; + Elf_Internal_Vernaux *ivernaux; + unsigned int j; + + _bfd_elf_swap_verneed_in (abfd, everneed, iverneed); + + iverneed->vn_bfd = abfd; + + iverneed->vn_filename = + bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + iverneed->vn_file); + if (iverneed->vn_filename == NULL) + goto error_return; + + amt = iverneed->vn_cnt; + amt *= sizeof (Elf_Internal_Vernaux); + iverneed->vn_auxptr = bfd_alloc (abfd, amt); + + evernaux = ((Elf_External_Vernaux *) + ((bfd_byte *) everneed + iverneed->vn_aux)); + ivernaux = iverneed->vn_auxptr; + for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++) + { + _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux); + + ivernaux->vna_nodename = + bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + ivernaux->vna_name); + if (ivernaux->vna_nodename == NULL) + goto error_return; + + if (j + 1 < iverneed->vn_cnt) + ivernaux->vna_nextptr = ivernaux + 1; + else + ivernaux->vna_nextptr = NULL; + + evernaux = ((Elf_External_Vernaux *) + ((bfd_byte *) evernaux + ivernaux->vna_next)); + + if (ivernaux->vna_other > freeidx) + freeidx = ivernaux->vna_other; + } + + if (i + 1 < hdr->sh_info) + iverneed->vn_nextref = iverneed + 1; + else + iverneed->vn_nextref = NULL; + + everneed = ((Elf_External_Verneed *) + ((bfd_byte *) everneed + iverneed->vn_next)); + } + + free (contents); + contents = NULL; + } if (elf_dynverdef (abfd) != 0) { @@ -6067,6 +6151,13 @@ _bfd_elf_slurp_version_tables (bfd *abfd) ((bfd_byte *) everdef + iverdefmem.vd_next)); } + if (default_imported_symver) + { + if (freeidx > maxidx) + maxidx = ++freeidx; + else + freeidx = ++maxidx; + } amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef); elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->verdef == NULL) @@ -6130,85 +6221,46 @@ _bfd_elf_slurp_version_tables (bfd *abfd) free (contents); contents = NULL; } - - if (elf_dynverref (abfd) != 0) + else if (default_imported_symver) { - Elf_Internal_Shdr *hdr; - Elf_External_Verneed *everneed; - Elf_Internal_Verneed *iverneed; - unsigned int i; - - hdr = &elf_tdata (abfd)->dynverref_hdr; - - amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed); - elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt); - if (elf_tdata (abfd)->verref == NULL) - goto error_return; - - elf_tdata (abfd)->cverrefs = hdr->sh_info; + if (freeidx < 3) + freeidx = 3; + else + freeidx++; - contents = bfd_malloc (hdr->sh_size); - if (contents == NULL) - goto error_return; - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size) + amt = (bfd_size_type) freeidx * sizeof (Elf_Internal_Verdef); + elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt); + if (elf_tdata (abfd)->verdef == NULL) goto error_return; - everneed = (Elf_External_Verneed *) contents; - iverneed = elf_tdata (abfd)->verref; - for (i = 0; i < hdr->sh_info; i++, iverneed++) - { - Elf_External_Vernaux *evernaux; - Elf_Internal_Vernaux *ivernaux; - unsigned int j; - - _bfd_elf_swap_verneed_in (abfd, everneed, iverneed); - - iverneed->vn_bfd = abfd; - - iverneed->vn_filename = - bfd_elf_string_from_elf_section (abfd, hdr->sh_link, - iverneed->vn_file); - if (iverneed->vn_filename == NULL) - goto error_return; - - amt = iverneed->vn_cnt; - amt *= sizeof (Elf_Internal_Vernaux); - iverneed->vn_auxptr = bfd_alloc (abfd, amt); - - evernaux = ((Elf_External_Vernaux *) - ((bfd_byte *) everneed + iverneed->vn_aux)); - ivernaux = iverneed->vn_auxptr; - for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++) - { - _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux); + elf_tdata (abfd)->cverdefs = freeidx; + } - ivernaux->vna_nodename = - bfd_elf_string_from_elf_section (abfd, hdr->sh_link, - ivernaux->vna_name); - if (ivernaux->vna_nodename == NULL) - goto error_return; + /* Create a default version based on the soname. */ + if (default_imported_symver) + { + Elf_Internal_Verdef *iverdef; + Elf_Internal_Verdaux *iverdaux; - if (j + 1 < iverneed->vn_cnt) - ivernaux->vna_nextptr = ivernaux + 1; - else - ivernaux->vna_nextptr = NULL; + iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];; - evernaux = ((Elf_External_Vernaux *) - ((bfd_byte *) evernaux + ivernaux->vna_next)); - } + iverdef->vd_version = VER_DEF_CURRENT; + iverdef->vd_flags = 0; + iverdef->vd_ndx = freeidx; + iverdef->vd_cnt = 1; - if (i + 1 < hdr->sh_info) - iverneed->vn_nextref = iverneed + 1; - else - iverneed->vn_nextref = NULL; + iverdef->vd_bfd = abfd; - everneed = ((Elf_External_Verneed *) - ((bfd_byte *) everneed + iverneed->vn_next)); - } + iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd); + if (iverdef->vd_nodename == NULL) + goto error_return; + iverdef->vd_nextdef = NULL; + amt = (bfd_size_type) sizeof (Elf_Internal_Verdaux); + iverdef->vd_auxptr = bfd_alloc (abfd, amt); - free (contents); - contents = NULL; + iverdaux = iverdef->vd_auxptr; + iverdaux->vda_nodename = iverdef->vd_nodename; + iverdaux->vda_nextptr = NULL; } return TRUE; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 7ab97bf..45c4ea9 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -1026,7 +1026,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) || (elf_tdata (abfd)->dynverref_section != 0 && elf_tdata (abfd)->verref == NULL)) { - if (! _bfd_elf_slurp_version_tables (abfd)) + if (!_bfd_elf_slurp_version_tables (abfd, FALSE)) return -1; } } diff --git a/bfd/elflink.c b/bfd/elflink.c index 4f2d096..b095312 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3347,7 +3347,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (dynamic) { /* Read in any version definitions. */ - if (! _bfd_elf_slurp_version_tables (abfd)) + if (!_bfd_elf_slurp_version_tables (abfd, + info->default_imported_symver)) goto error_free_sym; /* Read in the symbol versions, but don't bother to convert them @@ -3499,102 +3500,109 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) unsigned int vernum = 0; bfd_boolean skip; - if (ever != NULL) + if (ever == NULL) { - _bfd_elf_swap_versym_in (abfd, ever, &iver); - vernum = iver.vs_vers & VERSYM_VERSION; - - /* If this is a hidden symbol, or if it is not version - 1, we append the version name to the symbol name. - However, we do not modify a non-hidden absolute - symbol, because it might be the version symbol - itself. FIXME: What if it isn't? */ - if ((iver.vs_vers & VERSYM_HIDDEN) != 0 - || (vernum > 1 && ! bfd_is_abs_section (sec))) + if (info->default_imported_symver) + /* Use the default symbol version created earlier. */ + iver.vs_vers = elf_tdata (abfd)->cverdefs; + else + iver.vs_vers = 0; + } + else + _bfd_elf_swap_versym_in (abfd, ever, &iver); + + vernum = iver.vs_vers & VERSYM_VERSION; + + /* If this is a hidden symbol, or if it is not version + 1, we append the version name to the symbol name. + However, we do not modify a non-hidden absolute + symbol, because it might be the version symbol + itself. FIXME: What if it isn't? */ + if ((iver.vs_vers & VERSYM_HIDDEN) != 0 + || (vernum > 1 && ! bfd_is_abs_section (sec))) + { + const char *verstr; + size_t namelen, verlen, newlen; + char *newname, *p; + + if (isym->st_shndx != SHN_UNDEF) { - const char *verstr; - size_t namelen, verlen, newlen; - char *newname, *p; + if (vernum > elf_tdata (abfd)->cverdefs) + verstr = NULL; + else if (vernum > 1) + verstr = + elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; + else + verstr = ""; - if (isym->st_shndx != SHN_UNDEF) + if (verstr == NULL) { - if (vernum > elf_tdata (abfd)->cverdefs) - verstr = NULL; - else if (vernum > 1) - verstr = - elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; - else - verstr = ""; - - if (verstr == NULL) - { - (*_bfd_error_handler) - (_("%B: %s: invalid version %u (max %d)"), - abfd, name, vernum, - elf_tdata (abfd)->cverdefs); - bfd_set_error (bfd_error_bad_value); - goto error_free_vers; - } + (*_bfd_error_handler) + (_("%B: %s: invalid version %u (max %d)"), + abfd, name, vernum, + elf_tdata (abfd)->cverdefs); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; } - else + } + else + { + /* We cannot simply test for the number of + entries in the VERNEED section since the + numbers for the needed versions do not start + at 0. */ + Elf_Internal_Verneed *t; + + verstr = NULL; + for (t = elf_tdata (abfd)->verref; + t != NULL; + t = t->vn_nextref) { - /* We cannot simply test for the number of - entries in the VERNEED section since the - numbers for the needed versions do not start - at 0. */ - Elf_Internal_Verneed *t; - - verstr = NULL; - for (t = elf_tdata (abfd)->verref; - t != NULL; - t = t->vn_nextref) - { - Elf_Internal_Vernaux *a; + Elf_Internal_Vernaux *a; - for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) + for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) + { + if (a->vna_other == vernum) { - if (a->vna_other == vernum) - { - verstr = a->vna_nodename; - break; - } + verstr = a->vna_nodename; + break; } - if (a != NULL) - break; - } - if (verstr == NULL) - { - (*_bfd_error_handler) - (_("%B: %s: invalid needed version %d"), - abfd, name, vernum); - bfd_set_error (bfd_error_bad_value); - goto error_free_vers; } + if (a != NULL) + break; } + if (verstr == NULL) + { + (*_bfd_error_handler) + (_("%B: %s: invalid needed version %d"), + abfd, name, vernum); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; + } + } - namelen = strlen (name); - verlen = strlen (verstr); - newlen = namelen + verlen + 2; - if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && isym->st_shndx != SHN_UNDEF) - ++newlen; + namelen = strlen (name); + verlen = strlen (verstr); + newlen = namelen + verlen + 2; + if ((iver.vs_vers & VERSYM_HIDDEN) == 0 + && isym->st_shndx != SHN_UNDEF) + ++newlen; - newname = bfd_alloc (abfd, newlen); - if (newname == NULL) - goto error_free_vers; - memcpy (newname, name, namelen); - p = newname + namelen; - *p++ = ELF_VER_CHR; - /* If this is a defined non-hidden version symbol, - we add another @ to the name. This indicates the - default version of the symbol. */ - if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && isym->st_shndx != SHN_UNDEF) - *p++ = ELF_VER_CHR; - memcpy (p, verstr, verlen + 1); + newname = bfd_alloc (abfd, newlen); + if (newname == NULL) + goto error_free_vers; + memcpy (newname, name, namelen); + p = newname + namelen; + *p++ = ELF_VER_CHR; + /* If this is a defined non-hidden version symbol, + we add another @ to the name. This indicates the + default version of the symbol. */ + if ((iver.vs_vers & VERSYM_HIDDEN) == 0 + && isym->st_shndx != SHN_UNDEF) + *p++ = ELF_VER_CHR; + memcpy (p, verstr, verlen + 1); - name = newname; - } + name = newname; } if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value, |