Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] solib for darwin
@ 2008-12-03 12:55 Tristan Gingold
  2008-12-04 15:39 ` Ulrich Weigand
  0 siblings, 1 reply; 9+ messages in thread
From: Tristan Gingold @ 2008-12-03 12:55 UTC (permalink / raw)
  To: gdb-patches

Hi,

I just have added support for Darwin shared libraries and it fixes  
about 80 failures.
However I was unable to add this support without slightly changing  
common files.

This root issue is Darwin fat (or universal) binaries.  Fat binaries  
are binaries for more than one
architecture.  From a BFD point of view, it's a kind of archive with  
one member for each architecture.
(On Darwin the same fat executable can run on ppc or x86 provided it  
has the right component).
As system libraries are fat binaries, we can't avoid this issue.

solib.c:solib_bfd_open explicitly checked that the format is a  
bfd_object.  As this might not be true
on Darwin, I added a new solib target which does the check.  On  
Darwin, it may also extract the right
binary from the fat binary.

As it is not easy to retrieve the right member from a filename,  
solib.c:symbol_add_stub calls
symbol_file_add_from_bfd instead of symbol_file_add.  I think this is  
still a good idea not to have
2 bfd for the same file.  But this also implies that the bfd must be  
closed only once.  So I added a new
flag, OBJF_KEEPBFD that prevent objfile.c from bfd_close-ing the bfd  
of an objfile.

I still have to write ChangeLog entries and to clean-up a little bit  
solib-darwin.c.  But I'd like to heard
about my approach.

See below solib-darwin.[ch] and the patch against existing files.

Comments are *very* welcome.

Tristan.

Index: i386-darwin-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-darwin-tdep.c,v
retrieving revision 1.1
diff -c -p -r1.1 i386-darwin-tdep.c
*** i386-darwin-tdep.c	27 Nov 2008 09:23:01 -0000	1.1
--- i386-darwin-tdep.c	3 Dec 2008 12:47:43 -0000
***************
*** 29,34 ****
--- 29,36 ----
   #include "regcache.h"
   #include "libbfd.h"
   #include "objfiles.h"
+ #include "solib.h"
+ #include "solib-darwin.h"

   #include "i387-tdep.h"
   #include "i386-tdep.h"
*************** i386_darwin_init_abi (struct gdbarch_inf
*** 114,119 ****
--- 116,123 ----
     tdep->sc_num_regs = 16;

     tdep->jb_pc_offset = 20;
+
+   set_solib_ops (gdbarch, &darwin_so_ops);
   }

   static void
*************** x86_darwin_init_abi_64 (struct gdbarch_i
*** 131,136 ****
--- 135,142 ----
     tdep->sc_num_regs = ARRAY_SIZE  
(amd64_darwin_thread_state_reg_offset);

     tdep->jb_pc_offset = 148;
+
+   set_solib_ops (gdbarch, &darwin_so_ops);
   }

   static enum gdb_osabi
Index: machoread.c
===================================================================
RCS file: /cvs/src/src/gdb/machoread.c,v
retrieving revision 1.1
diff -c -p -r1.1 machoread.c
*** machoread.c	27 Nov 2008 09:23:01 -0000	1.1
--- machoread.c	3 Dec 2008 12:47:43 -0000
*************** macho_symfile_read (struct objfile *objf
*** 538,544 ****
     /* Get symbols from the symbol table only if the file is an  
executable.
        The symbol table of object files is not relocated and is  
expected to
        be in the executable.  */
!   if (bfd_get_file_flags (abfd) & EXEC_P)
       {
         /* Process the normal symbol table first.  */
         storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
--- 538,544 ----
     /* Get symbols from the symbol table only if the file is an  
executable.
        The symbol table of object files is not relocated and is  
expected to
        be in the executable.  */
!   if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
       {
         /* Process the normal symbol table first.  */
         storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
Index: objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.79
diff -c -p -r1.79 objfiles.c
*** objfiles.c	5 Sep 2008 11:37:17 -0000	1.79
--- objfiles.c	3 Dec 2008 12:47:43 -0000
*************** free_objfile (struct objfile *objfile)
*** 424,430 ****

     /* We always close the bfd. */

!   if (objfile->obfd != NULL)
       {
         char *name = bfd_get_filename (objfile->obfd);
         if (!bfd_close (objfile->obfd))
--- 424,430 ----

     /* We always close the bfd. */

!   if (objfile->obfd != NULL && !(objfile->flags & OBJF_KEEPBFD))
       {
         char *name = bfd_get_filename (objfile->obfd);
         if (!bfd_close (objfile->obfd))
Index: objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.57
diff -c -p -r1.57 objfiles.h
*** objfiles.h	18 Nov 2008 21:31:26 -0000	1.57
--- objfiles.h	3 Dec 2008 12:47:43 -0000
*************** struct objfile
*** 414,419 ****
--- 414,424 ----

   #define OBJF_USERLOADED	(1 << 3)	/* User loaded */

+ /* The bfd of this objfile is used outside of the objfile (eg by  
solib).
+    Do not try to free it.  */
+
+ #define OBJF_KEEPBFD (1 << 4)		/* Do not delete bfd.  */
+
   /* The object file that the main symbol table was loaded from (e.g.  
the
      argument to the "symbol-file" or "file" command).  */

Index: solib-frv.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-frv.c,v
retrieving revision 1.23
diff -c -p -r1.23 solib-frv.c
*** solib-frv.c	19 Nov 2008 21:17:07 -0000	1.23
--- solib-frv.c	3 Dec 2008 12:47:43 -0000
*************** _initialize_frv_solib (void)
*** 1280,1285 ****
--- 1280,1286 ----
     frv_so_ops.current_sos = frv_current_sos;
     frv_so_ops.open_symbol_file_object = open_symbol_file_object;
     frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;
+   frv_so_ops.check_bfd_format = solib_default_check_bfd_format;

     /* Debug this file's internals.  */
     add_setshow_zinteger_cmd ("solib-frv", class_maintenance,
Index: solib-irix.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-irix.c,v
retrieving revision 1.21
diff -c -p -r1.21 solib-irix.c
*** solib-irix.c	22 Sep 2008 15:20:08 -0000	1.21
--- solib-irix.c	3 Dec 2008 12:47:43 -0000
*************** _initialize_irix_solib (void)
*** 730,733 ****
--- 730,734 ----
     irix_so_ops.current_sos = irix_current_sos;
     irix_so_ops.open_symbol_file_object = irix_open_symbol_file_object;
     irix_so_ops.in_dynsym_resolve_code = irix_in_dynsym_resolve_code;
+   irix_so_ops.check_bfd_format = solib_default_check_bfd_format;
   }
Index: solib-null.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-null.c,v
retrieving revision 1.5
diff -c -p -r1.5 solib-null.c
*** solib-null.c	1 Jan 2008 22:53:13 -0000	1.5
--- solib-null.c	3 Dec 2008 12:47:43 -0000
*************** _initialize_null_solib (void)
*** 81,86 ****
--- 81,87 ----
     null_so_ops.current_sos = null_current_sos;
     null_so_ops.open_symbol_file_object = null_open_symbol_file_object;
     null_so_ops.in_dynsym_resolve_code = null_in_dynsym_resolve_code;
+   null_so_ops.check_bfd_format = solib_default_check_bfd_format;

     /* Set current_target_so_ops to null_so_ops if not already set.  */
     if (current_target_so_ops == 0)
Index: solib-pa64.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-pa64.c,v
retrieving revision 1.13
diff -c -p -r1.13 solib-pa64.c
*** solib-pa64.c	9 Aug 2008 18:21:59 -0000	1.13
--- solib-pa64.c	3 Dec 2008 12:47:44 -0000
*************** _initialize_pa64_solib (void)
*** 658,663 ****
--- 658,664 ----
     pa64_so_ops.current_sos = pa64_current_sos;
     pa64_so_ops.open_symbol_file_object = pa64_open_symbol_file_object;
     pa64_so_ops.in_dynsym_resolve_code = pa64_in_dynsym_resolve_code;
+   pa64_so_ops.check_bfd_format = solib_default_check_bfd_format;

     memset (&dld_cache, 0, sizeof (dld_cache));
   }
Index: solib-som.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-som.c,v
retrieving revision 1.17
diff -c -p -r1.17 solib-som.c
*** solib-som.c	1 Oct 2008 16:56:52 -0000	1.17
--- solib-som.c	3 Dec 2008 12:47:44 -0000
*************** _initialize_som_solib (void)
*** 804,809 ****
--- 804,810 ----
     som_so_ops.current_sos = som_current_sos;
     som_so_ops.open_symbol_file_object = som_open_symbol_file_object;
     som_so_ops.in_dynsym_resolve_code = som_in_dynsym_resolve_code;
+   som_so_ops.check_bfd_format = solib_default_check_bfd_format;
   }

   void som_solib_select (struct gdbarch *gdbarch)
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.94
diff -c -p -r1.94 solib-svr4.c
*** solib-svr4.c	22 Sep 2008 15:20:08 -0000	1.94
--- solib-svr4.c	3 Dec 2008 12:47:44 -0000
*************** _initialize_svr4_solib (void)
*** 1826,1829 ****
--- 1826,1830 ----
     svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
     svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
     svr4_so_ops.same = svr4_same;
+   svr4_so_ops.check_bfd_format = solib_default_check_bfd_format;
   }
Index: solib-target.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-target.c,v
retrieving revision 1.9
diff -c -p -r1.9 solib-target.c
*** solib-target.c	14 Mar 2008 22:30:07 -0000	1.9
--- solib-target.c	3 Dec 2008 12:47:44 -0000
*************** _initialize_solib_target (void)
*** 492,495 ****
--- 492,496 ----
       = solib_target_open_symbol_file_object;
     solib_target_so_ops.in_dynsym_resolve_code
       = solib_target_in_dynsym_resolve_code;
+   solib_target_so_ops.check_bfd_format =  
solib_default_check_bfd_format;
   }
Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.107
diff -c -p -r1.107 solib.c
*** solib.c	3 Nov 2008 14:01:27 -0000	1.107
--- solib.c	3 Dec 2008 12:47:44 -0000
*************** solib_bfd_open (char *in_pathname)
*** 182,190 ****
   		 temp_pathname, bfd_errmsg (bfd_get_error ()));
   	}

!       if (!bfd_check_format (abfd, bfd_object))
   	{
- 	  bfd_close (abfd);
   	  make_cleanup (xfree, temp_pathname);
   	  error (_("`%s': not in executable format: %s"),
   		 temp_pathname, bfd_errmsg (bfd_get_error ()));
