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]

[PATCH v16 1/5] New remove-symbol-file command.


New command for removing symbol files added via
the add-symbol-file command.

2013-18-03  Nicolas Blanc  <nicolas.blanc@intel.com>

	* breakpoint.c (disable_breakpoints_in_freed_objfile): New function.
	* objfiles.c (free_objfile): Notify free_objfile.
	(is_addr_in_objfile): New function.
	* objfiles.h (is_addr_in_objfile): New declaration.
	* printcmd.c (clear_dangling_display_expressions): Act upon free_objfile
	events instead of solib_unloaded events.
	(_initialize_printcmd): Register observer for free_objfile instead
	of solib_unloaded notifications.
	* solib.c (remove_user_added_objfile): New function.
	* symfile.c (remove_symbol_file_command): New command.
	(_initialize_symfile): Add remove-symbol-file.
gdb/doc
	* observer.texi: New free_objfile event.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/breakpoint.c      |   67 ++++++++++++++++++++++++++++++++++++++--
 gdb/doc/observer.texi |    4 ++
 gdb/objfiles.c        |   23 ++++++++++++++
 gdb/objfiles.h        |    2 +
 gdb/printcmd.c        |   15 +++++---
 gdb/solib.c           |   22 +++++++++++++
 gdb/symfile.c         |   82 +++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 206 insertions(+), 9 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b98ca9e..d180c76 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7467,9 +7467,9 @@ disable_breakpoints_in_shlibs (void)
   }
 }
 
-/* Disable any breakpoints and tracepoints that are in an unloaded shared
-   library.  Only apply to enabled breakpoints, disabled ones can just stay
-   disabled.  */
+/* Disable any breakpoints and tracepoints that are in SOLIB upon
+   notification of unloaded_shlib.  Only apply to enabled breakpoints,
+   disabled ones can just stay disabled.  */
 
 static void
 disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
@@ -7521,6 +7521,66 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
   }
 }
 
+/* Disable any breakpoints and tracepoints in OBJFILE upon
+   notification of free_objfile.  Only apply to enabled breakpoints,
+   disabled ones can just stay disabled.  */
+
+static void
+disable_breakpoints_in_freed_objfile (struct objfile *objfile)
+{
+  struct breakpoint *b;
+
+  if (objfile == NULL)
+    return;
+
+  /* If the file is a shared library not loaded by the user then
+     solib_unloaded was notified and disable_breakpoints_in_unloaded_shlib
+     was called.  In that case there is no need to take action again.  */
+  if ((objfile->flags & OBJF_SHARED) && !(objfile->flags & OBJF_USERLOADED))
+    return;
+
+  ALL_BREAKPOINTS (b)
+    {
+      struct bp_location *loc;
+      int bp_modified = 0;
+
+      if (!is_breakpoint (b) && !is_tracepoint (b))
+	continue;
+
+      for (loc = b->loc; loc != NULL; loc = loc->next)
+	{
+	  CORE_ADDR loc_addr = loc->address;
+
+	  if (loc->loc_type != bp_loc_hardware_breakpoint
+	      && loc->loc_type != bp_loc_software_breakpoint)
+	    continue;
+
+	  if (loc->shlib_disabled != 0)
+	    continue;
+
+	  if (objfile->pspace != loc->pspace)
+	    continue;
+
+	  if (loc->loc_type != bp_loc_hardware_breakpoint
+	      && loc->loc_type != bp_loc_software_breakpoint)
+	    continue;
+
+	  if (is_addr_in_objfile (loc_addr, objfile))
+	    {
+	      loc->shlib_disabled = 1;
+	      loc->inserted = 0;
+
+	      mark_breakpoint_location_modified (loc);
+
+	      bp_modified = 1;
+	    }
+	}
+
+      if (bp_modified)
+	observer_notify_breakpoint_modified (b);
+    }
+}
+
 /* FORK & VFORK catchpoints.  */
 
 /* An instance of this type is used to represent a fork or vfork
@@ -15995,6 +16055,7 @@ _initialize_breakpoint (void)
   initialize_breakpoint_ops ();
 
   observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
+  observer_attach_free_objfile (disable_breakpoints_in_freed_objfile);
   observer_attach_inferior_exit (clear_syscall_counts);
   observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
 
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index adb7085..f753965 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -138,6 +138,10 @@ Called with @var{objfile} equal to @code{NULL} to indicate
 previously loaded symbol table data has now been invalidated.
 @end deftypefun
 
+@deftypefun void free_objfile (struct objfile *@var{objfile})
+The object file specified by @var{objfile} is about to be freed.
+@end deftypefun
+
 @deftypefun void new_thread (struct thread_info *@var{t})
 The thread specified by @var{t} has been created.
 @end deftypefun
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index b10f803..b7a00a0 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -545,6 +545,9 @@ free_objfile_separate_debug (struct objfile *objfile)
 void
 free_objfile (struct objfile *objfile)
 {
+  /* First notify observers that this objfile is about to be freed.  */
+  observer_notify_free_objfile (objfile);
+
   /* Free all separate debug objfiles.  */
   free_objfile_separate_debug (objfile);
 
