This is the mail archive of the gdb-patches@sourceware.cygnus.com 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]

dlclose support: first cut



I've committed the following patch, adding support for shared object
unloading.  It causes no regressions on either Linux or Solaris.  This
also incorporates Peter's fixes for the new 64-bit CORE_ADDR type.

Please check out these changes and try them on your systems.

Weaknesses I'm aware of:

- I haven't written any tests for it; I've just tested it by hand, using
  Chris's test program from Bugzilla (I've lost the bug number).  I'll
  work on that now.

- It's a pretty big change by itself; combined with the CORE_ADDR
  changes, it's kind of hard to read.  I'm sorry about that; I saw
  Peter's patch, and plunged into adapting it before I realized it
  should be handled as a separate issue.  It'd take some time to
  disentangle now.



2000-03-14  Jim Blandy  <jimb@redhat.com>

	Deal with the inferior unloading shared objects.
	* solib.c (current_sos): New function, replacing find_solib.
	(find_solib): Deleted.
	(free_so): New function.
	(clear_solib): Call free_so, instead of writing it out.
	(solib_add): Rewritten: compare the inferior's current list of
	shared objects with GDB's list, and do the required loads and
	unloads.
	(info_sharedlibrary_command, solib_address): Don't use find_solib
	to walk the list of shared libraries: call solib_add, and then
	walk the list at so_list_head normally.
	* objfiles.c (free_objfile): Don't call CLEAR_SOLIB, and don't
	detach the core target.  These tasks are taken care of elsewhere.
	* target.c (remove_target_sections): New function.
	* target.h (remove_target_sections): New declaration.

	* solib.c (symbol_add_stub): Check whether we've already created
	an objfile for this shared object first, before doing all that
	work to compute section addresses, etc.

	* objfiles.c (unlink_objfile): Report an internal error if objfile
	doesn't occur in the object_files list.

	* solib.c (special_symbol_handling): Delete argument; it's not
	used.
	
	Changes from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>:

	* solib.c (SOLIB_EXTRACT_ADDRESS):  New macro to extract addresses
	from solib structures. Use it throughout solib.c, get rid of all
	CORE_ADDR casts.
	(struct so_list):  Change type of lmaddr to CORE_ADDR.
	(first_link_map_member):  Change return value type to CORE_ADDR,
	update callers.
	(solib_add_common_symbols):  Change parameter type to CORE_ADDR,
	update callers.
	(open_symbol_file_object, find_solib):  Change type of lm variable
	to CORE_ADDR.



Index: gdb/objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.2
diff -c -r1.2 objfiles.c
*** gdb/objfiles.c	2000/02/29 12:58:51	1.2
--- gdb/objfiles.c	2000/03/14 23:57:52
***************
*** 370,378 ****
  	{
  	  *objpp = (*objpp)->next;
  	  objfile->next = NULL;
! 	  break;
  	}
      }
  }
  
  
--- 370,380 ----
  	{
  	  *objpp = (*objpp)->next;
  	  objfile->next = NULL;
! 	  return;
  	}
      }
+ 
+   internal_error ("objfiles.c (unlink_objfile): objfile already unlinked");
  }
  
  
***************
*** 436,452 ****
       is unknown, but we play it safe for now and keep each action until
       it is shown to be no longer needed. */
  
- #if defined (CLEAR_SOLIB)
-   CLEAR_SOLIB ();
-   /* CLEAR_SOLIB closes the bfd's for any shared libraries.  But
-      the to_sections for a core file might refer to those bfd's.  So
-      detach any core file.  */
-   {
-     struct target_ops *t = find_core_target ();
-     if (t != NULL)
-       (t->to_detach) (NULL, 0);
-   }
- #endif
    /* I *think* all our callers call clear_symtab_users.  If so, no need
       to call this here.  */
    clear_pc_function_cache ();
--- 438,443 ----
Index: gdb/solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.2
diff -c -r1.2 solib.c
*** gdb/solib.c	2000/03/06 18:04:56	1.2
--- gdb/solib.c	2000/03/14 23:57:53
***************
*** 109,121 ****
  
  /* local data declarations */
  
  #ifndef SVR4_SHARED_LIBS
  
! #define LM_ADDR(so) ((so) -> lm.lm_addr)
! #define LM_NEXT(so) ((so) -> lm.lm_next)
! #define LM_NAME(so) ((so) -> lm.lm_name)
  /* Test for first link map entry; first entry is a shared library. */
! #define IGNORE_FIRST_LINK_MAP_ENTRY(x) (0)
  static struct link_dynamic dynamic_copy;
  static struct link_dynamic_2 ld_2_copy;
  static struct ld_debug debug_copy;
--- 109,130 ----
  
  /* local data declarations */
  
+ /* 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.  */
+ 
+ #define SOLIB_EXTRACT_ADDRESS(member) \
+   extract_address (&member, sizeof (member))
+ 
  #ifndef SVR4_SHARED_LIBS
  
! #define LM_ADDR(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.lm_addr))
! #define LM_NEXT(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.lm_next))
! #define LM_NAME(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.lm_name))
  /* Test for first link map entry; first entry is a shared library. */
! #define IGNORE_FIRST_LINK_MAP_ENTRY(so) (0)
  static struct link_dynamic dynamic_copy;
  static struct link_dynamic_2 ld_2_copy;
  static struct ld_debug debug_copy;
***************
*** 124,134 ****
  
  #else /* SVR4_SHARED_LIBS */
  
! #define LM_ADDR(so) ((so) -> lm.l_addr)
! #define LM_NEXT(so) ((so) -> lm.l_next)
! #define LM_NAME(so) ((so) -> lm.l_name)
  /* Test for first link map entry; first entry is the exec-file. */
! #define IGNORE_FIRST_LINK_MAP_ENTRY(x) ((x).l_prev == NULL)
  static struct r_debug debug_copy;
  char shadow_contents[BREAKPOINT_MAX];	/* Stash old bkpt addr contents */
  
--- 133,144 ----
  
  #else /* SVR4_SHARED_LIBS */
  