--- 182,190 ----
   		 temp_pathname, bfd_errmsg (bfd_get_error ()));
   	}

!       abfd = ops->check_bfd_format (abfd);
!       if (abfd)
   	{
   	  make_cleanup (xfree, temp_pathname);
   	  error (_("`%s': not in executable format: %s"),
   		 temp_pathname, bfd_errmsg (bfd_get_error ()));
*************** solib_bfd_open (char *in_pathname)
*** 267,275 ****
   	     temp_pathname, bfd_errmsg (bfd_get_error ()));
       }

!   if (!bfd_check_format (abfd, bfd_object))
       {
-       bfd_close (abfd);
         make_cleanup (xfree, temp_pathname);
         error (_("`%s': not in executable format: %s"),
   	     temp_pathname, bfd_errmsg (bfd_get_error ()));
--- 267,275 ----
   	     temp_pathname, bfd_errmsg (bfd_get_error ()));
       }

!   abfd = ops->check_bfd_format (abfd);
!   if (!abfd)
       {
         make_cleanup (xfree, temp_pathname);
         error (_("`%s': not in executable format: %s"),
   	     temp_pathname, bfd_errmsg (bfd_get_error ()));
*************** symbol_add_stub (void *arg)
*** 432,439 ****
     sap = build_section_addr_info_from_section_table (so->sections,
                                                       so- 
 >sections_end);

!   so->objfile = symbol_file_add (so->so_name, so->from_tty,
! 				 sap, 0, OBJF_SHARED);
     free_section_addr_info (sap);

     return (1);
--- 432,439 ----
     sap = build_section_addr_info_from_section_table (so->sections,
                                                       so- 
 >sections_end);

!   so->objfile = symbol_file_add_from_bfd (so->abfd, so->from_tty,
! 					  sap, 0, OBJF_SHARED | OBJF_KEEPBFD);
     free_section_addr_info (sap);

     return (1);
*************** solib_global_lookup (const struct objfil
*** 1000,1005 ****
--- 1000,1015 ----
     return NULL;
   }

+ bfd *
+ solib_default_check_bfd_format (bfd *abfd)
+ {
+   if (!bfd_check_format (abfd, bfd_object))
+     {
+       bfd_close (abfd);
+       return NULL;
+     }
+   return abfd;
+ }

   extern initialize_file_ftype _initialize_solib; /* -Wmissing- 
prototypes */

Index: solist.h
===================================================================
RCS file: /cvs/src/src/gdb/solist.h,v
retrieving revision 1.21
diff -c -p -r1.21 solist.h
*** solist.h	26 Aug 2008 17:30:35 -0000	1.21
--- solist.h	3 Dec 2008 12:47:44 -0000
*************** struct target_so_ops
*** 118,123 ****
--- 118,130 ----
          and another from the list returned by current_sos, return 1
          if they represent the same library.  */
       int (*same) (struct so_list *gdb, struct so_list *inferior);
+
+     /* Return a bfd for the shared library if ABFD is valid.
+        If ABFD is not valid, it is freed and NULL is returned.
+        On most system, this is just a format check.
+        On some systems (eg Darwin), this can extract a shared  
library from
+        a fat image.  */
+     bfd * (*check_bfd_format)(bfd *abfd);
     };

   /* Free the memory associated with a (so_list *).  */