@@ -1463,6 +1466,26 @@ resume_section_map_updates_cleanup (void *arg)
   resume_section_map_updates (arg);
 }
 
+/* Return 1 if ADDR maps into one of the sections of OBJFILE and 0
+   otherwise.  */
+
+int
+is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile)
+{
+  struct obj_section *osect;
+
+  if (objfile == NULL)
+    return 0;
+
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      if (obj_section_addr (osect) <= addr
+	  && addr < obj_section_endaddr (osect))
+	return 1;
+    }
+  return 0;
+}
+
 /* The default implementation for the "iterate_over_objfiles_in_search_order"
    gdbarch method.  It is equivalent to use the ALL_OBJFILES macro,
    searching the objfiles in the order they are stored internally,
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 72cef50..e0fc1ba 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -480,6 +480,8 @@ extern void objfile_set_sym_fns (struct objfile *objfile,
 
 extern void objfiles_changed (void);
 
+extern int is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile);
+
 /* This operation deletes all objfile entries that represent solibs that
    weren't explicitly loaded by the user, via e.g., the add-symbol-file
    command.  */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 751cd2b..55531b5 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1940,21 +1940,24 @@ disable_display_command (char *args, int from_tty)
    an item by re-parsing .exp_string field in the new execution context.  */
 
 static void