! #define LM_ADDR(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.l_addr))
! #define LM_NEXT(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.l_next))
! #define LM_NAME(so) (SOLIB_EXTRACT_ADDRESS ((so) -> lm.l_name))
  /* Test for first link map entry; first entry is the exec-file. */
! #define IGNORE_FIRST_LINK_MAP_ENTRY(so) \
!   (SOLIB_EXTRACT_ADDRESS ((so) -> lm.l_prev) == 0)
  static struct r_debug debug_copy;
  char shadow_contents[BREAKPOINT_MAX];	/* Stash old bkpt addr contents */
  
***************
*** 136,153 ****
  
  struct so_list
    {
      struct so_list *next;	/* next structure in linked list */
      struct link_map lm;		/* copy of link map from inferior */
!     struct link_map *lmaddr;	/* addr in inferior lm was read from */
      CORE_ADDR lmend;		/* upper addr bound of mapped object */
-     char so_name[MAX_PATH_SIZE];	/* shared object lib name (FIXME) */
      char symbols_loaded;	/* flag: symbols read in yet? */
      char from_tty;		/* flag: print msgs? */
      struct objfile *objfile;	/* objfile for loaded lib */
      struct section_table *sections;
      struct section_table *sections_end;
      struct section_table *textsection;
-     bfd *abfd;
    };
  
  static struct so_list *so_list_head;	/* List of known shared objects */
--- 146,181 ----
  
  struct so_list
    {
+     /* The following fields of the structure come directly from the
+        dynamic linker's tables in the inferior, and are initialized by
+        current_sos.  */
+ 
      struct so_list *next;	/* next structure in linked list */
      struct link_map lm;		/* copy of link map from inferior */
!     CORE_ADDR lmaddr;		/* addr in inferior lm was read from */
! 
!     /* Shared object file name, exactly as it appears in the
!        inferior's link map.  This may be a relative path, or something
!        which needs to be looked up in LD_LIBRARY_PATH, etc.  We use it
!        to tell which entries in the inferior's dynamic linker's link
!        map we've already loaded.  */
!     char so_original_name[MAX_PATH_SIZE];
! 
!     /* shared object file name, expanded to something GDB can open */
!     char so_name[MAX_PATH_SIZE];
! 
!     /* The following fields of the structure are built from
!        information gathered from the shared object file itself, and
!        are initialized when we actually add it to our symbol tables.  */
! 
!     bfd *abfd;
      CORE_ADDR lmend;		/* upper addr bound of mapped object */
      char symbols_loaded;	/* flag: symbols read in yet? */
      char from_tty;		/* flag: print msgs? */
      struct objfile *objfile;	/* objfile for loaded lib */
      struct section_table *sections;
      struct section_table *sections_end;
      struct section_table *textsection;
    };
  
  static struct so_list *so_list_head;	/* List of known shared objects */
***************
*** 168,174 ****
  match_main PARAMS ((char *));
  
  static void
! special_symbol_handling PARAMS ((struct so_list *));
  
  static void
  sharedlibrary_command PARAMS ((char *, int));
--- 196,202 ----
  match_main PARAMS ((char *));
  
  static void
! special_symbol_handling PARAMS ((void));
  
  static void
  sharedlibrary_command PARAMS ((char *, int));
***************
*** 180,190 ****
  info_sharedlibrary_command PARAMS ((char *, int));
  
  static int symbol_add_stub PARAMS ((PTR));
- 
- static struct so_list *
-   find_solib PARAMS ((struct so_list *));
  
! static struct link_map *
    first_link_map_member PARAMS ((void));
  
  static CORE_ADDR
--- 208,215 ----
  info_sharedlibrary_command PARAMS ((char *, int));
  
  static int symbol_add_stub PARAMS ((PTR));
  
! static CORE_ADDR
    first_link_map_member PARAMS ((void));
  
  static CORE_ADDR
***************
*** 199,204 ****
--- 224,232 ----
  
  #else
  
+ static struct so_list *current_sos (void);
+ static void free_so (struct so_list *node);
+ 
  static int
  disable_break PARAMS ((void));
  
***************
*** 206,212 ****
  allocate_rt_common_objfile PARAMS ((void));
  
  static void
! solib_add_common_symbols PARAMS ((struct rtc_symb *));
  
  #endif
  
--- 234,240 ----
  allocate_rt_common_objfile PARAMS ((void));
  
  static void
! solib_add_common_symbols (CORE_ADDR);
  
  #endif
  
***************
*** 338,346 ****
        /* Relocate the section binding addresses as recorded in the shared
           object's file by the base address to which the object was actually
           mapped. */