*************** struct so_list *master_so_list (void);
*** 129,134 ****
--- 136,144 ----
   /* Find solib binary file and open it.  */
   extern bfd *solib_bfd_open (char *in_pathname);

+ /* Default implementation of check_bfd_format op.  */
+ extern bfd *solib_default_check_bfd_format (bfd *abfd);
+
   /* FIXME: gdbarch needs to control this variable */
   extern struct target_so_ops *current_target_so_ops;


solib-darwin.h:

/* Handle shared libraries for GDB, the GNU Debugger.

    Copyright (C) 2008 Free Software Foundation, Inc.

    This file is part of GDB.

    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 3 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, see <http://www.gnu.org/licenses/ 
 >.  */

#ifndef SOLIB_DARWIN_H
#define SOLIB_DARWIN_H

struct objfile;
struct target_so_ops;

extern struct target_so_ops darwin_so_ops;

#endif /* solib-darwin.h */


solib-darwin.c:

/* Handle Darwin shared libraries for GDB, the GNU Debugger.

    Copyright (C) 2008 Free Software Foundation, Inc.

    This file is part of GDB.

    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 3 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, see <http://www.gnu.org/licenses/ 
 >.  */

#include "defs.h"

#include "symtab.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbcore.h"
#include "target.h"
#include "inferior.h"
#include "gdbthread.h"

