Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/gnu/dist/bfd Made libbfd read and understand our a.out dynam...



details:   https://anonhg.NetBSD.org/src/rev/b38425dbfa0c
branches:  trunk
changeset: 480209:b38425dbfa0c
user:      kristerw <kristerw%NetBSD.org@localhost>
date:      Thu Jan 06 21:50:05 2000 +0000

description:
Made libbfd read and understand our a.out dynamic symbols.
Solves PR bin/7576 from Mike Neuman.

diffstat:

 gnu/dist/bfd/netbsd.h |  360 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 359 insertions(+), 1 deletions(-)

diffs (truncated from 391 to 300 lines):

diff -r bdabe7cb0d81 -r b38425dbfa0c gnu/dist/bfd/netbsd.h
--- a/gnu/dist/bfd/netbsd.h     Thu Jan 06 21:13:55 2000 +0000
+++ b/gnu/dist/bfd/netbsd.h     Thu Jan 06 21:50:05 2000 +0000
@@ -35,7 +35,7 @@
 #define N_PIC(exec) ((exec).a_info & 0x40000000)
 
 /* Determine if this is a shared library using the flags. */
-#define N_SHARED_LIB(x)        (N_DYNAMIC(x))
+#define N_SHARED_LIB(x)        (N_DYNAMIC(x) && N_PIC(x))
 
 /* We have 6 bits of flags and 10 bits of machine ID.  */
 #define N_MACHTYPE(exec) \
@@ -55,6 +55,7 @@
         ((exec).a_info & 0x03ffffff) | ((flags & 0x03f) << 26))
 
 #define BIND_WEAK       2
+#define EXTERNAL_NZLIST_SIZE 16
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -78,9 +79,14 @@
        _bfd_archive_bsd44_construct_extended_name_table
 #define MY_translate_from_native_sym_flags netbsd_translate_from_native_sym_flags
 #define MY_translate_to_native_sym_flags netbsd_translate_to_native_sym_flags
+#define MY_get_dynamic_symtab_upper_bound netbsd_get_dynamic_symtab_upper_bound
+#define MY_canonicalize_dynamic_symtab netbsd_canonicalize_dynamic_symtab
 
 static boolean netbsd_translate_from_native_sym_flags PARAMS ((bfd *, aout_symbol_type *));
 static boolean netbsd_translate_to_native_sym_flags PARAMS ((bfd *, asymbol *, struct external_nlist *));
+static long netbsd_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
+static long netbsd_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
+static boolean netbsd_slurp_dynamic_symtab PARAMS ((bfd *));
 
 #define SET_ARCH_MACH(ABFD, EXEC) \
   bfd_default_set_arch_mach(abfd, DEFAULT_ARCH, 0); \
@@ -431,3 +437,355 @@
 
   return true;
 }