-clear_dangling_display_expressions (struct so_list *solib)
+clear_dangling_display_expressions (struct objfile *objfile)
 {
-  struct objfile *objfile = solib->objfile;
   struct display *d;
+  struct program_space *pspace;
 
   /* With no symbol file we cannot have a block or expression from it.  */
   if (objfile == NULL)
     return;
+  pspace = objfile->pspace;
   if (objfile->separate_debug_objfile_backlink)
-    objfile = objfile->separate_debug_objfile_backlink;
-  gdb_assert (objfile->pspace == solib->pspace);
+    {
+      objfile = objfile->separate_debug_objfile_backlink;
+      gdb_assert (objfile->pspace == pspace);
+    }
 
   for (d = display_chain; d != NULL; d = d->next)
     {
-      if (d->pspace != solib->pspace)
+      if (d->pspace != pspace)
 	continue;
 
       if (lookup_objfile_from_block (d->block) == objfile
@@ -2486,7 +2489,7 @@ _initialize_printcmd (void)
 
   current_display_number = -1;
 
-  observer_attach_solib_unloaded (clear_dangling_display_expressions);
+  observer_attach_free_objfile (clear_dangling_display_expressions);
 
   add_info ("address", address_info,
 	    _("Describe where symbol SYM is stored."));
diff --git a/gdb/solib.c b/gdb/solib.c
index 8ed492a..ef7cd2e 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1496,6 +1496,26 @@ gdb_bfd_lookup_symbol (bfd *abfd,
   return symaddr;
 }
 
+/* SO_LIST_HEAD may contain user-loaded object files that can be removed
+   out-of-band by the user.  So upon notification of free_objfile remove
+   all references to any user-loaded file that is about to be freed.  */
+
+static void
+remove_user_added_objfile (struct objfile *objfile)
+{
+  struct so_list *so;
+
+  if (objfile == NULL)
+    return;
+
+  if (objfile->flags & OBJF_USERLOADED)
+    {
+      for (so = so_list_head; so != NULL; so = so->next)
+	if (so->objfile == objfile)
+	  so->objfile = NULL;
+    }
+}
+
 extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
 
 void
@@ -1503,6 +1523,8 @@ _initialize_solib (void)
 {
   solib_data = gdbarch_data_register_pre_init (solib_init);
 
+  observer_attach_free_objfile (remove_user_added_objfile);
+
   add_com ("sharedlibrary", class_files, sharedlibrary_command,
 	   _("Load shared object library symbols for files matching REGEXP."));
   add_info ("sharedlibrary", info_sharedlibrary_command,
diff --git a/gdb/symfile.c b/gdb/symfile.c
index ecf4e32..f960088 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2342,6 +2342,79 @@ add_symbol_file_command (char *args, int from_tty)
 }
 
 
+/* This function removes a symbol file that was added via add-symbol-file.  */
+
+static void
+remove_symbol_file_command (char *args, int from_tty)
+{
+  char **argv;
+  struct objfile *objf = NULL;
+  struct cleanup *my_cleanups;
+  struct program_space *pspace = current_program_space;
+  struct gdbarch *gdbarch = get_current_arch ();
+
+  dont_repeat ();
+
+  if (args == NULL)
+    error (_("remove-symbol-file FILENAME\nremove-symbol-file -a ADDRESS"));
+
+  my_cleanups = make_cleanup (null_cleanup, NULL);
+
+  argv = gdb_buildargv (args);
+
+  if (strcmp (argv[0], "-a") == 0)
+    {
+      /* Interpret the next argument as an address.  */
+      CORE_ADDR addr;
+
+      if (argv[1] == NULL)
+	error (_("Missing address argument"));
+
+      if (argv[2] != NULL)
+	error (_("Junk after %s"), argv[1]);
+
+      addr = parse_and_eval_address (argv[1]);
+
+      ALL_OBJFILES (objf)
+	{
+	  if (objf->flags & OBJF_USERLOADED
+	      && objf->pspace == pspace && is_addr_in_objfile (addr, objf))
+	    break;
+	}
+    }
+  else if (argv[0] != NULL)
+    {
+      /* Interpret the current argument as a file name.  */
+      char *filename;
+
+      if (argv[1] != NULL)
+	error (_("Junk after %s"), argv[0]);
+
+      filename = tilde_expand (argv[0]);
+      make_cleanup (xfree, filename);
+
+      ALL_OBJFILES (objf)
+	{
+	  if (objf->flags & OBJF_USERLOADED
+	      && objf->pspace == pspace
+	      && filename_cmp (filename, objfile_name (objf)) == 0)
+	    break;
+	}
+    }
+
+  if (objf == NULL)
+    error (_("No symbol file found"));
+
+  if (from_tty
+      && !query (_("Remove symbol table from file \"%s\"? "), objfile_name (objf)))
+    error (_("Not confirmed."));
+
+  free_objfile (objf);
+  clear_symtab_users (0);
+
+  do_cleanups (my_cleanups);
+}
+
 typedef struct objfile *objfilep;
 
 DEF_VEC_P (objfilep);
@@ -3769,6 +3842,15 @@ with the text.  SECT is a section name to be loaded at SECT_ADDR."),
 	       &cmdlist);
   set_cmd_completer (c, filename_completer);
 
+  c = add_cmd ("remove-symbol-file", class_files,
+	       remove_symbol_file_command, _("\
+Remove a symbol file added via the add-symbol-file command.\n\
+Usage: remove-symbol-file FILENAME\n\
+       remove-symbol-file -a ADDRESS\n\
+The file to remove can be identified by its filename or by an address\n\
+that lies within the boundaries of this symbol file in memory."),
+	       &cmdlist);
+
   c = add_cmd ("load", class_files, load_command, _("\
 Dynamically load FILE into the running program, and record its symbols\n\
 for access from GDB.\n\
-- 
1.7.6.5


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