#include "gdb_assert.h"

#include "solist.h"
#include "solib.h"
#include "solib-svr4.h"

#include "bfd-target.h"
#include "elf-bfd.h"
#include "exec.h"
#include "auxv.h"
#include "exceptions.h"
#include "mach-o.h"

struct gdb_dyld_image_info
{
   /* Base address (which corresponds to the Mach-O header).  */
   CORE_ADDR mach_header;
   /* Image file path.  */
   CORE_ADDR file_path;
   /* st.m_time of image file.  */
   unsigned long mtime;
};

/* Content of inferior dyld_all_image_infos structure.  */
struct gdb_dyld_all_image_infos
{
   /* Version (1).  */
   unsigned long version;
   /* Number of images.  */
   unsigned long count;
   /* Image description.  */
   CORE_ADDR info;
   /* Notifier (function called when a library is added or removed).  */
   CORE_ADDR notifier;
};

/* Current all_image_infos version.  */
#define DYLD_VERSION 1

/* Address of structure dyld_all_image_infos in inferior.  */
static CORE_ADDR dyld_all_image_addr;

/* Gdb copy of dyld_all_info_infos.  */
static struct gdb_dyld_all_image_infos dyld_all_image;

/* Read dyld_all_image from inferior.  */
static void
darwin_load_image_infos (void)
{
   gdb_byte buf[24];
   struct type *ptr_type = builtin_type (target_gdbarch)- 
 >builtin_data_ptr;
   int len;

   len = 4 + 4 + 2 * ptr_type->length;
   memset (&dyld_all_image, 0, sizeof (dyld_all_image));

   if (dyld_all_image_addr == 0)
     return;

   if (target_read_memory (dyld_all_image_addr, buf, len))
     return;

   dyld_all_image.version = extract_unsigned_integer (buf, 4);
   if (dyld_all_image.version != DYLD_VERSION)
     return;

   dyld_all_image.count = extract_unsigned_integer (buf + 4, 4);
   dyld_all_image.info = extract_typed_address (buf + 8, ptr_type);
   dyld_all_image.notifier = extract_typed_address
     (buf + 8 + ptr_type->length, ptr_type);
}

