+/* Scan a SunOs dynamic symbol table for symbols of interest and
+ add them to the minimal symbol table. */
+
+static void
+read_dbx_dynamic_symtab (section_offsets, objfile)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ bfd *abfd = objfile->obfd;
+ int counter;
+ bfd_size_type dynsym_count = 0;
+ struct external_nlist *dynsyms = NULL;
+ char *dynstrs = NULL;
+ bfd_size_type dynstr_size;
+ struct external_nlist *ext_symptr;
+ bfd_byte *ext_relptr;
+ bfd_size_type dynrel_count = 0;
+ PTR dynrels = NULL;
+ CORE_ADDR sym_value;
+ bfd_vma strx;
+ char *namestring;
+
+ /* Check that the symbol file has dynamic symbols that we know about.
+ bfd_arch_unknown can happen if we are reading a sun3 symbol file
+ on a sun4 host (and vice versa) and bfd is not configured
+ --with-target=all. This would trigger an assertion in bfd/sunos.c,
+ so we ignore the dynamic symbols in this case. */
+ if (bfd_get_flavour (abfd) != bfd_target_aout_flavour
+ || (bfd_get_file_flags (abfd) & DYNAMIC) == 0
+ || bfd_get_arch (abfd) == bfd_arch_unknown
+ || aout_backend_info (abfd)->read_dynamic_symbols == NULL)
+ return;
+
+ dynsym_count = ((*aout_backend_info (abfd)->read_dynamic_symbols)
+ (abfd, &dynsyms, &dynstrs, &dynstr_size));
+ if (dynsym_count == (bfd_size_type) -1)
+ return;
+
+ /* Enter dynamic symbols into the minimal symbol table
+ if this is a stripped executable. */
+ if (bfd_get_symcount (abfd) <= 0)
+ {
+ ext_symptr = dynsyms;
+ for (counter = 0; counter < dynsym_count; counter++, ext_symptr++)
+ {
+ int type = bfd_h_get_8 (abfd, ext_symptr->e_type);
+
+ switch (type)
+ {
+ case N_TEXT | N_EXT:
+ sym_value = bfd_h_get_32 (abfd, ext_symptr->e_value)
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+
+ case N_DATA:
+ case N_DATA | N_EXT:
+ sym_value = bfd_h_get_32 (abfd, ext_symptr->e_value)
+ + ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+
+ case N_BSS:
+ case N_BSS | N_EXT:
+ sym_value = bfd_h_get_32 (abfd, ext_symptr->e_value)
+ + ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+
+ default:
+ continue;
+ }
+
+ strx = bfd_h_get_32 (abfd, ext_symptr->e_strx);
+ if (strx >= dynstr_size)
+ {
+ complain (&string_table_offset_complaint, counter);
+ namestring = "<bad dynamic string table offset>";
+ }
+ else
+ namestring = strx + dynstrs;
+ record_minimal_symbol (namestring, sym_value, type, objfile);
+ }
+ }
+
+ /* Symbols from shared libraries have a dynamic relocation entry
+ that points to the associated slot in the procedure linkage table.
+ We make a mininal symbol table entry with type mst_solib_trampoline
+ at the address in the procedure linkage table. */
+ if (aout_backend_info (abfd)->read_dynamic_relocs == NULL)
+ return;
+
+ dynrel_count = ((*aout_backend_info (abfd)->read_dynamic_relocs)
+ (abfd, &dynrels));
+ if (dynrel_count == (bfd_size_type) -1)
+ return;
+
+ for (counter = 0, ext_relptr = (bfd_byte *) dynrels;
+ counter < dynrel_count;
+ counter++, ext_relptr += obj_reloc_entry_size (abfd))
+ {
+ int r_index;
+
+ if (bfd_get_arch (abfd) == bfd_arch_sparc)
+ {
+ struct reloc_ext_external *rptr =
+ (struct reloc_ext_external *) ext_relptr;
+ int r_type;
+
+ r_type = (rptr->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
+ >> RELOC_EXT_BITS_TYPE_SH_BIG;
+
+ if (r_type != RELOC_JMP_SLOT)
+ continue;
+
+ r_index = (rptr->r_index[0] << 16)
+ | (rptr->r_index[1] << 8)
+ | rptr->r_index[2];
+
+ sym_value = bfd_h_get_32 (abfd, rptr->r_address);
+ }
+ else if (bfd_get_arch (abfd) == bfd_arch_m68k)
+ {
+ struct reloc_std_external *rptr =
+ (struct reloc_std_external *) ext_relptr;
+
+ if ((rptr->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG) == 0)
+ continue;
+
+ r_index = (rptr->r_index[0] << 16)
+ | (rptr->r_index[1] << 8)
+ | rptr->r_index[2];
+
+ /* Adjust address in procedure linkage table to point to
+ the start of the bsr instruction. */
+ sym_value = bfd_h_get_32 (abfd, rptr->r_address) - 2;
+ }
+ else
+ {
+ continue;
+ }
+
+ if (r_index >= dynsym_count)
+ continue;
+ ext_symptr = dynsyms + r_index;
+ if (bfd_h_get_8 (abfd, ext_symptr->e_type) != N_EXT)
+ continue;
+
+ strx = bfd_h_get_32 (abfd, ext_symptr->e_strx);
+ if (strx >= dynstr_size)
+ {
+ complain (&string_table_offset_complaint, r_index);
+ namestring = "<bad dynamic string table offset>";
+ }
+ else
+ namestring = strx + dynstrs;
+
+ prim_record_minimal_symbol (obsavestring (namestring,
+ strlen (namestring),
+ &objfile -> symbol_obstack),
+ sym_value,
+ mst_solib_trampoline,
+ objfile);
+ }
+}
+