+
+/* NetBSD shared library support.  We store a pointer to this structure
+   in obj_aout_dynamic_info (abfd).  */
+
+struct netbsd_dynamic_info
+{
+  /* Whether we found any dynamic information.  */
+  boolean valid;
+  /* Dynamic information.  */
+  struct internal_section_dispatch_table dyninfo;
+  /* Number of dynamic symbols.  */
+  unsigned long dynsym_count;
+  /* Read in nlists for dynamic symbols.  */
+  struct external_nlist *dynsym;
+  /* asymbol structures for dynamic symbols.  */
+  aout_symbol_type *canonical_dynsym;
+  /* Read in dynamic string table.  */
+  char *dynstr;
+  /* Number of dynamic relocs.  */
+  unsigned long dynrel_count;
+  /* Read in dynamic relocs.  This may be reloc_std_external or
+     reloc_ext_external.  */
+  PTR dynrel;
+  /* arelent structures for dynamic relocs.  */
+  arelent *canonical_dynrel;
+};
+
+struct external_nzlist {
+  bfd_byte e_strx[BYTES_IN_WORD];      /* index into string table of name */
+  bfd_byte e_type[1];                  /* type of symbol */
+  bfd_byte e_other[1];                 /* misc info */
+  bfd_byte e_desc[2];                  /* description field */
+  bfd_byte e_value[BYTES_IN_WORD];     /* value of symbol */
+  bfd_byte e_size[4];
+};
+
+static boolean netbsd_translate_symbol_table PARAMS ((bfd *, aout_symbol_type *, struct external_nzlist *, bfd_size_type, char *, bfd_size_type, boolean));
+
+/* 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
+netbsd_read_dynamic_info (abfd)
+     bfd *abfd;
+{
+  struct netbsd_dynamic_info *info;
+  asection *dynsec;
+  bfd_vma dynoff;
+  struct external_netbsd_dynamic dyninfo;
+  unsigned long dynver;
+  struct external_netbsd_dynamic_link linkinfo;
+
+  if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
+    return true;
+
+  if ((abfd->flags & DYNAMIC) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
+  info = ((struct netbsd_dynamic_info *)
+         bfd_zalloc (abfd, sizeof (struct netbsd_dynamic_info)));
+  if (!info)
+    return false;
+  info->valid = false;
+  info->dynsym = NULL;
+  info->dynstr = NULL;
+  info->canonical_dynsym = NULL;
+  info->dynrel = NULL;
+  info->canonical_dynrel = NULL;
+  obj_aout_dynamic_info (abfd) = (PTR) info;
+
+  /* This code used to look for the __DYNAMIC symbol to locate the dynamic
+     linking information.
+     However this inhibits recovering the dynamic symbols from a
+     stripped object file, so blindly assume that the dynamic linking
+     information is located at the start of the data section.
+     We could verify this assumption later by looking through the dynamic
+     symbols for the __DYNAMIC symbol.  */
+  if ((abfd->flags & DYNAMIC) == 0)
+    return true;
+  if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
+                                 (file_ptr) 0, sizeof dyninfo))
+    return true;
+
+  dynver = GET_WORD (abfd, dyninfo.d_version);
+  if (dynver != 8)
+    return true;
+
+  dynoff = GET_WORD (abfd, dyninfo.d_un);
+
+  /* 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 > 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.sdt_loaded = GET_WORD (abfd, linkinfo.sdt_loaded);
+  info->dyninfo.sdt_sods = GET_WORD (abfd, linkinfo.sdt_sods);
+  info->dyninfo.sdt_paths = GET_WORD (abfd, linkinfo.sdt_paths);
+  info->dyninfo.sdt_got = GET_WORD (abfd, linkinfo.sdt_got);
+  info->dyninfo.sdt_plt = GET_WORD (abfd, linkinfo.sdt_plt);
+  info->dyninfo.sdt_rel = GET_WORD (abfd, linkinfo.sdt_rel);
+  info->dyninfo.sdt_hash = GET_WORD (abfd, linkinfo.sdt_hash);
+  info->dyninfo.sdt_nzlist = GET_WORD (abfd, linkinfo.sdt_nzlist);
+  info->dyninfo.sdt_filler2 = GET_WORD (abfd, linkinfo.sdt_filler2);
+  info->dyninfo.sdt_buckets = GET_WORD (abfd, linkinfo.sdt_buckets);
+  info->dyninfo.sdt_strings = GET_WORD (abfd, linkinfo.sdt_strings);
+  info->dyninfo.sdt_str_sz = GET_WORD (abfd, linkinfo.sdt_str_sz);
+  info->dyninfo.sdt_text_sz = GET_WORD (abfd, linkinfo.sdt_text_sz);
+  info->dyninfo.sdt_plt_sz = GET_WORD (abfd, linkinfo.sdt_plt_sz);
+
+  /* Transform values into file offsets. */
+  {
+    struct internal_exec *execp = exec_hdr (abfd);
+    unsigned long text_addr;
+
+    text_addr = N_TXTADDR(*execp) - N_TXTOFF(*execp);
+
+    info->dyninfo.sdt_sods -= text_addr;
+    info->dyninfo.sdt_paths -= text_addr;
+    info->dyninfo.sdt_got -= text_addr;
+    info->dyninfo.sdt_plt -= text_addr;
+    info->dyninfo.sdt_rel -= text_addr;
+    info->dyninfo.sdt_hash -= text_addr;
+    info->dyninfo.sdt_nzlist -= text_addr;
+    info->dyninfo.sdt_strings -= text_addr;
+  }
+
+  /* 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.sdt_strings - info->dyninfo.sdt_nzlist)
+                       / EXTERNAL_NZLIST_SIZE);
+  BFD_ASSERT (info->dynsym_count * EXTERNAL_NZLIST_SIZE
+             == (unsigned long) (info->dyninfo.sdt_strings
+                                 - info->dyninfo.sdt_nzlist));
+
+  /* Similarly, the relocs end at the hash table.  */
+  info->dynrel_count = ((info->dyninfo.sdt_hash - info->dyninfo.sdt_rel)
+                       / obj_reloc_entry_size (abfd));
+  BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
+             == (unsigned long) (info->dyninfo.sdt_hash
+                                 - info->dyninfo.sdt_rel));
+  info->valid = true;
+
+  return true;
+}
+
+/* Return the amount of memory required for the dynamic symbols.  */
+
+static long
+netbsd_get_dynamic_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  struct netbsd_dynamic_info *info;
+
+  if (! netbsd_read_dynamic_info (abfd))
+    return -1;
+
+  info = (struct netbsd_dynamic_info *) obj_aout_dynamic_info (abfd);
+  if (! info->valid)
+    {
+      bfd_set_error (bfd_error_no_symbols);
+      return -1;
+    }
+
+  return (info->dynsym_count + 1) * sizeof (asymbol *);
+}
+
+/* Read in the dynamic symbols.  */
+
+static long
+netbsd_canonicalize_dynamic_symtab (abfd, storage)
+     bfd *abfd;
+     asymbol **storage;
+{
+  struct netbsd_dynamic_info *info;
+  unsigned long i;
+
+  if (! netbsd_slurp_dynamic_symtab (abfd))
+    return -1;
+
+  info = (struct netbsd_dynamic_info *) obj_aout_dynamic_info (abfd);
+
+  /* Get the asymbol structures corresponding to the dynamic nlist
+     structures.  */
+  if (info->canonical_dynsym == (aout_symbol_type *) NULL)
+    {
+      info->canonical_dynsym = ((aout_symbol_type *)
+                               bfd_alloc (abfd,
+                                          (info->dynsym_count
+                                           * sizeof (aout_symbol_type))));
+      if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
+       return -1;
+
+      if (! netbsd_translate_symbol_table (abfd, info->canonical_dynsym,
+                                          (struct external_nzlist *)info->dynsym,
+                                          info->dynsym_count,
+                                          info->dynstr,
+                                          info->dyninfo.sdt_str_sz,
+                                          true))
+       {
+         if (info->canonical_dynsym != NULL)
+           {
+             bfd_release (abfd, info->canonical_dynsym);
+             info->canonical_dynsym = NULL;
+           }
+         return -1;
+       }
+    }
+
+  /* Return pointers to the dynamic asymbol structures.  */
+  for (i = 0; i < info->dynsym_count; i++)
+    *storage++ = (asymbol *) (info->canonical_dynsym + i);
+  *storage = NULL;
+
+  return info->dynsym_count;
+}
+
+/* Read the external dynamic symbols.  */
+
+static boolean
+netbsd_slurp_dynamic_symtab (abfd)
+     bfd *abfd;
+{
+  struct netbsd_dynamic_info *info;
+
+  /* Get the general dynamic information.  */
+  if (obj_aout_dynamic_info (abfd) == NULL)
+    {
+      if (! netbsd_read_dynamic_info (abfd))
+         return false;
+    }
+
+  info = (struct netbsd_dynamic_info *) obj_aout_dynamic_info (abfd);
+  if (! info->valid)
+    {
+      bfd_set_error (bfd_error_no_symbols);
+      return false;
+    }
+
+  /* Get the dynamic nlist structures.  */
+  if (info->dynsym == (struct external_nlist *) NULL)
+    {
+      info->dynsym = ((struct external_nlist *)



Home | Main Index | Thread Index | Old Index