/* Link map info to include in an allocated so_list entry */

struct lm_info
{
   /* The target location of lm.  */
   CORE_ADDR lm_addr;
};

struct darwin_so_list
{
   struct so_list sl;
   struct lm_info li;
};

/* Local function prototypes */

static int match_main (char *);

static CORE_ADDR bfd_lookup_symbol (bfd *, char *);

/* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent
    the same shared library.  */

static int
darwin_same (struct so_list *gdb, struct so_list *inferior)
{
   return strcmp (gdb->so_original_name, inferior->so_original_name)  
== 0;
}

/*

    LOCAL FUNCTION

    bfd_lookup_symbol -- lookup the value for a specific symbol

    SYNOPSIS

    CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)

    DESCRIPTION

    An expensive way to lookup the value of a single symbol for
    bfd's that are only temporary anyway.  This is used by the
    shared library support to find the address of the debugger
    notification routine in the shared library.

    The returned symbol may be in a code or data section; functions
    will normally be in a code section, but may be in a data section
    if this architecture uses function descriptors.

    Note that 0 is specifically allowed as an error return (no
    such symbol).
  */

static CORE_ADDR
bfd_lookup_symbol (bfd *abfd, char *symname)
{
   long storage_needed;
   asymbol **symbol_table;
   unsigned int number_of_symbols;
   unsigned int i;
   CORE_ADDR symaddr = 0;

   storage_needed = bfd_get_symtab_upper_bound (abfd);

   if (storage_needed > 0)
     {
       symbol_table = (asymbol **) xmalloc (storage_needed);
       number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);

       for (i = 0; i < number_of_symbols; i++)
	{
	  asymbol *sym = symbol_table[i];
	  if (strcmp (sym->name, symname) == 0
               && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
	    {
	      /* BFD symbols are section relative.  */
	      symaddr = sym->value + sym->section->vma;
	      break;
	    }
	}
       xfree (symbol_table);
     }

   return symaddr;
}


/* Return program interpreter string.  */
static gdb_byte *
find_program_interpreter (void)
{
   gdb_byte *buf = NULL;

   /* If we have an exec_bfd, use its section table.  */
   if (exec_bfd)
     {
       struct bfd_section *dylinker_sect;

       dylinker_sect = bfd_get_section_by_name (exec_bfd,  
"LC_LOAD_DYLINKER");
       if (dylinker_sect != NULL)
	{
	  int sect_size = bfd_section_size (exec_bfd, dylinker_sect);

	  buf = xmalloc (sect_size);
	  if (bfd_get_section_contents (exec_bfd, dylinker_sect,
					buf, 0, sect_size))
	    return buf;
	  xfree (buf);
	}
     }

   /* If we didn't find it, read from memory.
      FIXME: todo.  */
   return buf;
}

