diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 8 | ||||
-rw-r--r-- | bfd/elflink.c | 92 | ||||
-rw-r--r-- | bfd/elflink.h | 87 |
4 files changed, 108 insertions, 90 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9b46913..e626129 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2002-07-25 Alan Modra <amodra@bigpond.net.au> + + * elf-bfd.h (_bfd_elf32_link_record_local_dynamic_symbol): Define + as elf_link_record_local_dynamic_symbol. + (_bfd_elf64_link_record_local_dynamic_symbol): Likewise. + (elf_link_record_local_dynamic_symbol): Declare. Now returns int. + * elflink.h (elf_link_record_local_dynamic_symbol): Move to.. + * elflink.c: .. here. Use bfd_elf_get_elf_syms. Check whether an + attempt is made to record a symbol in a discarded section, and + return `2' in that case. + 2002-07-24 Nick Clifton <nickc@redhat.com> * po/sv.po: Updated Swedish translation. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 4623e78..8a7fff1 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1558,10 +1558,12 @@ extern Elf_Internal_Rela *_bfd_elf64_link_read_relocs #define bfd_elf64_link_record_dynamic_symbol \ _bfd_elf_link_record_dynamic_symbol -extern boolean _bfd_elf32_link_record_local_dynamic_symbol - PARAMS ((struct bfd_link_info *, bfd *, long)); -extern boolean _bfd_elf64_link_record_local_dynamic_symbol +extern int elf_link_record_local_dynamic_symbol PARAMS ((struct bfd_link_info *, bfd *, long)); +#define _bfd_elf32_link_record_local_dynamic_symbol \ + elf_link_record_local_dynamic_symbol +#define _bfd_elf64_link_record_local_dynamic_symbol \ + elf_link_record_local_dynamic_symbol extern boolean _bfd_elf_close_and_cleanup PARAMS ((bfd *)); diff --git a/bfd/elflink.c b/bfd/elflink.c index c32ff1c..f8cc645 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -302,6 +302,98 @@ _bfd_elf_link_record_dynamic_symbol (info, h) return true; } +/* Record a new local dynamic symbol. Returns 0 on failure, 1 on + success, and 2 on a failure caused by attempting to record a symbol + in a discarded section, eg. a discarded link-once section symbol. */ + +int +elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) + struct bfd_link_info *info; + bfd *input_bfd; + long input_indx; +{ + bfd_size_type amt; + struct elf_link_local_dynamic_entry *entry; + struct elf_link_hash_table *eht; + struct elf_strtab_hash *dynstr; + unsigned long dynstr_index; + char *name; + Elf_External_Sym_Shndx eshndx; + char esym[sizeof (Elf64_External_Sym)]; + + if (! is_elf_hash_table (info)) + return 0; + + /* See if the entry exists already. */ + for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) + if (entry->input_bfd == input_bfd && entry->input_indx == input_indx) + return 1; + + amt = sizeof (*entry); + entry = (struct elf_link_local_dynamic_entry *) bfd_alloc (input_bfd, amt); + if (entry == NULL) + return 0; + + /* Go find the symbol, so that we can find it's name. */ + if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr, + (size_t) 1, (size_t) input_indx, + &entry->isym, esym, &eshndx)) + { + bfd_release (input_bfd, entry); + return 0; + } + + if (entry->isym.st_shndx != SHN_UNDEF + && (entry->isym.st_shndx < SHN_LORESERVE + || entry->isym.st_shndx > SHN_HIRESERVE)) + { + asection *s; + + s = bfd_section_from_elf_index (input_bfd, entry->isym.st_shndx); + if (s == NULL || bfd_is_abs_section (s->output_section)) + { + /* We can still bfd_release here as nothing has done another + bfd_alloc. We can't do this later in this function. */ + bfd_release (input_bfd, entry); + return 2; + } + } + + name = (bfd_elf_string_from_elf_section + (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link, + entry->isym.st_name)); + + dynstr = elf_hash_table (info)->dynstr; + if (dynstr == NULL) + { + /* Create a strtab to hold the dynamic symbol names. */ + elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init (); + if (dynstr == NULL) + return 0; + } + + dynstr_index = _bfd_elf_strtab_add (dynstr, name, false); + if (dynstr_index == (unsigned long) -1) + return 0; + entry->isym.st_name = dynstr_index; + + eht = elf_hash_table (info); + + entry->next = eht->dynlocal; + eht->dynlocal = entry; + entry->input_bfd = input_bfd; + entry->input_indx = input_indx; + eht->dynsymcount++; + + /* Whatever binding the symbol had before, it's now local. */ + entry->isym.st_info + = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info)); + + /* The dynindx will be set at the end of size_dynamic_sections. */ + + return 1; +} + /* Return the dynindex of a local dynamic symbol. */ long diff --git a/bfd/elflink.h b/bfd/elflink.h index 956f691..29c5551 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -2448,93 +2448,6 @@ elf_add_dynamic_entry (info, tag, val) return true; } - -/* Record a new local dynamic symbol. */ - -boolean -elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) - struct bfd_link_info *info; - bfd *input_bfd; - long input_indx; -{ - struct elf_link_local_dynamic_entry *entry; - struct elf_link_hash_table *eht; - struct elf_strtab_hash *dynstr; - Elf_External_Sym esym; - Elf_External_Sym_Shndx eshndx; - Elf_External_Sym_Shndx *shndx; - unsigned long dynstr_index; - char *name; - file_ptr pos; - bfd_size_type amt; - - if (! is_elf_hash_table (info)) - return false; - - /* See if the entry exists already. */ - for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) - if (entry->input_bfd == input_bfd && entry->input_indx == input_indx) - return true; - - entry = (struct elf_link_local_dynamic_entry *) - bfd_alloc (input_bfd, (bfd_size_type) sizeof (*entry)); - if (entry == NULL) - return false; - - /* Go find the symbol, so that we can find it's name. */ - amt = sizeof (Elf_External_Sym); - pos = elf_tdata (input_bfd)->symtab_hdr.sh_offset + input_indx * amt; - if (bfd_seek (input_bfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) &esym, amt, input_bfd) != amt) - return false; - shndx = NULL; - if (elf_tdata (input_bfd)->symtab_shndx_hdr.sh_size != 0) - { - amt = sizeof (Elf_External_Sym_Shndx); - pos = elf_tdata (input_bfd)->symtab_shndx_hdr.sh_offset; - pos += input_indx * amt; - shndx = &eshndx; - if (bfd_seek (input_bfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx, amt, input_bfd) != amt) - return false; - } - elf_swap_symbol_in (input_bfd, (const PTR) &esym, (const PTR) shndx, - &entry->isym); - - name = (bfd_elf_string_from_elf_section - (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link, - entry->isym.st_name)); - - dynstr = elf_hash_table (info)->dynstr; - if (dynstr == NULL) - { - /* Create a strtab to hold the dynamic symbol names. */ - elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init (); - if (dynstr == NULL) - return false; - } - - dynstr_index = _bfd_elf_strtab_add (dynstr, name, false); - if (dynstr_index == (unsigned long) -1) - return false; - entry->isym.st_name = dynstr_index; - - eht = elf_hash_table (info); - - entry->next = eht->dynlocal; - eht->dynlocal = entry; - entry->input_bfd = input_bfd; - entry->input_indx = input_indx; - eht->dynsymcount++; - - /* Whatever binding the symbol had before, it's now local. */ - entry->isym.st_info - = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info)); - - /* The dynindx will be set at the end of size_dynamic_sections. */ - - return true; -} /* Read and swap the relocs from the section indicated by SHDR. This may be either a REL or a RELA section. The relocations are |