!       p->addr += (CORE_ADDR) LM_ADDR (so);
!       p->endaddr += (CORE_ADDR) LM_ADDR (so);
!       so->lmend = (CORE_ADDR) max (p->endaddr, so->lmend);
        if (STREQ (p->the_bfd_section->name, ".text"))
  	{
  	  so->textsection = p;
--- 366,374 ----
        /* Relocate the section binding addresses as recorded in the shared
           object's file by the base address to which the object was actually
           mapped. */
!       p->addr += LM_ADDR (so);
!       p->endaddr += LM_ADDR (so);
!       so->lmend = max (p->endaddr, so->lmend);
        if (STREQ (p->the_bfd_section->name, ".text"))
  	{
  	  so->textsection = p;
***************
*** 398,404 ****
  
  static void
  solib_add_common_symbols (rtc_symp)
!      struct rtc_symb *rtc_symp;
  {
    struct rtc_symb inferior_rtc_symb;
    struct nlist inferior_rtc_nlist;
--- 426,432 ----
  
  static void
  solib_add_common_symbols (rtc_symp)
!      CORE_ADDR rtc_symp;
  {
    struct rtc_symb inferior_rtc_symb;
    struct nlist inferior_rtc_nlist;
***************
*** 421,430 ****
  
    while (rtc_symp)
      {
!       read_memory ((CORE_ADDR) rtc_symp,
  		   (char *) &inferior_rtc_symb,
  		   sizeof (inferior_rtc_symb));
!       read_memory ((CORE_ADDR) inferior_rtc_symb.rtc_sp,
  		   (char *) &inferior_rtc_nlist,
  		   sizeof (inferior_rtc_nlist));
        if (inferior_rtc_nlist.n_type == N_COMM)
--- 449,458 ----
  
    while (rtc_symp)
      {
!       read_memory (rtc_symp,
  		   (char *) &inferior_rtc_symb,
  		   sizeof (inferior_rtc_symb));
!       read_memory (SOLIB_EXTRACT_ADDRESS (inferior_rtc_symb.rtc_sp),
  		   (char *) &inferior_rtc_nlist,
  		   sizeof (inferior_rtc_nlist));
        if (inferior_rtc_nlist.n_type == N_COMM)
***************
*** 435,441 ****
  	  len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
  
  	  name = xmalloc (len);
! 	  read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);
  
  	  /* Allocate the runtime common objfile if necessary. */
  	  if (rt_common_objfile == NULL)
--- 463,470 ----
  	  len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
  
  	  name = xmalloc (len);
! 	  read_memory (SOLIB_EXTRACT_ADDRESS (inferior_rtc_nlist.n_un.n_name),
! 		       name, len);
  
  	  /* Allocate the runtime common objfile if necessary. */
  	  if (rt_common_objfile == NULL)
***************
*** 445,451 ****
  				      mst_bss, rt_common_objfile);
  	  free (name);
  	}
!       rtc_symp = inferior_rtc_symb.rtc_next;
      }
  
    /* Install any minimal symbols that have been collected as the current
--- 474,480 ----
  				      mst_bss, rt_common_objfile);
  	  free (name);
  	}
!       rtc_symp = SOLIB_EXTRACT_ADDRESS (inferior_rtc_symb.rtc_next);
      }
  
    /* Install any minimal symbols that have been collected as the current
***************
*** 848,866 ****
  
     SYNOPSIS
  
!    static struct link_map *first_link_map_member (void)
  
     DESCRIPTION
  
     Find the first element in the inferior's dynamic link map, and
     return its address in the inferior.  This function doesn't copy the
!    link map entry itself into our address space; find_solib actually
     does the reading.  */
  
! static struct link_map *
  first_link_map_member ()
  {
!   struct link_map *lm = NULL;
  
  #ifndef SVR4_SHARED_LIBS
  
--- 877,895 ----
  
     SYNOPSIS
  
!    static CORE_ADDR first_link_map_member (void)
  
     DESCRIPTION
  
     Find the first element in the inferior's dynamic link map, and
     return its address in the inferior.  This function doesn't copy the
!    link map entry itself into our address space; current_sos actually
     does the reading.  */
  
! static CORE_ADDR
  first_link_map_member ()
  {
!   CORE_ADDR lm = 0;
  
  #ifndef SVR4_SHARED_LIBS
  
***************
*** 869,877 ****
      {
        /* It is a version that we can deal with, so read in the secondary
           structure and find the address of the link map list from it. */
!       read_memory ((CORE_ADDR) dynamic_copy.ld_un.ld_2, (char *) &ld_2_copy,
! 		   sizeof (struct link_dynamic_2));
!       lm = ld_2_copy.ld_loaded;
      }
  
  #else /* SVR4_SHARED_LIBS */
--- 898,906 ----
      {
        /* It is a version that we can deal with, so read in the secondary
           structure and find the address of the link map list from it. */
!       read_memory (SOLIB_EXTRACT_ADDRESS (dynamic_copy.ld_un.ld_2),
! 		   (char *) &ld_2_copy, sizeof (struct link_dynamic_2));
!       lm = SOLIB_EXTRACT_ADDRESS (ld_2_copy.ld_loaded);
      }
  
  #else /* SVR4_SHARED_LIBS */
***************
*** 880,886 ****
    /* FIXME:  Perhaps we should validate the info somehow, perhaps by
       checking r_version for a known version number, or r_state for
       RT_CONSISTENT. */
!   lm = debug_copy.r_map;
  
  #endif /* !SVR4_SHARED_LIBS */
  
--- 909,915 ----
    /* FIXME:  Perhaps we should validate the info somehow, perhaps by
       checking r_version for a known version number, or r_state for
       RT_CONSISTENT. */
!   lm = SOLIB_EXTRACT_ADDRESS (debug_copy.r_map);
  
  #endif /* !SVR4_SHARED_LIBS */
  
***************
*** 912,918 ****
       PTR arg;
  {
    int from_tty = (int) arg;	/* sneak past catch_errors */
!   struct link_map *lm, lmcopy;
    char *filename;
    int errcode;
  
--- 941,948 ----
       PTR arg;
  {
    int from_tty = (int) arg;	/* sneak past catch_errors */
!   CORE_ADDR lm;
!   struct link_map lmcopy;
    char *filename;
    int errcode;
  
***************
*** 924,940 ****
      return 0;	/* failed somehow... */
  
    /* First link map member should be the executable.  */
!   if ((lm = first_link_map_member ()) == NULL)
      return 0;	/* failed somehow... */
  
    /* Read from target memory to GDB.  */
!   read_memory ((CORE_ADDR) lm, (void *) &lmcopy, sizeof (lmcopy));
  
    if (lmcopy.l_name == 0)
      return 0;	/* no filename.  */
  
    /* Now fetch the filename from target memory.  */
!   target_read_string ((CORE_ADDR) lmcopy.l_name, &filename, 
  		      MAX_PATH_SIZE - 1, &errcode);
    if (errcode)
      {
--- 954,970 ----
      return 0;	/* failed somehow... */
  
    /* First link map member should be the executable.  */
!   if ((lm = first_link_map_member ()) == 0)
      return 0;	/* failed somehow... */
  
    /* Read from target memory to GDB.  */
!   read_memory (lm, (void *) &lmcopy, sizeof (lmcopy));
  
    if (lmcopy.l_name == 0)
      return 0;	/* no filename.  */
  
    /* Now fetch the filename from target memory.  */
!   target_read_string (SOLIB_EXTRACT_ADDRESS (lmcopy.l_name), &filename, 
  		      MAX_PATH_SIZE - 1, &errcode);
    if (errcode)
      {
***************
*** 951,1091 ****
  }
  #endif /* SVR4_SHARED_LIBS */
  
- /*
  
!    LOCAL FUNCTION
  
!    find_solib -- step through list of shared objects
  
     SYNOPSIS
  
!    struct so_list *find_solib (struct so_list *so_list_ptr)
  
     DESCRIPTION
  
!    This module contains the routine which finds the names of any
!    loaded "images" in the current process. The argument in must be
!    NULL on the first call, and then the returned value must be passed
!    in on subsequent calls. This provides the capability to "step" down
!    the list of loaded objects. On the last object, a NULL value is
!    returned.
  
!    The arg and return value are "struct link_map" pointers, as defined
!    in <link.h>.
!  */
  
! static struct so_list *
! find_solib (so_list_ptr)
!      struct so_list *so_list_ptr;	/* Last lm or NULL for first one */
  {
!   struct so_list *so_list_next = NULL;
!   struct link_map *lm = NULL;
!   struct so_list *new;
! 
!   if (so_list_ptr == NULL)
!     {
!       /* We are setting up for a new scan through the loaded images. */
!       if ((so_list_next = so_list_head) == NULL)
! 	{
! 	  /* We have not already read in the dynamic linking structures
! 	     from the inferior, lookup the address of the base structure. */
! 	  debug_base = locate_base ();
! 	  if (debug_base != 0)
! 	    {
! 	      /* Read the base structure in and find the address of the first
! 	         link map list member. */
! 	      lm = first_link_map_member ();
! 	    }
! 	}
      }
!   else
      {
!       /* We have been called before, and are in the process of walking
!          the shared library list.  Advance to the next shared object. */
!       if ((lm = LM_NEXT (so_list_ptr)) == NULL)
! 	{
! 	  /* We have hit the end of the list, so check to see if any were
! 	     added, but be quiet if we can't read from the target any more. */
! 	  int status = target_read_memory ((CORE_ADDR) so_list_ptr->lmaddr,
! 					   (char *) &(so_list_ptr->lm),
! 					   sizeof (struct link_map));
! 	  if (status == 0)
! 	    {
! 	      lm = LM_NEXT (so_list_ptr);
! 	    }
! 	  else
! 	    {
! 	      lm = NULL;
! 	    }
! 	}
!       so_list_next = so_list_ptr->next;
      }
!   if ((so_list_next == NULL) && (lm != NULL))
      {
!       /* Get next link map structure from inferior image and build a local
!          abbreviated load_map structure */
!       new = (struct so_list *) xmalloc (sizeof (struct so_list));
!       memset ((char *) new, 0, sizeof (struct so_list));
        new->lmaddr = lm;
!       /* Add the new node as the next node in the list, or as the root
!          node if this is the first one. */
!       if (so_list_ptr != NULL)
! 	{
! 	  so_list_ptr->next = new;
! 	}
!       else
! 	{
! 	  so_list_head = new;
  
! 	  if (!solib_cleanup_queued)
! 	    {
! 	      make_run_cleanup (do_clear_solib, NULL);
! 	      solib_cleanup_queued = 1;
! 	    }
  
- 	}
-       so_list_next = new;
-       read_memory ((CORE_ADDR) lm, (char *) &(new->lm),
- 		   sizeof (struct link_map));
        /* For SVR4 versions, the first entry in the link map is for the
           inferior executable, so we must ignore it.  For some versions of
           SVR4, it has no name.  For others (Solaris 2.3 for example), it
           does have a name, so we can no longer use a missing name to
           decide when to ignore it. */
!       if (!IGNORE_FIRST_LINK_MAP_ENTRY (new->lm))
  	{
  	  int errcode;
  	  char *buffer;
! 	  target_read_string ((CORE_ADDR) LM_NAME (new), &buffer,
  			      MAX_PATH_SIZE - 1, &errcode);
  	  if (errcode != 0)
  	    {
! 	      warning ("find_solib: Can't read pathname for load map: %s\n",
  		       safe_strerror (errcode));
- 	      return (so_list_next);
  	    }
! 	  strncpy (new->so_name, buffer, MAX_PATH_SIZE - 1);
! 	  new->so_name[MAX_PATH_SIZE - 1] = '\0';
! 	  free (buffer);
! 	  catch_errors (solib_map_sections, new,
! 			"Error while mapping shared library sections:\n",
! 			RETURN_MASK_ALL);
  	}
      }
!   return (so_list_next);
  }
  
  /* A small stub to get us past the arg-passing pinhole of catch_errors.  */
  
  static int
  symbol_add_stub (arg)
       PTR arg;
  {
!   register struct so_list *so = (struct so_list *) arg;		/* catch_errs bogon */
    CORE_ADDR text_addr = 0;
!   struct section_addr_info section_addrs;
  
!   memset (&section_addrs, 0, sizeof (section_addrs));
    if (so->textsection)
      text_addr = so->textsection->addr;
    else if (so->abfd != NULL)
--- 981,1168 ----
  }
  #endif /* SVR4_SHARED_LIBS */
  
  
! /* LOCAL FUNCTION
  
!    free_so --- free a `struct so_list' object
  
     SYNOPSIS
  
!    void free_so (struct so_list *so)
  
     DESCRIPTION
  
!    Free the storage associated with the `struct so_list' object SO.
!    If we have opened a BFD for SO, close it.  
  
!    The caller is responsible for removing SO from whatever list it is
!    a member of.  If we have placed SO's sections in some target's
!    section table, the caller is responsible for removing them.
! 
!    This function doesn't mess with objfiles at all.  If there is an
!    objfile associated with SO that needs to be removed, the caller is
!    responsible for taking care of that.  */
  
! static void
! free_so (struct so_list *so)
  {
!   char *bfd_filename = 0;
! 
!   if (so->sections)
!     free (so->sections);
!       
!   if (so->abfd)
!     {
!       bfd_filename = bfd_get_filename (so->abfd);
!       if (! bfd_close (so->abfd))
! 	warning ("cannot close \"%s\": %s",
! 		 bfd_filename, bfd_errmsg (bfd_get_error ()));
      }
! 
!   if (bfd_filename)
!     free (bfd_filename);
! 
!   free (so);
! }
! 
! 
! /* On some systems, the only way to recognize the link map entry for
!    the main executable file is by looking at its name.  Return
!    non-zero iff SONAME matches one of the known main executable names.  */
! 
! static int
! match_main (soname)
!      char *soname;
! {
!   char **mainp;
! 
!   for (mainp = main_name_list; *mainp != NULL; mainp++)
      {
!       if (strcmp (soname, *mainp) == 0)
! 	return (1);
      }
! 
!   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 *
! current_sos ()
! {
!   CORE_ADDR lm;
!   struct so_list *head = 0;
!   struct so_list **link_ptr = &head;
! 
!   /* Make sure we've looked up the inferior's dynamic linker's base
!      structure.  */
!   if (! debug_base)
      {
!       debug_base = locate_base ();
! 
!       /* If we can't find the dynamic linker's base structure, this
! 	 must not be a dynamically linked executable.  Hmm.  */
!       if (! debug_base)
! 	return 0;
!     }
! 
!   /* Walk the inferior's link map list, and build our list of
!      `struct so_list' nodes.  */
!   lm = first_link_map_member ();  
!   while (lm)
!     {
!       struct so_list *new
! 	= (struct so_list *) xmalloc (sizeof (struct so_list));
!       memset (new, 0, sizeof (*new));
! 
        new->lmaddr = lm;
!       read_memory (lm, (char *) &(new->lm), sizeof (struct link_map));
  
!       lm = LM_NEXT (new);
  
        /* For SVR4 versions, the first entry in the link map is for the
           inferior executable, so we must ignore it.  For some versions of
           SVR4, it has no name.  For others (Solaris 2.3 for example), it
           does have a name, so we can no longer use a missing name to
           decide when to ignore it. */
!       if (IGNORE_FIRST_LINK_MAP_ENTRY (new))
  	{
+ 	  free_so (new);
+ 	}
+       else
+ 	{
  	  int errcode;
  	  char *buffer;
! 
! 	  /* Extract this shared object's name.  */
! 	  target_read_string (LM_NAME (new), &buffer,
  			      MAX_PATH_SIZE - 1, &errcode);
  	  if (errcode != 0)
  	    {
! 	      warning ("current_sos: Can't read pathname for load map: %s\n",
  		       safe_strerror (errcode));
  	    }
! 	  else
! 	    {
! 	      strncpy (new->so_name, buffer, MAX_PATH_SIZE - 1);
! 	      new->so_name[MAX_PATH_SIZE - 1] = '\0';
! 	      free (buffer);
! 	      strcpy (new->so_original_name, new->so_name);
! 	    }
! 
! 	  /* If this entry has no name, or its name matches the name
! 	     for the main executable, don't include it in the list.  */
! 	  if (! new->so_name[0]
! 	      || match_main (new->so_name))
! 	    free_so (new);
! 	  else
! 	    {
! 	      new->next = 0;
! 	      *link_ptr = new;
! 	      link_ptr = &new->next;
! 	    }
  	}
      }
! 
!   return head;
  }
  
+ 
  /* A small stub to get us past the arg-passing pinhole of catch_errors.  */
  
  static int
  symbol_add_stub (arg)
       PTR arg;
  {
!   register struct so_list *so = (struct so_list *) arg;  /* catch_errs bogon */
    CORE_ADDR text_addr = 0;
! 
!   /* Have we already loaded this shared object?  */
!   ALL_OBJFILES (so->objfile)
!     {
!       if (strcmp (so->objfile->name, so->so_name) == 0)
! 	return 1;
!     }
  
!   /* Find the shared object's text segment.  */
    if (so->textsection)
      text_addr = so->textsection->addr;
    else if (so->abfd != NULL)
***************
*** 1094,1168 ****
  
        /* If we didn't find a mapped non zero sized .text section, set up
           text_addr so that the relocation in symbol_file_add does no harm.  */
- 
        lowest_sect = bfd_get_section_by_name (so->abfd, ".text");
        if (lowest_sect == NULL)
  	bfd_map_over_sections (so->abfd, find_lowest_section,
  			       (PTR) &lowest_sect);
        if (lowest_sect)
  	text_addr = bfd_section_vma (so->abfd, lowest_sect)
! 	  + (CORE_ADDR) LM_ADDR (so);
      }
  
-   ALL_OBJFILES (so->objfile)
    {
!     if (strcmp (so->objfile->name, so->so_name) == 0)
!       return 1;
!   }
!   section_addrs.text_addr = text_addr;
!   so->objfile =
!     symbol_file_add (so->so_name, so->from_tty,
! 		     &section_addrs, 0, OBJF_SHARED);
!   return (1);
! }
! 
! /* This function will check the so name to see if matches the main list.
!    In some system the main object is in the list, which we want to exclude */
  
! static int
! match_main (soname)
!      char *soname;
! {
!   char **mainp;
  
!   for (mainp = main_name_list; *mainp != NULL; mainp++)
!     {
!       if (strcmp (soname, *mainp) == 0)
! 	return (1);
!     }
  
!   return (0);
  }
  
- /*
  
!    GLOBAL FUNCTION
  
!    solib_add -- add a shared library file to the symtab and section list
  
     SYNOPSIS
  
!    void solib_add (char *arg_string, int from_tty,
!    struct target_ops *target)
  
     DESCRIPTION
  
!  */
  
  void
! solib_add (arg_string, from_tty, target)
!      char *arg_string;
!      int from_tty;
!      struct target_ops *target;
  {
!   register struct so_list *so = NULL;	/* link map state variable */
! 
!   /* Last shared library that we read.  */
!   struct so_list *so_last = NULL;
  
!   char *re_err;
!   int count;
!   int old;
  
  #ifdef SVR4_SHARED_LIBS
    /* If we are attaching to a running process for which we 
--- 1171,1243 ----
  
        /* If we didn't find a mapped non zero sized .text section, set up
           text_addr so that the relocation in symbol_file_add does no harm.  */
        lowest_sect = bfd_get_section_by_name (so->abfd, ".text");
        if (lowest_sect == NULL)
  	bfd_map_over_sections (so->abfd, find_lowest_section,
  			       (PTR) &lowest_sect);
        if (lowest_sect)
  	text_addr = bfd_section_vma (so->abfd, lowest_sect)
! 	  + LM_ADDR (so);
      }
  
    {
!     struct section_addr_info section_addrs;
  
!     memset (&section_addrs, 0, sizeof (section_addrs));
!     section_addrs.text_addr = text_addr;
  
!     so->objfile = symbol_file_add (so->so_name, so->from_tty,
! 				   &section_addrs, 0, OBJF_SHARED);
!   }
  
!   return (1);
  }
  
  
! /* LOCAL FUNCTION
  
!    solib_add -- synchronize GDB's shared object list with the inferior's
  
     SYNOPSIS
  
!    void solib_add (char *pattern, int from_tty, struct target_ops *TARGET)
  
     DESCRIPTION
  
!    Extract the list of currently loaded shared objects from the
!    inferior, and compare it with the list of shared objects for which
!    GDB has currently loaded symbolic information.  If new shared
!    objects have been loaded, or old shared objects have disappeared,
!    make the appropriate changes to GDB's tables.
! 
!    If PATTERN is non-null, read symbols only for shared objects
!    whose names match PATTERN.
! 
!    If FROM_TTY is non-null, feel free to print messages about what
!    we're doing.
! 
!    If TARGET is non-null, add the sections of all new shared objects
!    to TARGET's section table.  Note that this doesn't remove any
!    sections for shared objects that have been unloaded, and it
!    doesn't check to see if the new shared objects are already present in
!    the section table.  But we only use this for core files and
!    processes we've just attached to, so that's okay.  */
  
  void
! solib_add (char *pattern, int from_tty, struct target_ops *target)
  {
!   struct so_list *inferior = current_sos ();
!   struct so_list *gdb, **gdb_link;
  
!   /* #define JIMB_DEBUG */
! #ifdef JIMB_DEBUG
!   printf ("GDB's shared library list:\n");
!   for (gdb = so_list_head; gdb; gdb = gdb->next)
!     printf ("  %s\n", gdb->so_original_name);
!   printf ("inferior's shared library list:\n");
!   for (gdb = inferior; gdb; gdb = gdb->next)
!     printf ("  %s\n", gdb->so_original_name);
! #endif
  
  #ifdef SVR4_SHARED_LIBS
    /* If we are attaching to a running process for which we 
***************
*** 1175,1254 ****
  		  RETURN_MASK_ALL);
  
  #endif SVR4_SHARED_LIBS
  
!   if ((re_err = re_comp (arg_string? arg_string : ".")) != NULL)
      {
!       error ("Invalid regexp: %s", re_err);
      }
  
!   /* Add the shared library sections to the section table of the
!      specified target, if any.  */
!   if (target)
      {
!       /* Count how many new section_table entries there are.  */
!       so = NULL;
!       count = 0;
!       while ((so = find_solib (so)) != NULL)
  	{
! 	  if (so->so_name[0] && !match_main (so->so_name))
! 	    {
! 	      count += so->sections_end - so->sections;
! 	    }
  	}
  
!       if (count)
  	{
! 	  
! 	  /* Add these section table entries to the target's table.  */
! 	  old = target_resize_to_sections (target, count);
! 	  while ((so = find_solib (so)) != NULL)
! 	    {
! 	      if (so->so_name[0])
! 		{
! 		  count = so->sections_end - so->sections;
! 		  memcpy ((char *) (target->to_sections + old),
! 			  so->sections,
! 			  (sizeof (struct section_table)) * count);
! 		  old += count;
! 		}
! 	    }
  	}
      }
  
!   /* Now add the symbol files.  */
!   while ((so = find_solib (so)) != NULL)
      {
!       if (so->so_name[0] && re_exec (so->so_name) &&
! 	  !match_main (so->so_name))
  	{
! 	  so->from_tty = from_tty;
! 	  if (so->symbols_loaded)
  	    {
! 	      if (from_tty)
  		{
! 		  printf_unfiltered ("Symbols already loaded for %s\n", so->so_name);
  		}
  	    }
! 	  else if (catch_errors
! 		   (symbol_add_stub, so,
! 		    "Error while reading shared library symbols:\n",
! 		    RETURN_MASK_ALL))
  	    {
! 	      so_last = so;
! 	      so->symbols_loaded = 1;
  	    }
  	}
-     }
  
!   /* Getting new symbols may change our opinion about what is
!      frameless.  */
!   if (so_last)
!     reinit_frame_cache ();
  
!   if (so_last)
!     special_symbol_handling (so_last);
  }
  
  /*
  
     LOCAL FUNCTION
--- 1250,1438 ----
  		  RETURN_MASK_ALL);
  
  #endif SVR4_SHARED_LIBS
+ 
+   if (pattern)
+     {
+       char *re_err = re_comp (pattern);
+ 
+       if (re_err)
+ 	error ("Invalid regexp: %s", re_err);
+     }
  
!   /* Since this function might actually add some elements to the
!      so_list_head list, arrange for it to be cleaned up when
!      appropriate.  */
!   if (!solib_cleanup_queued)
      {
!       make_run_cleanup (do_clear_solib, NULL);
!       solib_cleanup_queued = 1;
      }
  
!   /* GDB and the inferior's dynamic linker each maintain their own
!      list of currently loaded shared objects; we want to bring the
!      former in sync with the latter.  Scan both lists, seeing which
!      shared objects appear where.  There are three cases:
! 
!      - A shared object appears on both lists.  This means that GDB
!        knows about it already, and it's still loaded in the inferior.
!        Nothing needs to happen.
! 
!      - A shared object appears only on GDB's list.  This means that
!        the inferior has unloaded it.  We should remove the shared
!        object from GDB's tables.
! 
!      - A shared object appears only on the inferior's list.  This
!        means that it's just been loaded.  We should add it to GDB's
!        tables.
! 
!      So we walk GDB's list, checking each entry to see if it appears
!      in the inferior's list too.  If it does, no action is needed, and
!      we remove it from the inferior's list.  If it doesn't, the
!      inferior has unloaded it, and we remove it from GDB's list.  By
!      the time we're done walking GDB's list, the inferior's list
!      contains only the new shared objects, which we then add.  */
! 
!   gdb = so_list_head;
!   gdb_link = &so_list_head;
!   while (gdb)
      {
!       struct so_list *i = inferior;
!       struct so_list **i_link = &inferior;
! 
!       /* Check to see whether the shared object *gdb also appears in
! 	 the inferior's current list.  */
!       while (i)
  	{
! 	  if (! strcmp (gdb->so_original_name, i->so_original_name))
! 	    break;
! 
! 	  i_link = &i->next;
! 	  i = *i_link;
! 	}
! 
!       /* If the shared object appears on the inferior's list too, then
!          it's still loaded, so we don't need to do anything.  Delete
!          it from the inferior's list, and leave it on GDB's list.  */
!       if (i)
! 	{
! 	  *i_link = i->next;
! #ifdef JIMB_DEBUG
! 	  printf ("unchanged: %s\n", i->so_name);
! #endif
! 	  free_so (i);
! 	  gdb_link = &gdb->next;
! 	  gdb = *gdb_link;
  	}
  
!       /* If it's not on the inferior's list, remove it from GDB's tables.  */
!       else
  	{
! 	  *gdb_link = gdb->next;
! #ifdef JIMB_DEBUG
! 	  printf ("removed:   %s\n", gdb->so_name);
! #endif
! 
! 	  /* Unless the user loaded it explicitly, free SO's objfile.  */
! 	  if (! (gdb->objfile->flags & OBJF_USERLOADED))
! 	    free_objfile (gdb->objfile);
! 
! 	  /* Some targets' section tables might be referring to
! 	     sections from so->abfd; remove them.  */
! 	  remove_target_sections (gdb->abfd);
! 
! 	  free_so (gdb);
! 	  gdb = *gdb_link;
  	}
      }
  
!   /* Now the inferior's list contains only shared objects that don't
!      appear in GDB's list --- those that are newly loaded.  Add them
!      to GDB's shared object list, and read in their symbols, if
!      appropriate.  */
!   if (inferior)
      {
!       struct so_list *i;
! 
!       /* Add the new shared objects to GDB's list.  */
!       *gdb_link = inferior;
! 
!       /* Fill in the rest of each of the `struct so_list' nodes, and
! 	 read symbols for those files whose names match PATTERN.  */
!       for (i = inferior; i; i = i->next)
  	{
! 	  i->from_tty = from_tty;
! 
! 	  /* Fill in the rest of the `struct so_list' node.  */
! 	  catch_errors (solib_map_sections, i,
! 			"Error while mapping shared library sections:\n",
! 			RETURN_MASK_ALL);
! 
! 	  if (! pattern || re_exec (i->so_name))
  	    {
! 	      if (i->symbols_loaded)
  		{
! 		  if (from_tty)
! 		    printf_unfiltered ("Symbols already loaded for %s\n",
! 				       i->so_name);
  		}
+ 	      else
+ 		{
+ #ifdef JIMB_DEBUG
+ 		  printf ("added:     %s\n", i->so_name);
+ #endif
+ 		  if (catch_errors
+ 		      (symbol_add_stub, i,
+ 		       "Error while reading shared library symbols:\n",
+ 		       RETURN_MASK_ALL))
+ 		    {
+ 		      if (from_tty)
+ 			printf_unfiltered ("Loaded symbols for %s\n",
+ 					   i->so_name);
+ 		      i->symbols_loaded = 1;
+ 		    }
+ 		}
  	    }
! 	}
! 
!       /* If requested, add the shared objects' sections to the the
! 	 TARGET's section table.  */
!       if (target)
! 	{
! 	  int new_sections;
! 
! 	  /* Figure out how many sections we'll need to add in total.  */
! 	  new_sections = 0;
! 	  for (i = inferior; i; i = i->next)
! 	    new_sections += (i->sections_end - i->sections);
! 
! 	  if (new_sections > 0)
  	    {
! 	      int space = target_resize_to_sections (target, new_sections);
! 
! 	      for (i = inferior; i; i = i->next)
! 		{
! 		  int count = (i->sections_end - i->sections);
! 		  memcpy (target->to_sections + space,
! 			  i->sections,
! 			  count * sizeof (i->sections[0]));
! 		  space += count;
! 		}
  	    }
  	}
  
!       /* Getting new symbols may change our opinion about what is
!          frameless.  */
!       reinit_frame_cache ();
  
!       special_symbol_handling ();
!     }
! 
! #ifdef JIMB_DEBUG
!   putchar ('\n');
! #endif
  }
  
+ 
  /*
  
     LOCAL FUNCTION
***************
*** 1289,1295 ****
    addr_fmt = "016l";
  #endif
  
!   while ((so = find_solib (so)) != NULL)
      {
        if (so->so_name[0])
  	{
--- 1473,1481 ----
    addr_fmt = "016l";
  #endif
  
!   solib_add (0, 0, 0);
! 
!   for (so = so_list_head; so; so = so->next)
      {
        if (so->so_name[0])
  	{
***************
*** 1347,1361 ****
  {
    register struct so_list *so = 0;	/* link map state variable */
  
!   while ((so = find_solib (so)) != NULL)
      {
!       if (so->so_name[0])
! 	{
! 	  if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
! 	      (address < (CORE_ADDR) so->lmend))
! 	    return (so->so_name);
! 	}
      }
    return (0);
  }
  
--- 1533,1544 ----
  {
    register struct so_list *so = 0;	/* link map state variable */
  
!   for (so = so_list_head; so; so = so->next)
      {
!       if (LM_ADDR (so) <= address && address < so->lmend)
! 	return (so->so_name);
      }
+ 
    return (0);
  }
  
***************
*** 1364,1372 ****
  void
  clear_solib ()
  {
-   struct so_list *next;
-   char *bfd_filename;
- 
    /* This function is expected to handle ELF shared libraries.  It is
       also used on Solaris, which can run either ELF or a.out binaries
       (for compatibility with SunOS 4), both of which can use shared
--- 1547,1552 ----
***************
*** 1393,1419 ****
  
    while (so_list_head)
      {
!       if (so_list_head->sections)
! 	{
! 	  free ((PTR) so_list_head->sections);
! 	}
!       if (so_list_head->abfd)
! 	{
! 	  bfd_filename = bfd_get_filename (so_list_head->abfd);
! 	  if (!bfd_close (so_list_head->abfd))
! 	    warning ("cannot close \"%s\": %s",
! 		     bfd_filename, bfd_errmsg (bfd_get_error ()));
! 	}
!       else
! 	/* This happens for the executable on SVR4.  */
! 	bfd_filename = NULL;
! 
!       next = so_list_head->next;
!       if (bfd_filename)
! 	free ((PTR) bfd_filename);
!       free ((PTR) so_list_head);
!       so_list_head = next;
      }
    debug_base = 0;
  }
  
--- 1573,1583 ----
  
    while (so_list_head)
      {
!       struct so_list *so = so_list_head;
!       so_list_head = so->next;
!       free_so (so);
      }
+ 
    debug_base = 0;
  }
  
***************
*** 1484,1490 ****
  
    write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
  
!   breakpoint_addr = (CORE_ADDR) debug_copy.ldd_bp_addr;
    write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst,
  		sizeof (debug_copy.ldd_bp_inst));
  