/*

   LOCAL FUNCTION

   open_symbol_file_object

   SYNOPSIS

   void open_symbol_file_object (void *from_tty)

   DESCRIPTION

   If no open symbol file, attempt to locate and open the main symbol
   file.  On SVR4 systems, this is the first link map entry.  If its
   name is here, we can open it.  Useful when attaching to a process
   without first loading its symbol file.

   If FROM_TTYP dereferences to a non-zero integer, allow messages to
   be printed.  This parameter is a pointer rather than an int because
   open_symbol_file_object() is called via catch_errors() and
   catch_errors() requires a pointer argument. */

static int
open_symbol_file_object (void *from_ttyp)
{
   return 0;
}

/* LOCAL FUNCTION

    current_sos -- build a list of currently loaded shared objects

    SYNOPSIS

    struct so_list *current_sos ()

    DESCRIPTION

    Build a list of `struct so_list' objects describing the shared
    objects currently loaded in the inferior.  This list does not
    include an entry for the main executable file.

    Note that we only gather information directly available from the
    inferior --- we don't examine any of the shared library files
    themselves.  The declaration of `struct so_list' says which fields
    we provide values for.  */

static struct so_list *
darwin_current_sos (void)
{
   struct type *ptr_type = builtin_type (target_gdbarch)- 
 >builtin_data_ptr;
   int ptr_len = TYPE_LENGTH (ptr_type);
   unsigned int image_info_size;
   CORE_ADDR lm;
   struct so_list *head = NULL;
   struct so_list *tail = NULL;
   int i;

   darwin_load_image_infos ();

   if (dyld_all_image.version != DYLD_VERSION)
     return NULL;

   image_info_size = ptr_len * 3;

   for (i = 0; i < dyld_all_image.count; i++)
     {
       CORE_ADDR info = dyld_all_image.info + i * image_info_size;
       char buf[image_info_size];
       CORE_ADDR load_addr;
       CORE_ADDR path_addr;
       char *file_path;
       int errcode;
       struct darwin_so_list *dnew = XZALLOC (struct darwin_so_list);
       struct so_list *new = &dnew->sl;
       struct cleanup *old_chain = make_cleanup (xfree, dnew);

       new->lm_info = &dnew->li;

       if (target_read_memory (info, buf, image_info_size))
	break;

       load_addr = extract_typed_address (buf, ptr_type);
       path_addr = extract_typed_address (buf + ptr_len, ptr_type);

       target_read_string (path_addr, &file_path,
			  SO_NAME_MAX_PATH_SIZE - 1, &errcode);
       if (errcode)
	break;

       /* Ignore first entry as this is the executable itself.  */
       if (i == 0)
	continue;

       dnew = XZALLOC (struct darwin_so_list);
       new = &dnew->sl;
       old_chain = make_cleanup (xfree, dnew);

       new->lm_info = &dnew->li;

       strncpy (new->so_name, file_path, SO_NAME_MAX_PATH_SIZE - 1);
       new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
       strcpy (new->so_original_name, new->so_name);
       xfree (file_path);
       new->lm_info->lm_addr = load_addr;

       if (head == NULL)
	head = new;
       else
	tail->next = new;
       tail = new;

       discard_cleanups (old_chain);
     }

   return head;
}

/* Return 1 if PC lies in the dynamic symbol resolution code of the
    SVR4 run time loader.  */
static CORE_ADDR interp_text_sect_low;
static CORE_ADDR interp_text_sect_high;

int
darwin_in_dynsym_resolve_code (CORE_ADDR pc)
{
   return (pc >= interp_text_sect_low && pc < interp_text_sect_high);
}


