This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] solib for darwin


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;
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]