9783e04a64
check the result for NULL. Most set bfd_error to no_memory and return in that case; a few are harder to fix, and are marked with "FIXME <return type>". * elf32-hppa.c (hppa_elf_build_arg_reloc_stub hppa_elf_build_long_branch_stub): Check bfd_make_empty_symbol return. * linker.c (_bfd_generic_link_output_symbols _bfd_generic_link_write_global_symbol): Ditto * section.c (bfd_make_section_anyway): Ditto. * tekhex.c (find_chunk tekhex_mkobject): Check bfd_alloc. (first_phase): Ditto. FIXME void (tekhex_make_empty_symbol): Check bfd_zalloc. * sunos.c (sunos_read_dynamic_info): Check bfd_zalloc. (MY(read_dynamic_symbols) MY(read_dynamic_relocs)): Check bfd_alloc. * stringhash.c (_bfd_stringtab_hash_newfunc): Check bfd_hash_allocate. * srec.c: Indent. (fillup_symbols): Check bfd_alloc. FIXME void (srec_mkobject srec_get_section_contents srec_set_section_contents): Check bfd_alloc. (srec_make_empty_symbol): Check bfd_zalloc. * som.c (hppa_som_gen_reloc_type): Check bfd_alloc_by_size_t. (make_unique_section): Check bfd_alloc. (som_new_section_hook): Check bfd_zalloc. (bfd_som_attach_aux_hdr): Ditto. FIXME void * rs6000-core.c (rs6000coff_core_p): Check bfd_zalloc. * osf-core.c (osf_core_make_empty_symbol): Check bfd_zalloc. (osf_core_core_file_p): Check bfd_alloc. * oasys.c (oasys_slurp_symbol_table oasys_archive_p oasys_mkobject oasys_object_p oasys_new_section_hook oasys_set_section_contents): Check bfd_alloc. (oasys_slurp_section_data): Check bfd_zalloc and bfd_alloc. (oasys_make_empty_symbol): Check bfd_zalloc. * nlmcode.h (nlm_make_empty_symbol): Check bfd_zalloc. (nlm_slurp_symbol_table): Check bfd_zalloc and bfd_alloc. * nlm32-sparc.c (nlm_sparc_read_import): Check bfd_alloc. * nlm32-i386.c (nlm_i386_read_import): Check bfd_alloc. * nlm32-alpha.c (nlm_alpha_read_import): Check bfd_alloc. * linker.c (_bfd_link_hash_newfunc (generic_link_hash_newfunc (archive_hash_newfunc (_bfd_generic_link_add_one_symbol): Check bfd_hash_allocate. (_bfd_generic_final_link (_bfd_generic_link_output_symbols (default_indirect_link_order): Check bfd_alloc. (bfd_new_link_order): Check bfd_alloc_by_size_t. * irix-core.c (irix_core_make_empty_symbol): Check bfd_zalloc. * ieee.c: Indent. (read_id get_symbol get_section_entry ieee_archive_p ieee_object_p ieee_slurp_section_data ieee_new_section_hook): Check bfd_alloc. (do_one): Check bfd_alloc. Return a boolean. (ieee_slurp_section_data): Check it. (init_for_output): Check bfd_alloc. Return a boolean. (ieee_set_section_contents): Check it. (do_with_relocs): Check bfd_alloc. Return a boolean. (ieee_bfd_debug_info_accumulate): Ditto. FIXME void. (ieee_mkobject): Check bfd_zalloc. (ieee_make_empty_symbol): Check bfd_zmalloc. * hpux-core.c (hpux_core_make_empty_symbol): Check bfd_zalloc. * hppabsd-core.c (hppabsd_core_make_empty_symbol): Check bfd_zalloc. (hppabsd_core_core_file_p): Check bfd_zalloc. * hp300hpux.c (MY(slurp_symbol_table)): Check bfd_alloc. * elfcode.h (elf_new_section_hook): Check bfd_alloc. (bfd_section_from_phdr): Ditto. (write_relocs): Ditto. FIXME void (elf_map_symbols assign_section_numbers map_program_segments): Ditto. Return a boolean. (swap_out_syms): Ditto. Check elf_map_symbols. (elf_slurp_symbol_table): Check bfd_zalloc. (elf_slurp_reloca_table): Check bfd_alloc. (elf_slurp_reloc_table): Ditto. (elf_compute_section_file_positions): Check assign_section_numbers. (assign_file_positions_except_relocs): Return a boolean. Check map_program_segments. (elf_compute_section_file_positions): Check it. * elf32-mips.c (mips_elf_final_link): Check bfd_alloc. * elf32-hppa.c (hppa_elf_stub_branch_reloc): Check bfd_zmalloc and realloc. (hppa_elf_stub_reloc): Ditto. (hppa_elf_build_arg_reloc_stub): Check bfd_zalloc. (hppa_elf_build_long_branch_stub): Ditto. (elf32_hppa_backend_symbol_table_processing): Ditto. * ecoff.c (ecoff_set_symbol_info): Check bfd_alloc. Return a boolean. (ecoff_slurp_symbol_table): Check it. (ecoff_slurp_armap): Check bfd_alloc. (ecoff_write_armap): Check bfd_zalloc. (ecoff_link_hash_newfunc): Check bfd_hash_allocate and _bfd_link_hash_newfunc. (ecoff_link_add_externals): Check bfd_alloc. * ctor.c (bfd_constructor_entry): Check bfd_alloc. * coffgen.c (coff_real_object_p): Check bfd_alloc. (coff_renumber_symbols): Check bfd_alloc_by_size_t. Return a boolean. (coff_write_symbol): Check bfd_alloc. FIXME int (coff_write_linenumbers): Check bfd_alloc. Return a boolean. (coff_section_symbol): Check bfd_alloc_by_size_t. (coff_get_normalized_symtab): Check bfd_alloc. (coff_bfd_make_debug_symbol): Check bfd_zalloc. * libcoff-in.h: Change decls of coff_renumber_symbols, coff_write_linenumbers. * libcoff.h: Rebuilt. * coffcode.h (coff_write_object_contents): Check coff_renumber_symbols, coff_write_linenumbers. * coffcode.h: Indent. (coff_add_missing_symbols): Check bfd_alloc_by_size_t. Return a boolean. (coff_write_object_contents): Check it. * coff-alpha.c (alpha_relocate_section): Check bfd_alloc. * coff-mips.c (mips_relocate_section): Ditto. * archive.c (bfd_slurp_bsd_armap_f2): Check bfd_alloc value. (do_slurp_bsd_armap): Ditto. (compute_and_write_armap): Check bfd_realloc value. * aoutx.h (translate_from_native_sym_flags): Check bfd_alloc return value. Return boolean value. (NAME(aout,make_empty_symbol)): Check bfd_zalloc return value. (NAME(aout,slurp_symbol_table)): Check bf_alloc and bfd_zalloc return value. (add_to_stringtab): Ditto. FIXME void (aout_link_hash_newfunc): Check bfd_hash_allocate return value. (aout_link_add_symbols): Check bfd_alloc value. (translate_symbol_table): Check translate_from_native_sym_flags. * hp300hpux.c (MY(slurp_symbol_table)): Ditto. * aoutx.h (aout_link_hash_newfunc): Check _bfd_link_hash_newfunc. * opncls.c (bfd_zalloc bfd_realloc): Check result of bfd_alloc. * opncls.c (obstack_chunk_alloc): Define as malloc, not bfd_xmalloc_by_size_t. (_bfd_new_bfd): Check obstack_begin for 0 return. * ieee.c (obstack_chunk_alloc): Define as malloc, not bfd_xmalloc_by_size_t. (ieee_archive_p): Check obstack_begin for 0 return and obstack_finish for NULL return. * hash.c (obstack_chunk_alloc): Define as malloc, not bfd_xmalloc_by_size_t. (bfd_hash_table_init_n): Check obstack_begin for 0 return and obstack_finish for NULL return. (bfd_hash_lookup): Check obstack_alloc for NULL return. * ecofflink.c (obstack_chunk_alloc): Define as malloc, not bfd_xmalloc_by_size_t. bfd_ecoff_debug_accumulate bfd_ecoff_debug_accumulate_other): Check obstack_alloc. (add_file_shuffle add_memory_shuffle): Check obstack_alloc for NULL return. Return boolean, not void. (bfd_ecoff_debug_init): Check obstack_begin for 0 return. (bfd_ecoff_debug_accumulate): Check add_file_shuffle and add_memory_shuffle return. (string_hash_newfunc): Check bfd_hash_allocate and bfd_hash_newfunc. (bfd_ecoff_debug_accumulate): Check bfd_alloc. (ecoff_add_string): Check add_memory_shuffle return. * libbfd-in.h (xmalloc, bfd_xmalloc, bfd_xmalloc_by_size_t): Remove decls. * libbfd.h: Rebuilt.
310 lines
9.8 KiB
C
310 lines
9.8 KiB
C
/* BFD backend for SunOS binaries.
|
|
Copyright (C) 1990-1991 Free Software Foundation, Inc.
|
|
Written by Cygnus Support.
|
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
#define ARCH 32
|
|
#define TARGETNAME "a.out-sunos-big"
|
|
#define MY(OP) CAT(sunos_big_,OP)
|
|
|
|
#include "bfd.h"
|
|
|
|
/* Static routines defined in this file. */
|
|
|
|
struct external_nlist;
|
|
|
|
static boolean sunos_read_dynamic_info PARAMS ((bfd *));
|
|
static bfd_size_type MY(read_dynamic_symbols)
|
|
PARAMS ((bfd *, struct external_nlist **, char **, bfd_size_type *));
|
|
static bfd_size_type MY(read_dynamic_relocs) PARAMS ((bfd *, PTR *));
|
|
|
|
#define MY_read_dynamic_symbols MY(read_dynamic_symbols)
|
|
#define MY_read_dynamic_relocs MY(read_dynamic_relocs)
|
|
|
|
/* Include the usual a.out support. */
|
|
#include "aoutf1.h"
|
|
|
|
/* SunOS shared library support. We store a pointer to this structure
|
|
in obj_aout_dynamic_info (abfd). */
|
|
|
|
struct sunos_dynamic_info
|
|
{
|
|
/* Whether we found any dynamic information. */
|
|
boolean valid;
|
|
/* Dynamic information. */
|
|
struct internal_sun4_dynamic_link dyninfo;
|
|
/* Number of dynamic symbols. */
|
|
bfd_size_type dynsym_count;
|
|
/* Read in nlists for dynamic symbols. */
|
|
struct external_nlist *dynsym;
|
|
/* Read in dynamic string table. */
|
|
char *dynstr;
|
|
/* Number of dynamic relocs. */
|
|
bfd_size_type dynrel_count;
|
|
/* Read in dynamic relocs. This may be reloc_std_external or
|
|
reloc_ext_external. */
|
|
PTR dynrel;
|
|
};
|
|
|
|
/* Read in the basic dynamic information. This locates the __DYNAMIC
|
|
structure and uses it to find the dynamic_link structure. It
|
|
creates and saves a sunos_dynamic_info structure. If it can't find
|
|
__DYNAMIC, it sets the valid field of the sunos_dynamic_info
|
|
structure to false to avoid doing this work again. */
|
|
|
|
static boolean
|
|
sunos_read_dynamic_info (abfd)
|
|
bfd *abfd;
|
|
{
|
|
struct sunos_dynamic_info *info;
|
|
struct external_nlist dynsym;
|
|
char buf[sizeof "__DYNAMIC"];
|
|
asection *dynsec;
|
|
file_ptr dynoff;
|
|
struct external_sun4_dynamic dyninfo;
|
|
unsigned long dynver;
|
|
struct external_sun4_dynamic_link linkinfo;
|
|
|
|
if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
|
|
return true;
|
|
|
|
info = ((struct sunos_dynamic_info *)
|
|
bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
|
|
if (!info)
|
|
{
|
|
bfd_error = no_memory;
|
|
return false;
|
|
}
|
|
info->valid = false;
|
|
info->dynsym = NULL;
|
|
info->dynstr = NULL;
|
|
info->dynrel = NULL;
|
|
obj_aout_dynamic_info (abfd) = (PTR) info;
|
|
|
|
/* We look for the __DYNAMIC symbol to locate the dynamic linking
|
|
information. It should be the first symbol if it is defined. If
|
|
we can't find it, don't sweat it. */
|
|
if ((abfd->flags & DYNAMIC) == 0
|
|
|| bfd_get_symcount (abfd) <= 0
|
|
|| bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
|
|
|| (bfd_read ((PTR) &dynsym, 1, EXTERNAL_NLIST_SIZE, abfd)
|
|
!= EXTERNAL_NLIST_SIZE)
|
|
|| ((dynsym.e_type[0] & N_TYPE) != N_DATA
|
|
&& (dynsym.e_type[0] & N_TYPE) != N_TEXT)
|
|
|| bfd_seek (abfd,
|
|
obj_str_filepos (abfd) + GET_WORD (abfd, dynsym.e_strx),
|
|
SEEK_SET) != 0
|
|
|| bfd_read ((PTR) buf, 1, sizeof buf, abfd) != sizeof buf
|
|
|| buf[sizeof buf - 1] != '\0'
|
|
|| strcmp (buf, "__DYNAMIC") != 0)
|
|
return true;
|
|
|
|
if ((dynsym.e_type[0] & N_TYPE) == N_DATA)
|
|
dynsec = obj_datasec (abfd);
|
|
else
|
|
dynsec = obj_textsec (abfd);
|
|
if (! bfd_get_section_contents (abfd, dynsec, (PTR) &dyninfo,
|
|
(GET_WORD (abfd, dynsym.e_value)
|
|
- bfd_get_section_vma (abfd, dynsec)),
|
|
sizeof dyninfo))
|
|
return true;
|
|
|
|
dynver = GET_WORD (abfd, dyninfo.ld_version);
|
|
if (dynver != 2 && dynver != 3)
|
|
return true;
|
|
|
|
dynoff = GET_WORD (abfd, dyninfo.ld);
|
|
|
|
/* dynoff is a virtual address. It is probably always in the .data
|
|
section, but this code should work even if it moves. */
|
|
if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd)))
|
|
dynsec = obj_textsec (abfd);
|
|
else
|
|
dynsec = obj_datasec (abfd);
|
|
dynoff -= bfd_get_section_vma (abfd, dynsec);
|
|
if (dynoff < 0 || dynoff > bfd_section_size (abfd, dynsec))
|
|
return true;
|
|
|
|
/* This executable appears to be dynamically linked in a way that we
|
|
can understand. */
|
|
if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff,
|
|
(bfd_size_type) sizeof linkinfo))
|
|
return true;
|
|
|
|
/* Swap in the dynamic link information. */
|
|
info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded);
|
|
info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need);
|
|
info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules);
|
|
info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got);
|
|
info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt);
|
|
info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel);
|
|
info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash);
|
|
info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab);
|
|
info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash);
|
|
info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets);
|
|
info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols);
|
|
info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size);
|
|
info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
|
|
info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
|
|
|
|
/* The only way to get the size of the symbol information appears to
|
|
be to determine the distance between it and the string table. */
|
|
info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
|
|
/ EXTERNAL_NLIST_SIZE);
|
|
BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
|
|
== info->dyninfo.ld_symbols - info->dyninfo.ld_stab);
|
|
|
|
/* Similarly, the relocs end at the hash table. */
|
|
info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
|
|
/ obj_reloc_entry_size (abfd));
|
|
BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
|
|
== info->dyninfo.ld_hash - info->dyninfo.ld_rel);
|
|
|
|
info->valid = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Read in the dynamic symbols. */
|
|
|
|
static bfd_size_type
|
|
MY(read_dynamic_symbols) (abfd, syms, strs, strsize)
|
|
bfd *abfd;
|
|
struct external_nlist **syms;
|
|
char **strs;
|
|
bfd_size_type *strsize;
|
|
{
|
|
struct sunos_dynamic_info *info;
|
|
|
|
if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
|
|
{
|
|
if (! sunos_read_dynamic_info (abfd))
|
|
return (bfd_size_type) -1;
|
|
}
|
|
|
|
info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
|
|
if (! info->valid || info->dynsym_count == 0)
|
|
return 0;
|
|
|
|
if (info->dynsym == (struct external_nlist *) NULL)
|
|
{
|
|
info->dynsym = ((struct external_nlist *)
|
|
bfd_alloc (abfd,
|
|
(info->dynsym_count
|
|
* EXTERNAL_NLIST_SIZE)));
|
|
info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
|
|
if (!info->dynsym || !info->dynstr)
|
|
{
|
|
bfd_error = no_memory;
|
|
return 0;
|
|
}
|
|
if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0
|
|
|| (bfd_read ((PTR) info->dynsym, info->dynsym_count,
|
|
EXTERNAL_NLIST_SIZE, abfd)
|
|
!= info->dynsym_count * EXTERNAL_NLIST_SIZE)
|
|
|| bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0
|
|
|| (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size,
|
|
abfd)
|
|
!= info->dyninfo.ld_symb_size))
|
|
return (bfd_size_type) -1;
|
|
}
|
|
|
|
*syms = info->dynsym;
|
|
*strs = info->dynstr;
|
|
*strsize = info->dyninfo.ld_symb_size;
|
|
|
|
#ifdef CHECK_DYNAMIC_HASH
|
|
/* Check my understanding of the dynamic hash table by making sure
|
|
that each symbol can be located in the hash table. */
|
|
{
|
|
bfd_size_type table_size;
|
|
bfd_byte *table;
|
|
bfd_size_type i;
|
|
|
|
if (info->dyninfo.ld_buckets > info->dynsym_count)
|
|
abort ();
|
|
table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
|
|
table = (bfd_byte *) alloca (table_size);
|
|
if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
|
|
|| bfd_read ((PTR) table, 1, table_size, abfd) != table_size)
|
|
abort ();
|
|
for (i = 0; i < info->dynsym_count; i++)
|
|
{
|
|
unsigned char *name;
|
|
unsigned long hash;
|
|
|
|
name = ((unsigned char *) info->dynstr
|
|
+ GET_WORD (abfd, info->dynsym[i].e_strx));
|
|
hash = 0;
|
|
while (*name != '\0')
|
|
hash = (hash << 1) + *name++;
|
|
hash &= 0x7fffffff;
|
|
hash %= info->dyninfo.ld_buckets;
|
|
while (GET_WORD (abfd, table + 8 * hash) != i)
|
|
{
|
|
hash = GET_WORD (abfd, table + 8 * hash + 4);
|
|
if (hash == 0 || hash >= table_size / 8)
|
|
abort ();
|
|
}
|
|
}
|
|
}
|
|
#endif /* CHECK_DYNAMIC_HASH */
|
|
|
|
return info->dynsym_count;
|
|
}
|
|
|
|
/* Read in the dynamic relocs for a section. */
|
|
|
|
static bfd_size_type
|
|
MY(read_dynamic_relocs) (abfd, relocs)
|
|
bfd *abfd;
|
|
PTR *relocs;
|
|
{
|
|
struct sunos_dynamic_info *info;
|
|
|
|
if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
|
|
{
|
|
if (! sunos_read_dynamic_info (abfd))
|
|
return (bfd_size_type) -1;
|
|
}
|
|
|
|
info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
|
|
if (! info->valid || info->dynrel_count == 0)
|
|
return 0;
|
|
|
|
if (info->dynrel == NULL)
|
|
{
|
|
info->dynrel = (PTR) bfd_alloc (abfd,
|
|
(info->dynrel_count
|
|
* obj_reloc_entry_size (abfd)));
|
|
if (!info->dynrel)
|
|
{
|
|
bfd_error = no_memory;
|
|
return (bfd_size_type) -1;
|
|
}
|
|
if (bfd_seek (abfd, info->dyninfo.ld_rel, SEEK_SET) != 0
|
|
|| (bfd_read ((PTR) info->dynrel, info->dynrel_count,
|
|
obj_reloc_entry_size (abfd), abfd)
|
|
!= info->dynrel_count * obj_reloc_entry_size (abfd)))
|
|
return (bfd_size_type) -1;
|
|
}
|
|
|
|
*relocs = info->dynrel;
|
|
|
|
return info->dynrel_count;
|
|
}
|