diff options
author | Alan Modra <amodra@gmail.com> | 2002-07-07 09:10:41 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2002-07-07 09:10:41 +0000 |
commit | 6cdc0ccc1276096134b1870e92875487ffdc8292 (patch) | |
tree | d9ce6f2bb8abc152c4b8d99c9761b8c46658e619 /bfd/elflink.h | |
parent | d8462f1281a70eddafd4f2f50f142491299b69c2 (diff) | |
download | gdb-6cdc0ccc1276096134b1870e92875487ffdc8292.zip gdb-6cdc0ccc1276096134b1870e92875487ffdc8292.tar.gz gdb-6cdc0ccc1276096134b1870e92875487ffdc8292.tar.bz2 |
* elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx,
change type of locsyms.
(bfd_elf_get_elf_syms): Declare.
* elf.c (bfd_elf_get_elf_syms): New function.
(group_signature): Use bfd_elf_get_elf_syms.
(bfd_section_from_r_symndx): Likewise.
* elfcode.h (elf_slurp_symbol_table): Likewise.
* elflink.h (elf_link_is_defined_archive_symbol): Likewise.
(elf_link_add_object_symbols): Likewise. Reorganise to increase
locality of various data structures. Properly free internal relocs.
(elf_bfd_final_link): Properly free internal relocs.
(elf_link_check_versioned_symbol): Use bfd_elf_get_elf_syms.
(elf_link_input_bfd): Likewise.
(elf_gc_mark): Likewise. Properly free internal relocs.
(elf_gc_sweep): Properly free internal relocs.
(elf_reloc_symbol_deleted_p): No need to swap syms in.
(elf_bfd_discard_info): Use bfd_elf_get_elf_syms. Properly free
internal relocs.
* elf-m10200.c (mn10200_elf_relax_section): Use bfd_elf_get_elf_syms.
Properly free possibly cached info.
(mn10200_elf_relax_delete_bytes): Remove symbol swapping code.
(mn10200_elf_symbol_address_p): Pass in internal syms. Remove
symbol swapping code.
(mn10200_elf_get_relocated_section_contents): Use bfd_elf_get_elf_syms.
Properly free possibly cached info.
* elf-m10300.c (mn10300_elf_relax_section): As above for elf-m10200.c.
(mn10300_elf_relax_delete_bytes): Likewise.
(mn10300_elf_symbol_address_p): Likewise.
(mn10300_elf_get_relocated_section_contents): Likewise.
* elf32-h8300.c (elf32_h8_relax_section): As above for elf-m10200.c.
(elf32_h8_relax_delete_bytes): Likewise.
(elf32_h8_symbol_address_p): Likewise.
(elf32_h8_get_relocated_section_contents): Likewise.
* elf32-m32r.c (m32r_elf_relax_section): As above for elf-m10200.c.
(m32r_elf_relax_delete_bytes): Likewise.
(m32r_elf_get_relocated_section_contents): Likewise.
* elf32-sh.c (sh_elf_reloc_loop): Free section contents using
elf_section_data to determine whether cached.
(sh_elf_relax_section): As above for elf-m10200.c.
(sh_elf_relax_delete_bytes): Likewise.
(sh_elf_get_relocated_section_contents): Likewise.
* elf32-xstormy16.c (xstormy16_elf_relax_section): As above.
* elf64-alpha.c (elf64_alpha_relax_section): As above. Also delay
reading of local syms.
* elf64-mmix.c (mmix_elf_relax_section): Likewise.
* elf64-sh64.c (sh_elf64_get_relocated_section_contents): As above.
* elfxx-ia64.c (elfNN_ia64_relax_section): As above.
* elfxx-mips.c (_bfd_mips_elf_check_relocs): Properly free internal
relocs.
* elf32-arm.h (bfd_elf32_arm_process_before_allocation): Properly
free internal relocs and section contents. Don't read symbols.
* elf32-hppa.c (get_local_syms): Use bfd_elf_get_elf_syms.
(elf32_hppa_size_stubs): Don't free local syms.
* elf32-m68k.c (bfd_m68k_elf32_create_embedded_relocs): Delay
reading of local syms. Use bfd_elf_get_elf_syms. Properly free
possibly cached info.
* elf32-mips.c (bfd_mips_elf32_create_embedded_relocs): Likewise.
* elf64-hppa.c (elf64_hppa_check_relocs): Use bfd_elf_get_elf_syms.
* elf64-ppc.c (struct ppc_link_hash_table): Delete bfd_count and
all_local_syms.
(get_local_syms): Delete function.
(edit_opd): Use bfd_elf_get_elf_syms. Free on error exit. Cache
on exit.
(ppc64_elf_size_stubs): Use bfd_elf_get_elf_syms. Free/cache on exit.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r-- | bfd/elflink.h | 675 |
1 files changed, 245 insertions, 430 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h index 6c1d0d9..57819e9 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -149,18 +149,13 @@ elf_link_is_defined_archive_symbol (abfd, symdef) carsym * symdef; { Elf_Internal_Shdr * hdr; - Elf_Internal_Shdr * shndx_hdr; - Elf_External_Sym * esym; - Elf_External_Sym * esymend; - Elf_External_Sym * buf = NULL; - Elf_External_Sym_Shndx * shndx_buf = NULL; - Elf_External_Sym_Shndx * shndx; bfd_size_type symcount; bfd_size_type extsymcount; bfd_size_type extsymoff; - boolean result = false; - file_ptr pos; - bfd_size_type amt; + Elf_Internal_Sym *isymbuf; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + boolean result; abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset); if (abfd == (bfd *) NULL) @@ -178,15 +173,9 @@ elf_link_is_defined_archive_symbol (abfd, symdef) /* Select the appropriate symbol table. */ if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) - { - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - } + hdr = &elf_tdata (abfd)->symtab_hdr; else - { - hdr = &elf_tdata (abfd)->dynsymtab_hdr; - shndx_hdr = NULL; - } + hdr = &elf_tdata (abfd)->dynsymtab_hdr; symcount = hdr->sh_size / sizeof (Elf_External_Sym); @@ -203,58 +192,34 @@ elf_link_is_defined_archive_symbol (abfd, symdef) extsymoff = hdr->sh_info; } - amt = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (amt); - if (buf == NULL && extsymcount != 0) + if (extsymcount == 0) return false; - /* Read in the symbol table. - FIXME: This ought to be cached somewhere. */ - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, amt, abfd) != amt) - goto error_exit; - - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) - { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL && extsymcount != 0) - goto error_exit; - - pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) - goto error_exit; - } + /* Read in the symbol table. */ + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) + return false; /* Scan the symbol table looking for SYMDEF. */ - esymend = buf + extsymcount; - for (esym = buf, shndx = shndx_buf; - esym < esymend; - esym++, shndx = (shndx != NULL ? shndx + 1 : NULL)) + result = false; + for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++) { - Elf_Internal_Sym sym; - const char * name; - - elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym); + const char *name; - name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name); + name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + isym->st_name); if (name == (const char *) NULL) break; if (strcmp (name, symdef->name) == 0) { - result = is_global_data_symbol_definition (abfd, & sym); + result = is_global_data_symbol_definition (abfd, isym); break; } } - error_exit: - if (shndx_buf != NULL) - free (shndx_buf); - if (buf != NULL) - free (buf); + free (isymbuf); return result; } @@ -1186,25 +1151,20 @@ elf_link_add_object_symbols (abfd, info) asection *, const Elf_Internal_Rela *)); boolean collect; Elf_Internal_Shdr *hdr; - Elf_Internal_Shdr *shndx_hdr; bfd_size_type symcount; bfd_size_type extsymcount; bfd_size_type extsymoff; - Elf_External_Sym *buf = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_External_Sym_Shndx *shndx; struct elf_link_hash_entry **sym_hash; boolean dynamic; Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; - Elf_External_Dyn *dynbuf = NULL; struct elf_link_hash_entry *weaks; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; struct elf_backend_data *bed; boolean dt_needed; struct elf_link_hash_table * hash_table; - file_ptr pos; bfd_size_type amt; hash_table = elf_hash_table (info); @@ -1303,85 +1263,7 @@ elf_link_add_object_symbols (abfd, info) } } - /* If this is a dynamic object, we always link against the .dynsym - symbol table, not the .symtab symbol table. The dynamic linker - will only see the .dynsym symbol table, so there is no reason to - look at .symtab for a dynamic object. */ - - if (! dynamic || elf_dynsymtab (abfd) == 0) - { - hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - } - else - { - hdr = &elf_tdata (abfd)->dynsymtab_hdr; - shndx_hdr = NULL; - } - - if (dynamic) - { - /* Read in any version definitions. */ - - if (! _bfd_elf_slurp_version_tables (abfd)) - goto error_return; - - /* Read in the symbol versions, but don't bother to convert them - to internal format. */ - if (elf_dynversym (abfd) != 0) - { - Elf_Internal_Shdr *versymhdr; - - versymhdr = &elf_tdata (abfd)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); - if (extversym == NULL) - goto error_return; - amt = versymhdr->sh_size; - if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extversym, amt, abfd) != amt) - goto error_return; - } - } - - symcount = hdr->sh_size / sizeof (Elf_External_Sym); - - /* The sh_info field of the symtab header tells us where the - external symbols start. We don't care about the local symbols at - this point. */ - if (elf_bad_symtab (abfd)) - { - extsymcount = symcount; - extsymoff = 0; - } - else - { - extsymcount = symcount - hdr->sh_info; - extsymoff = hdr->sh_info; - } - - amt = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (amt); - if (buf == NULL && extsymcount != 0) - goto error_return; - - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) - { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL && extsymcount != 0) - goto error_return; - } - - /* We store a pointer to the hash table entry for each external - symbol. */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); - sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt); - if (sym_hash == NULL) - goto error_return; - elf_sym_hashes (abfd) = sym_hash; - dt_needed = false; - if (! dynamic) { /* If we are creating a shared library, create all the dynamic @@ -1431,6 +1313,7 @@ elf_link_add_object_symbols (abfd, info) s = bfd_get_section_by_name (abfd, ".dynamic"); if (s != NULL) { + Elf_External_Dyn *dynbuf = NULL; Elf_External_Dyn *extdyn; Elf_External_Dyn *extdynend; int elfsec; @@ -1444,11 +1327,11 @@ elf_link_add_object_symbols (abfd, info) if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0, s->_raw_size)) - goto error_return; + goto error_free_dyn; elfsec = _bfd_elf_section_from_bfd_section (abfd, s); if (elfsec == -1) - goto error_return; + goto error_free_dyn; shlink = elf_elfsections (abfd)[elfsec]->sh_link; extdyn = dynbuf; @@ -1465,7 +1348,7 @@ elf_link_add_object_symbols (abfd, info) unsigned int tagv = dyn.d_un.d_val; name = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (name == NULL) - goto error_return; + goto error_free_dyn; } if (dyn.d_tag == DT_NEEDED) { @@ -1477,11 +1360,11 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + goto error_free_dyn; memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1509,11 +1392,11 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + goto error_free_dyn; memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1537,11 +1420,15 @@ elf_link_add_object_symbols (abfd, info) n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (n == NULL || fnm == NULL) - goto error_return; + goto error_free_dyn; amt = strlen (fnm) + 1; anm = bfd_alloc (abfd, amt); if (anm == NULL) - goto error_return; + { + error_free_dyn: + free (dynbuf); + goto error_return; + } memcpy (anm, fnm, (size_t) amt); n->name = anm; n->by = abfd; @@ -1556,7 +1443,6 @@ elf_link_add_object_symbols (abfd, info) } free (dynbuf); - dynbuf = NULL; } /* We do not want to include any of the sections in a dynamic @@ -1606,10 +1492,6 @@ elf_link_add_object_symbols (abfd, info) if (dyn.d_tag == DT_NEEDED && dyn.d_un.d_val == strindex) { - if (buf != NULL) - free (buf); - if (extversym != NULL) - free (extversym); _bfd_elf_strtab_delref (hash_table->dynstr, strindex); return true; } @@ -1627,31 +1509,79 @@ elf_link_add_object_symbols (abfd, info) elf_dt_name (abfd) = name; } - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - amt = extsymcount * sizeof (Elf_External_Sym); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, amt, abfd) != amt) - goto error_return; + /* If this is a dynamic object, we always link against the .dynsym + symbol table, not the .symtab symbol table. The dynamic linker + will only see the .dynsym symbol table, so there is no reason to + look at .symtab for a dynamic object. */ + + if (! dynamic || elf_dynsymtab (abfd) == 0) + hdr = &elf_tdata (abfd)->symtab_hdr; + else + hdr = &elf_tdata (abfd)->dynsymtab_hdr; + + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + + /* The sh_info field of the symtab header tells us where the + external symbols start. We don't care about the local symbols at + this point. */ + if (elf_bad_symtab (abfd)) + { + extsymcount = symcount; + extsymoff = 0; + } + else + { + extsymcount = symcount - hdr->sh_info; + extsymoff = hdr->sh_info; + } - if (shndx_hdr != NULL && shndx_hdr->sh_size != 0) + sym_hash = NULL; + if (extsymcount != 0) { - amt = extsymcount * sizeof (Elf_External_Sym_Shndx); - pos = shndx_hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym_Shndx); - if (bfd_seek (abfd, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) + isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) goto error_return; + + /* We store a pointer to the hash table entry for each external + symbol. */ + amt = extsymcount * sizeof (struct elf_link_hash_entry *); + sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt); + if (sym_hash == NULL) + goto error_free_sym; + elf_sym_hashes (abfd) = sym_hash; + } + + if (dynamic) + { + /* Read in any version definitions. */ + if (! _bfd_elf_slurp_version_tables (abfd)) + goto error_free_sym; + + /* Read in the symbol versions, but don't bother to convert them + to internal format. */ + if (elf_dynversym (abfd) != 0) + { + Elf_Internal_Shdr *versymhdr; + + versymhdr = &elf_tdata (abfd)->dynversym_hdr; + extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); + if (extversym == NULL) + goto error_free_sym; + amt = versymhdr->sh_size; + if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 + || bfd_bread ((PTR) extversym, amt, abfd) != amt) + goto error_free_vers; + } } weaks = NULL; ever = extversym != NULL ? extversym + extsymoff : NULL; - esymend = buf + extsymcount; - for (esym = buf, shndx = shndx_buf; - esym < esymend; - esym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL), - shndx = (shndx != NULL ? shndx + 1 : NULL)) + for (isym = isymbuf, isymend = isymbuf + extsymcount; + isym < isymend; + isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) { - Elf_Internal_Sym sym; int bind; bfd_vma value; asection *sec; @@ -1666,14 +1596,12 @@ elf_link_add_object_symbols (abfd, info) override = false; - elf_swap_symbol_in (abfd, (const PTR) esym, (const PTR) shndx, &sym); - flags = BSF_NO_FLAGS; sec = NULL; - value = sym.st_value; + value = isym->st_value; *sym_hash = NULL; - bind = ELF_ST_BIND (sym.st_info); + bind = ELF_ST_BIND (isym->st_info); if (bind == STB_LOCAL) { /* This should be impossible, since ELF requires that all @@ -1684,8 +1612,8 @@ elf_link_add_object_symbols (abfd, info) } else if (bind == STB_GLOBAL) { - if (sym.st_shndx != SHN_UNDEF - && sym.st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF + && isym->st_shndx != SHN_COMMON) flags = BSF_GLOBAL; } else if (bind == STB_WEAK) @@ -1695,35 +1623,37 @@ elf_link_add_object_symbols (abfd, info) /* Leave it up to the processor backend. */ } - if (sym.st_shndx == SHN_UNDEF) + if (isym->st_shndx == SHN_UNDEF) sec = bfd_und_section_ptr; - else if (sym.st_shndx < SHN_LORESERVE || sym.st_shndx > SHN_HIRESERVE) + else if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE) { - sec = section_from_elf_index (abfd, sym.st_shndx); + sec = section_from_elf_index (abfd, isym->st_shndx); if (sec == NULL) sec = bfd_abs_section_ptr; else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) value -= sec->vma; } - else if (sym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) sec = bfd_abs_section_ptr; - else if (sym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) { sec = bfd_com_section_ptr; /* What ELF calls the size we call the value. What ELF calls the value we call the alignment. */ - value = sym.st_size; + value = isym->st_size; } else { /* Leave it up to the processor backend. */ } - name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name); + name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, + isym->st_name); if (name == (const char *) NULL) - goto error_return; + goto error_free_vers; - if (sym.st_shndx == SHN_COMMON && ELF_ST_TYPE (sym.st_info) == STT_TLS) + if (isym->st_shndx == SHN_COMMON + && ELF_ST_TYPE (isym->st_info) == STT_TLS) { asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon"); @@ -1735,15 +1665,15 @@ elf_link_add_object_symbols (abfd, info) | SEC_IS_COMMON | SEC_LINKER_CREATED | SEC_THREAD_LOCAL))) - goto error_return; + goto error_free_vers; } sec = tcomm; } else if (add_symbol_hook) { - if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec, + if (! (*add_symbol_hook) (abfd, info, isym, &name, &flags, &sec, &value)) - goto error_return; + goto error_free_vers; /* The hook function sets the name to NULL if this symbol should be skipped for some reason. */ @@ -1755,7 +1685,7 @@ elf_link_add_object_symbols (abfd, info) if (sec == (asection *) NULL) { bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } if (bfd_is_und_section (sec) @@ -1789,7 +1719,7 @@ elf_link_add_object_symbols (abfd, info) size_t namelen, verlen, newlen; char *newname, *p; - if (sym.st_shndx != SHN_UNDEF) + if (isym->st_shndx != SHN_UNDEF) { if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info) { @@ -1798,7 +1728,7 @@ elf_link_add_object_symbols (abfd, info) bfd_archive_filename (abfd), name, vernum, elf_tdata (abfd)->dynverdef_hdr.sh_info); bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } else if (vernum > 1) verstr = @@ -1838,7 +1768,7 @@ elf_link_add_object_symbols (abfd, info) (_("%s: %s: invalid needed version %d"), bfd_archive_filename (abfd), name, vernum); bfd_set_error (bfd_error_bad_value); - goto error_return; + goto error_free_vers; } } @@ -1846,12 +1776,12 @@ elf_link_add_object_symbols (abfd, info) verlen = strlen (verstr); newlen = namelen + verlen + 2; if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && sym.st_shndx != SHN_UNDEF) + && isym->st_shndx != SHN_UNDEF) ++newlen; newname = (char *) bfd_alloc (abfd, (bfd_size_type) newlen); if (newname == NULL) - goto error_return; + goto error_free_vers; memcpy (newname, name, namelen); p = newname + namelen; *p++ = ELF_VER_CHR; @@ -1859,7 +1789,7 @@ elf_link_add_object_symbols (abfd, info) we add another @ to the name. This indicates the default version of the symbol. */ if ((iver.vs_vers & VERSYM_HIDDEN) == 0 - && sym.st_shndx != SHN_UNDEF) + && isym->st_shndx != SHN_UNDEF) *p++ = ELF_VER_CHR; memcpy (p, verstr, verlen + 1); @@ -1867,10 +1797,10 @@ elf_link_add_object_symbols (abfd, info) } } - if (! elf_merge_symbol (abfd, info, name, &sym, &sec, &value, + if (! elf_merge_symbol (abfd, info, name, isym, &sec, &value, sym_hash, &override, &type_change_ok, &size_change_ok, dt_needed)) - goto error_return; + goto error_free_vers; if (override) definition = false; @@ -1898,7 +1828,7 @@ elf_link_add_object_symbols (abfd, info) if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, flags, sec, value, (const char *) NULL, false, collect, (struct bfd_link_hash_entry **) sym_hash))) - goto error_return; + goto error_free_vers; h = *sym_hash; while (h->root.type == bfd_link_hash_indirect @@ -1910,7 +1840,7 @@ elf_link_add_object_symbols (abfd, info) if (dynamic && definition && (flags & BSF_WEAK) != 0 - && ELF_ST_TYPE (sym.st_info) != STT_FUNC + && ELF_ST_TYPE (isym->st_info) != STT_FUNC && info->hash->creator->flavour == bfd_target_elf_flavour && h->weakdef == NULL) { @@ -1932,16 +1862,16 @@ elf_link_add_object_symbols (abfd, info) } /* Set the alignment of a common symbol. */ - if (sym.st_shndx == SHN_COMMON + if (isym->st_shndx == SHN_COMMON && h->root.type == bfd_link_hash_common) { unsigned int align; - align = bfd_log2 (sym.st_value); + align = bfd_log2 (isym->st_value); if (align > old_alignment /* Permit an alignment power of zero if an alignment of one is specified and no other alignments have been specified. */ - || (sym.st_value == 1 && old_alignment == 0)) + || (isym->st_value == 1 && old_alignment == 0)) h->root.u.c.p->alignment_power = align; } @@ -1952,16 +1882,16 @@ elf_link_add_object_symbols (abfd, info) int new_flag; /* Remember the symbol size and type. */ - if (sym.st_size != 0 + if (isym->st_size != 0 && (definition || h->size == 0)) { - if (h->size != 0 && h->size != sym.st_size && ! size_change_ok) + if (h->size != 0 && h->size != isym->st_size && ! size_change_ok) (*_bfd_error_handler) (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"), - name, (unsigned long) h->size, (unsigned long) sym.st_size, - bfd_archive_filename (abfd)); + name, (unsigned long) h->size, + (unsigned long) isym->st_size, bfd_archive_filename (abfd)); - h->size = sym.st_size; + h->size = isym->st_size; } /* If this is a common symbol, then we always want H->SIZE @@ -1972,37 +1902,37 @@ elf_link_add_object_symbols (abfd, info) if (h->root.type == bfd_link_hash_common) h->size = h->root.u.c.size; - if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE + if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE && (definition || h->type == STT_NOTYPE)) { if (h->type != STT_NOTYPE - && h->type != ELF_ST_TYPE (sym.st_info) + && h->type != ELF_ST_TYPE (isym->st_info) && ! type_change_ok) (*_bfd_error_handler) (_("Warning: type of symbol `%s' changed from %d to %d in %s"), - name, h->type, ELF_ST_TYPE (sym.st_info), + name, h->type, ELF_ST_TYPE (isym->st_info), bfd_archive_filename (abfd)); - h->type = ELF_ST_TYPE (sym.st_info); + h->type = ELF_ST_TYPE (isym->st_info); } /* If st_other has a processor-specific meaning, specific code might be needed here. */ - if (sym.st_other != 0) + if (isym->st_other != 0) { /* Combine visibilities, using the most constraining one. */ unsigned char hvis = ELF_ST_VISIBILITY (h->other); - unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other); + unsigned char symvis = ELF_ST_VISIBILITY (isym->st_other); if (symvis && (hvis > symvis || hvis == 0)) - h->other = sym.st_other; + h->other = isym->st_other; /* If neither has visibility, use the st_other of the definition. This is an arbitrary choice, since the other bits have no general meaning. */ if (!symvis && !hvis && (definition || h->other == 0)) - h->other = sym.st_other; + h->other = isym->st_other; } /* Set a flag in the hash table entry indicating the type of @@ -2046,21 +1976,21 @@ elf_link_add_object_symbols (abfd, info) /* Check to see if we need to add an indirect symbol for the default name. */ if (definition || h->root.type == bfd_link_hash_common) - if (! elf_add_default_symbol (abfd, info, h, name, &sym, + if (! elf_add_default_symbol (abfd, info, h, name, isym, &sec, &value, &dynsym, override, dt_needed)) - goto error_return; + goto error_free_vers; if (dynsym && h->dynindx == -1) { if (! _bfd_elf_link_record_dynamic_symbol (info, h)) - goto error_return; + goto error_free_vers; if (h->weakdef != NULL && ! new_weakdef && h->weakdef->dynindx == -1) { if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef)) - goto error_return; + goto error_free_vers; } } else if (dynsym && h->dynindx != -1) @@ -2083,7 +2013,7 @@ elf_link_add_object_symbols (abfd, info) bfd_size_type strindex; if (! is_elf_hash_table (info)) - goto error_return; + goto error_free_vers; /* The symbol from a DT_NEEDED object is referenced from the regular object to create a dynamic executable. We @@ -2094,7 +2024,7 @@ elf_link_add_object_symbols (abfd, info) strindex = _bfd_elf_strtab_add (hash_table->dynstr, elf_dt_soname (abfd), false); if (strindex == (bfd_size_type) -1) - goto error_return; + goto error_free_vers; if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) { @@ -2120,11 +2050,21 @@ elf_link_add_object_symbols (abfd, info) } if (! elf_add_dynamic_entry (info, (bfd_vma) DT_NEEDED, strindex)) - goto error_return; + goto error_free_vers; } } } + if (extversym != NULL) + { + free (extversym); + extversym = NULL; + } + + if (isymbuf != NULL) + free (isymbuf); + isymbuf = NULL; + /* Now set the weakdefs field correctly for all the weak defined symbols we found. The only way to do this is to search all the symbols. Since we only need the information for non functions in @@ -2192,24 +2132,11 @@ elf_link_add_object_symbols (abfd, info) if (! _bfd_elf_link_record_dynamic_symbol (info, hlook)) goto error_return; } - break; } } } - if (buf != NULL) - { - free (buf); - buf = NULL; - } - - if (extversym != NULL) - { - free (extversym); - extversym = NULL; - } - /* If this object is the same format as the output object, and it is not a shared library, then let the backend look through the relocs. @@ -2255,7 +2182,7 @@ elf_link_add_object_symbols (abfd, info) ok = (*check_relocs) (abfd, info, o, internal_relocs); - if (! info->keep_memory) + if (elf_section_data (o)->relocs != internal_relocs) free (internal_relocs); if (! ok) @@ -2334,13 +2261,13 @@ elf_link_add_object_symbols (abfd, info) return true; - error_return: - if (buf != NULL) - free (buf); - if (dynbuf != NULL) - free (dynbuf); + error_free_vers: if (extversym != NULL) free (extversym); + error_free_sym: + if (isymbuf != NULL) + free (isymbuf); + error_return: return false; } @@ -5050,7 +4977,7 @@ elf_bfd_final_link (abfd, info) o->reloc_count += (*bed->elf_backend_count_relocs) (sec, relocs); - if (!info->keep_memory) + if (elf_section_data (o)->relocs != relocs) free (relocs); } @@ -6072,8 +5999,6 @@ elf_link_check_versioned_symbol (info, h) { bfd *undef_bfd = h->root.u.undef.abfd; struct elf_link_loaded_list *loaded; - Elf_External_Sym *buf; - Elf_External_Versym *extversym; if ((undef_bfd->flags & DYNAMIC) == 0 || info->hash->creator->flavour != bfd_target_elf_flavour @@ -6090,11 +6015,11 @@ elf_link_check_versioned_symbol (info, h) bfd_size_type extsymcount; bfd_size_type extsymoff; Elf_Internal_Shdr *versymhdr; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + Elf_Internal_Sym *isymbuf; Elf_External_Versym *ever; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; - bfd_size_type count; - file_ptr pos; + Elf_External_Versym *extversym; input = loaded->abfd; @@ -6121,17 +6046,11 @@ elf_link_check_versioned_symbol (info, h) if (extsymcount == 0) continue; - count = extsymcount * sizeof (Elf_External_Sym); - buf = (Elf_External_Sym *) bfd_malloc (count); - if (buf == NULL) + isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff, + NULL, NULL, NULL); + if (isymbuf == NULL) return false; - /* Read in the symbol table. */ - pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym); - if (bfd_seek (input, pos, SEEK_SET) != 0 - || bfd_bread ((PTR) buf, count, input) != count) - goto error_ret; - /* Read in any version definitions. */ versymhdr = &elf_tdata (input)->dynversym_hdr; extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); @@ -6144,26 +6063,24 @@ elf_link_check_versioned_symbol (info, h) { free (extversym); error_ret: - free (buf); + free (isymbuf); return false; } ever = extversym + extsymoff; - esymend = buf + extsymcount; - for (esym = buf; esym < esymend; esym++, ever++) + isymend = isymbuf + extsymcount; + for (isym = isymbuf; isym < isymend; isym++, ever++) { const char *name; - Elf_Internal_Sym sym; Elf_Internal_Versym iver; - elf_swap_symbol_in (input, esym, NULL, &sym); - if (ELF_ST_BIND (sym.st_info) == STB_LOCAL - || sym.st_shndx == SHN_UNDEF) + if (ELF_ST_BIND (isym->st_info) == STB_LOCAL + || isym->st_shndx == SHN_UNDEF) continue; name = bfd_elf_string_from_elf_section (input, hdr->sh_link, - sym.st_name); + isym->st_name); if (strcmp (name, h->root.root.string) != 0) continue; @@ -6180,13 +6097,13 @@ elf_link_check_versioned_symbol (info, h) { /* This is the oldest (default) sym. We can use it. */ free (extversym); - free (buf); + free (isymbuf); return true; } } free (extversym); - free (buf); + free (isymbuf); } return false; @@ -6611,15 +6528,11 @@ elf_link_input_bfd (finfo, input_bfd) Elf_Internal_Sym *, asection **)); bfd *output_bfd; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; size_t locsymcount; size_t extsymoff; - Elf_External_Sym *external_syms; - Elf_External_Sym *esym; - Elf_External_Sym *esymend; - Elf_External_Sym_Shndx *shndx_buf; - Elf_External_Sym_Shndx *shndx; + Elf_Internal_Sym *isymbuf; Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; long *pindex; asection **ppsection; asection *o; @@ -6654,45 +6567,29 @@ elf_link_input_bfd (finfo, input_bfd) } /* Read the local symbols. */ - if (symtab_hdr->contents != NULL) - external_syms = (Elf_External_Sym *) symtab_hdr->contents; - else if (locsymcount == 0) - external_syms = NULL; - else - { - bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym); - external_syms = finfo->external_syms; - if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (external_syms, amt, input_bfd) != amt) + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL && locsymcount != 0) + { + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, + finfo->internal_syms, + finfo->external_syms, + finfo->locsym_shndx); + if (isymbuf == NULL) return false; } - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - shndx_buf = NULL; - if (shndx_hdr->sh_size != 0 && locsymcount != 0) - { - bfd_size_type amt = locsymcount * sizeof (Elf_External_Sym_Shndx); - shndx_buf = finfo->locsym_shndx; - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (shndx_buf, amt, input_bfd) != amt) - return false; - } - - /* Swap in the local symbols and write out the ones which we know - are going into the output file. */ - for (esym = external_syms, esymend = esym + locsymcount, - isym = finfo->internal_syms, pindex = finfo->indices, - ppsection = finfo->sections, shndx = shndx_buf; - esym < esymend; - esym++, isym++, pindex++, ppsection++, - shndx = (shndx != NULL ? shndx + 1 : NULL)) + /* Find local symbol sections and adjust values of symbols in + SEC_MERGE sections. Write out those local symbols we know are + going into the output file. */ + isymend = isymbuf + locsymcount; + for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections; + isym < isymend; + isym++, pindex++, ppsection++) { asection *isec; const char *name; Elf_Internal_Sym osym; - elf_swap_symbol_in (input_bfd, (const PTR) esym, (const PTR) shndx, - isym); *pindex = -1; if (elf_bad_symtab (input_bfd)) @@ -6731,7 +6628,7 @@ elf_link_input_bfd (finfo, input_bfd) *ppsection = isec; /* Don't output the first, undefined, symbol. */ - if (esym == external_syms) + if (ppsection == finfo->sections) continue; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) @@ -7001,7 +6898,7 @@ elf_link_input_bfd (finfo, input_bfd) if (! (*relocate_section) (output_bfd, finfo->info, input_bfd, o, contents, internal_relocs, - finfo->internal_syms, + isymbuf, finfo->sections)) return false; @@ -7085,7 +6982,7 @@ elf_link_input_bfd (finfo, input_bfd) /* This is a reloc against a local symbol. */ *rel_hash = NULL; - isym = finfo->internal_syms + r_symndx; + isym = isymbuf + r_symndx; sec = finfo->sections[r_symndx]; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) { @@ -7762,17 +7659,12 @@ elf_gc_mark (info, sec, gc_mark_hook) { Elf_Internal_Rela *relstart, *rel, *relend; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; struct elf_link_hash_entry **sym_hashes; size_t nlocsyms; size_t extsymoff; - Elf_External_Sym *locsyms, *freesyms = NULL; - Elf_External_Sym_Shndx *locsym_shndx; bfd *input_bfd = sec->owner; struct elf_backend_data *bed = get_elf_backend_data (input_bfd); - - /* GCFIXME: how to arrange so that relocs and symbols are not - reread continually? */ + Elf_Internal_Sym *isym = NULL; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -7786,37 +7678,18 @@ elf_gc_mark (info, sec, gc_mark_hook) else extsymoff = nlocsyms = symtab_hdr->sh_info; - if (symtab_hdr->contents) - locsyms = (Elf_External_Sym *) symtab_hdr->contents; - else if (nlocsyms == 0) - locsyms = NULL; - else - { - bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym); - locsyms = freesyms = bfd_malloc (amt); - if (freesyms == NULL - || bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (locsyms, amt, input_bfd) != amt) - { - ret = false; - goto out1; - } - } - - shndx_hdr = &elf_tdata (input_bfd)->symtab_shndx_hdr; - locsym_shndx = NULL; - if (shndx_hdr->sh_size != 0 && nlocsyms != 0) + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isym == NULL && nlocsyms != 0) { - bfd_size_type amt = nlocsyms * sizeof (Elf_External_Sym_Shndx); - locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (locsym_shndx, amt, input_bfd) != amt) + isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0, + NULL, NULL, NULL); + if (isym == NULL) return false; } /* Read the relocations. */ relstart = (NAME(_bfd_elf,link_read_relocs) - (sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL, + (input_bfd, sec, NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (relstart == NULL) { @@ -7830,41 +7703,20 @@ elf_gc_mark (info, sec, gc_mark_hook) unsigned long r_symndx; asection *rsec; struct elf_link_hash_entry *h; - Elf_Internal_Sym s; - Elf_External_Sym_Shndx *locshndx; r_symndx = ELF_R_SYM (rel->r_info); if (r_symndx == 0) continue; - if (elf_bad_symtab (sec->owner)) - { - locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0); - elf_swap_symbol_in (input_bfd, - (const PTR) (locsyms + r_symndx), - (const PTR) locshndx, - &s); - if (ELF_ST_BIND (s.st_info) == STB_LOCAL) - rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s); - else - { - h = sym_hashes[r_symndx - extsymoff]; - rsec = (*gc_mark_hook) (sec, info, rel, h, NULL); - } - } - else if (r_symndx >= nlocsyms) + if (r_symndx >= nlocsyms + || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL) { h = sym_hashes[r_symndx - extsymoff]; rsec = (*gc_mark_hook) (sec, info, rel, h, NULL); } else { - locshndx = locsym_shndx + (locsym_shndx ? r_symndx : 0); - elf_swap_symbol_in (input_bfd, - (const PTR) (locsyms + r_symndx), - (const PTR) locshndx, - &s); - rsec = (*gc_mark_hook) (sec, info, rel, NULL, &s); + rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]); } if (rsec && !rsec->gc_mark) @@ -7880,11 +7732,16 @@ elf_gc_mark (info, sec, gc_mark_hook) } out2: - if (!info->keep_memory) + if (elf_section_data (sec)->relocs != relstart) free (relstart); out1: - if (freesyms) - free (freesyms); + if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym) + { + if (! info->keep_memory) + free (isym); + else + symtab_hdr->contents = (unsigned char *) isym; + } } return ret; @@ -7941,7 +7798,7 @@ elf_gc_sweep (info, gc_sweep_hook) r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs); - if (!info->keep_memory) + if (elf_section_data (o)->relocs != internal_relocs) free (internal_relocs); if (!r) @@ -8439,7 +8296,6 @@ elf_reloc_symbol_deleted_p (offset, cookie) for (; rcookie->rel < rcookie->relend; rcookie->rel++) { unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info); - Elf_Internal_Sym isym; if (! rcookie->bad_symtab) if (rcookie->rel->r_offset > offset) @@ -8447,22 +8303,8 @@ elf_reloc_symbol_deleted_p (offset, cookie) if (rcookie->rel->r_offset != offset) continue; - if (rcookie->locsyms && r_symndx < rcookie->locsymcount) - { - Elf_External_Sym *lsym; - Elf_External_Sym_Shndx *lshndx; - - lsym = (Elf_External_Sym *) rcookie->locsyms + r_symndx; - lshndx = (Elf_External_Sym_Shndx *) rcookie->locsym_shndx; - if (lshndx != NULL) - lshndx += r_symndx; - elf_swap_symbol_in (rcookie->abfd, (const PTR) lsym, - (const PTR) lshndx, &isym); - } - if (r_symndx >= rcookie->locsymcount - || (rcookie->locsyms - && ELF_ST_BIND (isym.st_info) != STB_LOCAL)) + || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL) { struct elf_link_hash_entry *h; @@ -8479,17 +8321,19 @@ elf_reloc_symbol_deleted_p (offset, cookie) else return false; } - else if (rcookie->locsyms) + else { /* It's not a relocation against a global symbol, but it could be a relocation against a local symbol for a discarded section. */ asection *isec; + Elf_Internal_Sym *isym; /* Need to: get the symbol; get the section. */ - if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE) + isym = &rcookie->locsyms[r_symndx]; + if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE) { - isec = section_from_elf_index (rcookie->abfd, isym.st_shndx); + isec = section_from_elf_index (rcookie->abfd, isym->st_shndx); if (isec != NULL && elf_discarded_section (isec)) return true; } @@ -8512,8 +8356,6 @@ elf_bfd_discard_info (output_bfd, info) struct elf_reloc_cookie cookie; asection *stab, *eh, *ehdr; Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf_External_Sym *freesyms; struct elf_backend_data *bed; bfd *abfd; boolean ret = false; @@ -8564,8 +8406,6 @@ elf_bfd_discard_info (output_bfd, info) continue; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - cookie.abfd = abfd; cookie.sym_hashes = elf_sym_hashes (abfd); cookie.bad_symtab = elf_bad_symtab (abfd); @@ -8581,48 +8421,20 @@ elf_bfd_discard_info (output_bfd, info) cookie.extsymoff = symtab_hdr->sh_info; } - freesyms = NULL; - if (symtab_hdr->contents) - cookie.locsyms = (void *) symtab_hdr->contents; - else if (cookie.locsymcount == 0) - cookie.locsyms = NULL; - else + cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (cookie.locsyms == NULL && cookie.locsymcount != 0) { - bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym); - cookie.locsyms = bfd_malloc (amt); + cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, + cookie.locsymcount, 0, + NULL, NULL, NULL); if (cookie.locsyms == NULL) return false; - freesyms = cookie.locsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (cookie.locsyms, amt, abfd) != amt) - { - error_ret_free_loc: - free (cookie.locsyms); - return false; - } - } - - cookie.locsym_shndx = NULL; - if (shndx_hdr->sh_size != 0 && cookie.locsymcount != 0) - { - bfd_size_type amt; - amt = cookie.locsymcount * sizeof (Elf_External_Sym_Shndx); - cookie.locsym_shndx = bfd_malloc (amt); - if (cookie.locsym_shndx == NULL) - goto error_ret_free_loc; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (cookie.locsym_shndx, amt, abfd) != amt) - { - free (cookie.locsym_shndx); - goto error_ret_free_loc; - } } if (stab) { cookie.rels = (NAME(_bfd_elf,link_read_relocs) - (abfd, stab, (PTR) NULL, - (Elf_Internal_Rela *) NULL, + (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (cookie.rels) { @@ -8634,7 +8446,7 @@ elf_bfd_discard_info (output_bfd, info) elf_reloc_symbol_deleted_p, &cookie)) ret = true; - if (! info->keep_memory) + if (elf_section_data (stab)->relocs != cookie.rels) free (cookie.rels); } } @@ -8658,7 +8470,7 @@ elf_bfd_discard_info (output_bfd, info) elf_reloc_symbol_deleted_p, &cookie)) ret = true; - if (! info->keep_memory) + if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels) free (cookie.rels); } @@ -8668,11 +8480,14 @@ elf_bfd_discard_info (output_bfd, info) ret = true; } - if (cookie.locsym_shndx != NULL) - free (cookie.locsym_shndx); - - if (freesyms != NULL) - free (freesyms); + if (cookie.locsyms != NULL + && symtab_hdr->contents != (unsigned char *) cookie.locsyms) + { + if (! info->keep_memory) + free (cookie.locsyms); + else + symtab_hdr->contents = (unsigned char *) cookie.locsyms; + } } if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr)) |