2003-09-03 Dave Brolley <brolley@redhat.com>
[deliverable/binutils-gdb.git] / gdb / solib-svr4.c
index 1b0a43e97d426c5b1edb15ad7e1fd4d61a3a6108..7fda5e4e0202b1a6289441251ec1f4131ebf7cee 100644 (file)
@@ -43,6 +43,7 @@
 
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static struct link_map_offsets *legacy_fetch_link_map_offsets (void);
+static int svr4_have_link_map_offsets (void);
 
 /* fetch_link_map_offsets_gdbarch_data is a handle used to obtain the
    architecture specific link map offsets fetching function.  */
@@ -80,6 +81,17 @@ static char *solib_break_names[] =
   "_dl_debug_state",
   "rtld_db_dlactivity",
   "_rtld_debug_state",
+
+  /* On the 64-bit PowerPC, the linker symbol with the same name as
+     the C function points to a function descriptor, not to the entry
+     point.  The linker symbol whose name is the C function name
+     prefixed with a '.' points to the function's entry point.  So
+     when we look through this table, we ignore symbols that point
+     into the data section (thus skipping the descriptor's symbol),
+     and eventually try this one, giving us the real entry point
+     address.  */
+  "._dl_debug_state",
+
   NULL
 };
 
@@ -104,14 +116,16 @@ static char *main_name_list[] =
   NULL
 };
 
-/* Macro to extract an address from a solib structure.
-   When GDB is configured for some 32-bit targets (e.g. Solaris 2.7
-   sparc), BFD is configured to handle 64-bit targets, so CORE_ADDR is
-   64 bits.  We have to extract only the significant bits of addresses
-   to get the right address when accessing the core file BFD.  */
+/* Macro to extract an address from a solib structure.  When GDB is
+   configured for some 32-bit targets (e.g. Solaris 2.7 sparc), BFD is
+   configured to handle 64-bit targets, so CORE_ADDR is 64 bits.  We
+   have to extract only the significant bits of addresses to get the
+   right address when accessing the core file BFD.
+
+   Assume that the address is unsigned.  */
 
 #define SOLIB_EXTRACT_ADDRESS(MEMBER) \
-       extract_address (&(MEMBER), sizeof (MEMBER))
+       extract_unsigned_integer (&(MEMBER), sizeof (MEMBER))
 
 /* local data declarations */
 
@@ -131,7 +145,9 @@ LM_NEXT (struct so_list *so)
 {
   struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
 
-  return extract_address (so->lm_info->lm + lmo->l_next_offset, lmo->l_next_size);
+  /* Assume that the address is unsigned.  */
+  return extract_unsigned_integer (so->lm_info->lm + lmo->l_next_offset,
+                                  lmo->l_next_size);
 }
 
 static CORE_ADDR
@@ -139,7 +155,9 @@ LM_NAME (struct so_list *so)
 {
   struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
 
-  return extract_address (so->lm_info->lm + lmo->l_name_offset, lmo->l_name_size);
+  /* Assume that the address is unsigned.  */
+  return extract_unsigned_integer (so->lm_info->lm + lmo->l_name_offset,
+                                  lmo->l_name_size);
 }
 
 static int
@@ -147,8 +165,9 @@ IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so)
 {
   struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
 
-  return extract_address (so->lm_info->lm + lmo->l_prev_offset,
-                          lmo->l_prev_size) == 0;
+  /* Assume that the address is unsigned.  */
+  return extract_unsigned_integer (so->lm_info->lm + lmo->l_prev_offset,
+                                  lmo->l_prev_size) == 0;
 }
 
 static CORE_ADDR debug_base;   /* Base of dynamic linker structures */
@@ -158,7 +177,7 @@ static CORE_ADDR breakpoint_addr;   /* Address where end bkpt is set */
 
 static int match_main (char *);
 
-static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
+static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
 
 /*
 
@@ -168,7 +187,7 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
 
    SYNOPSIS
 
-   CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
+   CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
 
    DESCRIPTION
 
@@ -177,12 +196,15 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
    shared library support to find the address of the debugger
    interface structures in the shared library.
 
+   If SECT_FLAGS is non-zero, only match symbols in sections whose
+   flags include all those in SECT_FLAGS.
+
    Note that 0 is specifically allowed as an error return (no
    such symbol).
  */
 
 static CORE_ADDR