--- 1648,1654 ----
  
    write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
  
!   breakpoint_addr = SOLIB_EXTRACT_ADDRESS (debug_copy.ldd_bp_addr);
    write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst,
  		sizeof (debug_copy.ldd_bp_inst));
  
***************
*** 1579,1585 ****
  
    /* Calc address of debugger interface structure */
  
!   debug_addr = (CORE_ADDR) dynamic_copy.ldd;
  
    /* Calc address of `in_debugger' member of debugger interface structure */
  
--- 1743,1749 ----
  
    /* Calc address of debugger interface structure */
  
!   debug_addr = SOLIB_EXTRACT_ADDRESS (dynamic_copy.ldd);
  
    /* Calc address of `in_debugger' member of debugger interface structure */
  
***************
*** 1775,1781 ****
  {
    /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
       yet.  In fact, in the case of a SunOS4 executable being run on
!      Solaris, we can't get it yet.  find_solib will get it when it needs
       it.  */
  #if !(defined (SVR4_SHARED_LIBS) && defined (BKPT_AT_SYMBOL))
    if ((debug_base = locate_base ()) == 0)
--- 1939,1945 ----
  {
    /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
       yet.  In fact, in the case of a SunOS4 executable being run on
!      Solaris, we can't get it yet.  current_sos will get it when it needs
       it.  */
  #if !(defined (SVR4_SHARED_LIBS) && defined (BKPT_AT_SYMBOL))
    if ((debug_base = locate_base ()) == 0)
***************
*** 1843,1849 ****
  
     SYNOPSIS
  
!    void special_symbol_handling (struct so_list *so)
  
     DESCRIPTION
  
--- 2007,2013 ----
  
     SYNOPSIS
  
!    void special_symbol_handling ()
  
     DESCRIPTION
  
***************
*** 1859,1866 ****
   */
  
  static void
! special_symbol_handling (so)
!      struct so_list *so;
  {
  #ifndef SVR4_SHARED_LIBS
    int j;
--- 2023,2029 ----
   */
  
  static void
! special_symbol_handling ()
  {
  #ifndef SVR4_SHARED_LIBS
    int j;
***************
*** 1881,1887 ****
        /* FIXME, this needs work for cross-debugging of core files
           (byteorder, size, alignment, etc).  */
  
!       debug_addr = (CORE_ADDR) dynamic_copy.ldd;
      }
  
    /* Read the debugger structure from the inferior, just to make sure
--- 2044,2050 ----
        /* FIXME, this needs work for cross-debugging of core files
           (byteorder, size, alignment, etc).  */
  
!       debug_addr = SOLIB_EXTRACT_ADDRESS (dynamic_copy.ldd);
      }
  
    /* Read the debugger structure from the inferior, just to make sure
***************
*** 1896,1902 ****
  
    if (debug_copy.ldd_cp)
      {
!       solib_add_common_symbols (debug_copy.ldd_cp);
      }
  
  #endif /* !SVR4_SHARED_LIBS */
--- 2059,2065 ----
  
    if (debug_copy.ldd_cp)
      {
!       solib_add_common_symbols (SOLIB_EXTRACT_ADDRESS (debug_copy.ldd_cp));
      }
  
  #endif /* !SVR4_SHARED_LIBS */
Index: gdb/target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.3
diff -c -r1.3 target.c
*** gdb/target.c	2000/02/16 22:24:50	1.3
--- gdb/target.c	2000/03/14 23:57:55
***************
*** 1325,1330 ****
--- 1325,1363 ----
  
  }
  
+ /* Remove all target sections taken from ABFD.
+ 
+    Scan the current target stack for targets whose section tables
+    refer to sections from BFD, and remove those sections.  We use this
+    when we notice that the inferior has unloaded a shared object, for
+    example.  */
+ void
+ remove_target_sections (bfd *abfd)
+ {
+   struct target_ops **t;
+ 
+   for (t = target_structs; t < target_structs + target_struct_size; t++)
+     {
+       struct section_table *src, *dest;
+ 
+       dest = (*t)->to_sections;
+       for (src = (*t)->to_sections; src < (*t)->to_sections_end; src++)
+ 	if (src->bfd != abfd)
+ 	  {
+ 	    /* Keep this section.  */
+ 	    if (dest < src) *dest = *src;
+ 	    dest++;
+ 	  }
+ 
+       /* If we've dropped any sections, resize the section table.  */
+       if (dest < src)
+ 	target_resize_to_sections (*t, dest - src);
+     }
+ }
+ 
+ 
+ 
+ 
  /* Find a single runnable target in the stack and return it.  If for
     some reason there is more than one, return NULL.  */
  
Index: gdb/target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.1.1.17
diff -c -r1.1.1.17 target.h
*** gdb/target.h	2000/02/02 00:21:11	1.1.1.17
--- gdb/target.h	2000/03/14 23:57:56
***************
*** 1377,1382 ****
--- 1377,1385 ----
  
  extern int
  target_resize_to_sections PARAMS ((struct target_ops *target, int num_added));
+ 
+ extern void remove_target_sections (bfd *abfd);
+ 
  
  /* Stuff that should be shared among the various remote targets.  */
  

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