/*
    LOCAL FUNCTION

    special_symbol_handling -- additional shared library symbol handling

    SYNOPSIS

    void special_symbol_handling ()

    DESCRIPTION

    Once the symbols from a shared object have been loaded in the usual
    way, we are called to do any system specific symbol handling that
    is needed.

    For SunOS4, this consisted of grunging around in the dynamic
    linkers structures to find symbol definitions for "common" symbols
    and adding them to the minimal symbol table for the runtime common
    objfile.

    However, for SVR4, there's nothing to do.

  */

static void
darwin_special_symbol_handling (void)
{
}

/*

    GLOBAL FUNCTION

    darwin_solib_create_inferior_hook -- shared library startup support

    SYNOPSIS

    void darwin_solib_create_inferior_hook ()

    DESCRIPTION

    When gdb starts up the inferior, it nurses it along (through the
    shell) until it is ready to execute it's first instruction.  At this
    point, this function gets called via expansion of the macro
    SOLIB_CREATE_INFERIOR_HOOK.

    For SunOS executables, this first instruction is typically the
    one at "_start", or a similar text label, regardless of whether
    the executable is statically or dynamically linked.  The runtime
    startup code takes care of dynamically linking in any shared
    libraries, once gdb allows the inferior to continue.

    For SVR4 executables, this first instruction is either the first
    instruction in the dynamic linker (for dynamically linked
    executables) or the instruction at "start" for statically linked
    executables.  For dynamically linked executables, the system
    first exec's /lib/libc.so.N, which contains the dynamic linker,
    and starts it running.  The dynamic linker maps in any needed
    shared libraries, maps in the actual user executable, and then
    jumps to "start" in the user executable.

    For both SunOS shared libraries, and SVR4 shared libraries, we
    can arrange to cooperate with the dynamic linker to discover the
    names of shared libraries that are dynamically linked, and the
    base addresses to which they are linked.

    This function is responsible for discovering those names and
    addresses, and saving sufficient information about them to allow
    their symbols to be read at a later time.

    FIXME

    Between enable_break() and disable_break(), this code does not
    properly handle hitting breakpoints which the user might have
    set in the startup code or in the dynamic linker itself.  Proper
    handling will probably have to wait until the implementation is
    changed to use the "breakpoint handler function" method.

    Also, what if child has exit()ed?  Must exit loop somehow.
  */

static void
darwin_solib_create_inferior_hook (void)
{
   struct minimal_symbol *msymbol;
   char **bkpt_namep;
   asection *interp_sect;
   gdb_byte *interp_name;
   CORE_ADDR sym_addr;
   CORE_ADDR load_addr = 0;
   int load_addr_found = 0;
   int loader_found_in_list = 0;
   struct so_list *so;
   bfd *dyld_bfd = NULL;

   /* First, remove all the solib event breakpoints.  Their addresses
      may have changed since the last time we ran the program.  */
   remove_solib_event_breakpoints ();

   interp_text_sect_low = interp_text_sect_high = 0;

   /* Find the program interpreter; if not found, warn the user and drop
      into the old breakpoint at symbol code.  */
   interp_name = find_program_interpreter ();
   if (!interp_name)
     return;

   sym_addr = 0;

   /* Now we need to figure out where the dynamic linker was
      loaded so that we can load its symbols and place a breakpoint
      in the dynamic linker itself.

      This address is stored on the stack.  However, I've been unable
      to find any magic formula to find it for Solaris (appears to
      be trivial on GNU/Linux).  Therefore, we have to try an alternate
      mechanism to find the dynamic linker's base address.  */

   dyld_bfd = bfd_openr (interp_name, gnutarget);
   if (dyld_bfd)
     {
       bfd *sub;
       sub = bfd_mach_o_fat_extract (dyld_bfd, bfd_object,
				    gdbarch_bfd_arch_info (current_gdbarch));
       if (sub)
	dyld_bfd = sub;
       else
	{
	  bfd_close (dyld_bfd);
	  dyld_bfd = NULL;
	}
     }
   if (!dyld_bfd)
     {
       xfree (interp_name);
       return;
     }

   /* Otherwise we find the dynamic linker's base address by examining
      the current pc (which should point at the entry point for the
      dynamic linker) and subtracting the offset of the entry point.

      This is more fragile than the previous approaches, but is a good
      fallback method because it has actually been working well in
      most cases.  */
   load_addr = (read_pc () - bfd_get_start_address (dyld_bfd));

#if 0
   /* Record the relocated start and end address of the dynamic linker
      text and plt section for svr4_in_dynsym_resolve_code.  */
   interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
   if (interp_sect)
     {
       interp_text_sect_low =
	bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
       interp_text_sect_high =
	interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
     }
#endif

   /* Now try to set a breakpoint in the dynamic linker.  */
   dyld_all_image_addr =
     bfd_lookup_symbol (dyld_bfd, "_dyld_all_image_infos");

   bfd_close (dyld_bfd);
   xfree (interp_name);

   if (dyld_all_image_addr == 0)
     return;

   dyld_all_image_addr += load_addr;

   darwin_load_image_infos ();

   if (dyld_all_image.version == DYLD_VERSION)
     create_solib_event_breakpoint (dyld_all_image.notifier);
}