-bfd_lookup_symbol (bfd *abfd, char *symname)
+bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
 {
   long storage_needed;
   asymbol *sym;
@@ -203,7 +225,8 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
       for (i = 0; i < number_of_symbols; i++)
        {
          sym = *symbol_table++;
-         if (STREQ (sym->name, symname))
+         if (STREQ (sym->name, symname)
+              && (sym->section->flags & sect_flags) == sect_flags)
            {
              /* Bfd symbols are section relative. */
              symaddr = sym->value + sym->section->vma;
@@ -230,7 +253,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname)
       for (i = 0; i < number_of_symbols; i++)
        {
          sym = *symbol_table++;
-         if (STREQ (sym->name, symname))
+
+         if (STREQ (sym->name, symname)
+              && (sym->section->flags & sect_flags) == sect_flags)
            {
              /* Bfd symbols are section relative. */
              symaddr = sym->value + sym->section->vma;
@@ -336,7 +361,7 @@ look_for_base (int fd, CORE_ADDR baseaddr)
 
   for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
     {
-      address = bfd_lookup_symbol (interp_bfd, *symbolp);
+      address = bfd_lookup_symbol (interp_bfd, *symbolp, 0);
       if (address != 0)
        {
          break;
@@ -542,9 +567,10 @@ locate_base (void)
   /* Check to see if we have a currently valid address, and if so, avoid
      doing all this work again and just return the cached address.  If
      we have no cached address, try to locate it in the dynamic info
-     section for ELF executables.  */
+     section for ELF executables.  There's no point in doing any of this
+     though if we don't have some link map offsets to work with.  */
 
-  if (debug_base == 0)
+  if (debug_base == 0 && svr4_have_link_map_offsets ())
     {
       if (exec_bfd != NULL
          && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
@@ -585,7 +611,8 @@ first_link_map_member (void)
 
   read_memory (debug_base + lmo->r_map_offset, r_map_buf, lmo->r_map_size);
 
-  lm = extract_address (r_map_buf, lmo->r_map_size);
+  /* Assume that the address is unsigned.  */
+  lm = extract_unsigned_integer (r_map_buf, lmo->r_map_size);
 
   /* FIXME:  Perhaps we should validate the info somehow, perhaps by
      checking r_version for a known version number, or r_state for
@@ -643,8 +670,9 @@ open_symbol_file_object (void *from_ttyp)
   /* Read address of name from target memory to GDB.  */
   read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
 
-  /* Convert the address to host format.  */
-  l_name = extract_address (l_name_buf, lmo->l_name_size);
+  /* Convert the address to host format.  Assume that the address is
+     unsigned.  */
+  l_name = extract_unsigned_integer (l_name_buf, lmo->l_name_size);
 
   /* Free l_name_buf.  */
   do_cleanups (cleanups);
@@ -818,9 +846,9 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
       /* Read address of name from target memory to GDB.  */
       read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
 
-      /* Extract this object's name.  */
-      name_address = extract_address (l_name_buf,
-                                     lmo->l_name_size);
+      /* Extract this object's name.  Assume that the address is
+         unsigned.  */
+      name_address = extract_unsigned_integer (l_name_buf, lmo->l_name_size);
       target_read_string (name_address, &buffer,
                          SO_NAME_MAX_PATH_SIZE - 1, &errcode);
       make_cleanup (xfree, buffer);
@@ -841,9 +869,10 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
              return lm;
            }
        }
-      /* Not the file we wanted, continue checking.  */
-      lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
-                           lmo->l_next_size);
+      /* Not the file we wanted, continue checking.  Assume that the
+         address is unsigned.  */
+      lm = extract_unsigned_integer (objfile_lm_info.lm + lmo->l_next_offset,
+                                    lmo->l_next_size);
       do_cleanups (old_chain);
     }
   return 0;
@@ -1037,7 +1066,16 @@ enable_break (void)
       /* Now try to set a breakpoint in the dynamic linker.  */
       for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
        {
-         sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
+          /* On ABI's that use function descriptors, there are usually
+             two linker symbols associated with each C function: one
+             pointing at the actual entry point of the machine code,
+             and one pointing at the function's descriptor.  The
+             latter symbol has the same name as the C function.
+
+             What we're looking for here is the machine code entry
+             point, so we are only interested in symbols in code
+             sections.  */
+         sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep, SEC_CODE);
          if (sym_addr != 0)
            break;
        }
@@ -1273,6 +1311,13 @@ svr4_solib_create_inferior_hook (void)
   /* Relocate the main executable if necessary.  */
   svr4_relocate_main_executable ();
 
+  if (!svr4_have_link_map_offsets ())
+    {
+      warning ("no shared library support for this OS / ABI");
+      return;
+
+    }
+
   if (!enable_break ())
     {
       warning ("shared library handler failed to enable breakpoint");
@@ -1392,6 +1437,20 @@ svr4_fetch_link_map_offsets (void)
     return (flmo ());
 }
 
+/* Return 1 if a link map offset fetcher has been defined, 0 otherwise.  */
+static int
+svr4_have_link_map_offsets (void)
+{
+  struct link_map_offsets *(*flmo)(void) =
+    gdbarch_data (current_gdbarch, fetch_link_map_offsets_gdbarch_data);
+  if (flmo == NULL
+      || (flmo == legacy_fetch_link_map_offsets 
+          && legacy_svr4_fetch_link_map_offsets_hook == NULL))
+    return 0;
+  else
+    return 1;
+}
+
 /* set_solib_svr4_fetch_link_map_offsets() is intended to be called by
    a <arch>_gdbarch_init() function.  It is used to establish an
    architecture specific link_map_offsets fetcher for the architecture
@@ -1422,11 +1481,13 @@ init_fetch_link_map_offsets (struct gdbarch *gdbarch)
 
 static struct target_so_ops svr4_so_ops;
 
+extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
+
 void
 _initialize_svr4_solib (void)
 {
   fetch_link_map_offsets_gdbarch_data =
-    register_gdbarch_data (init_fetch_link_map_offsets, 0);
+    register_gdbarch_data (init_fetch_link_map_offsets);
 
   svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses;
   svr4_so_ops.free_so = svr4_free_so;
This page took 0.026154 seconds and 4 git commands to generate.