static void
darwin_clear_solib (void)
{
   dyld_all_image_addr = 0;
   dyld_all_image.version = 0;
}

static void
darwin_free_so (struct so_list *so)
{
}

static void
darwin_relocate_section_addresses (struct so_list *so,
				   struct section_table *sec)
{
   sec->addr += so->lm_info->lm_addr;
   sec->endaddr += so->lm_info->lm_addr;

   /* Best effort to set addr_high/addr_low.  */
   if (so->addr_high == 0)
     {
       so->addr_low = sec->addr;
       so->addr_high = sec->endaddr;
     }
   if (sec->endaddr > so->addr_high)
     so->addr_high = sec->endaddr;
   if (sec->addr < so->addr_low)
     so->addr_low = sec->addr;
}
static struct symbol *
darwin_lookup_lib_symbol (const struct objfile *objfile,
			  const char *name,
			  const char *linkage_name,
			  const domain_enum domain)
{
   return NULL;
}

bfd *
darwin_check_bfd_format (bfd *abfd)
{
   bfd *res;

   res = bfd_mach_o_fat_extract (abfd, bfd_object,
				gdbarch_bfd_arch_info (current_gdbarch));
   if (res)
     return res;
   bfd_close (abfd);
   return NULL;
}

extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing- 
prototypes */

struct target_so_ops darwin_so_ops;

void
_initialize_darwin_solib (void)
{
   darwin_so_ops.relocate_section_addresses =  
darwin_relocate_section_addresses;
   darwin_so_ops.free_so = darwin_free_so;
   darwin_so_ops.clear_solib = darwin_clear_solib;
   darwin_so_ops.solib_create_inferior_hook =  
darwin_solib_create_inferior_hook;
   darwin_so_ops.special_symbol_handling =  
darwin_special_symbol_handling;
   darwin_so_ops.current_sos = darwin_current_sos;
   darwin_so_ops.open_symbol_file_object = open_symbol_file_object;
   darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code;
   darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol;
   darwin_so_ops.same = darwin_same;
   darwin_so_ops.check_bfd_format = darwin_check_bfd_format;
}


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-01-15 16:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-03 12:55 [RFC] solib for darwin Tristan Gingold
2008-12-04 15:39 ` Ulrich Weigand
2008-12-04 16:01   ` Tristan Gingold
2008-12-11 13:12   ` Tristan Gingold
2008-12-14 17:40     ` Ulrich Weigand
2008-12-15 13:22       ` Tristan Gingold
2008-12-17 19:46         ` [rfc] Allow platform-specific override for solib_bfd_open (Re: [RFC] solib for darwin) Ulrich Weigand
2009-01-15 16:37           ` Ulrich Weigand
2009-01-15 16:53             ` Tristan Gingold

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox