New remove-symbol-file command.
New command for removing symbol files added via the add-symbol-file command. 2013-10-29 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>
This commit is contained in:
parent
487ad57ccf
commit
63644780ba
|
@ -7475,9 +7475,9 @@ disable_breakpoints_in_shlibs (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable any breakpoints and tracepoints that are in an unloaded shared
|
/* Disable any breakpoints and tracepoints that are in SOLIB upon
|
||||||
library. Only apply to enabled breakpoints, disabled ones can just stay
|
notification of unloaded_shlib. Only apply to enabled breakpoints,
|
||||||
disabled. */
|
disabled ones can just stay disabled. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
|
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
|
||||||
|
@ -7529,6 +7529,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. */
|
/* FORK & VFORK catchpoints. */
|
||||||
|
|
||||||
/* An instance of this type is used to represent a fork or vfork
|
/* An instance of this type is used to represent a fork or vfork
|
||||||
|
@ -16007,6 +16067,7 @@ _initialize_breakpoint (void)
|
||||||
initialize_breakpoint_ops ();
|
initialize_breakpoint_ops ();
|
||||||
|
|
||||||
observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
|
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_inferior_exit (clear_syscall_counts);
|
||||||
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
|
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,10 @@ Called with @var{objfile} equal to @code{NULL} to indicate
|
||||||
previously loaded symbol table data has now been invalidated.
|
previously loaded symbol table data has now been invalidated.
|
||||||
@end deftypefun
|
@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})
|
@deftypefun void new_thread (struct thread_info *@var{t})
|
||||||
The thread specified by @var{t} has been created.
|
The thread specified by @var{t} has been created.
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
|
@ -548,6 +548,9 @@ free_objfile_separate_debug (struct objfile *objfile)
|
||||||
void
|
void
|
||||||
free_objfile (struct objfile *objfile)
|
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 all separate debug objfiles. */
|
||||||
free_objfile_separate_debug (objfile);
|
free_objfile_separate_debug (objfile);
|
||||||
|
|
||||||
|
@ -1464,6 +1467,29 @@ resume_section_map_updates_cleanup (void *arg)
|
||||||
resume_section_map_updates (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 (section_is_overlay (osect) && !section_is_mapped (osect))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
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"
|
/* The default implementation for the "iterate_over_objfiles_in_search_order"
|
||||||
gdbarch method. It is equivalent to use the ALL_OBJFILES macro,
|
gdbarch method. It is equivalent to use the ALL_OBJFILES macro,
|
||||||
searching the objfiles in the order they are stored internally,
|
searching the objfiles in the order they are stored internally,
|
||||||
|
|
|
@ -485,6 +485,8 @@ extern void objfile_set_sym_fns (struct objfile *objfile,
|
||||||
|
|
||||||
extern void objfiles_changed (void);
|
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
|
/* This operation deletes all objfile entries that represent solibs that
|
||||||
weren't explicitly loaded by the user, via e.g., the add-symbol-file
|
weren't explicitly loaded by the user, via e.g., the add-symbol-file
|
||||||
command. */
|
command. */
|
||||||
|
|
|
@ -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. */
|
an item by re-parsing .exp_string field in the new execution context. */
|
||||||
|
|
||||||
static void
|
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 display *d;
|
||||||
|
struct program_space *pspace;
|
||||||
|
|
||||||
/* With no symbol file we cannot have a block or expression from it. */
|
/* With no symbol file we cannot have a block or expression from it. */
|
||||||
if (objfile == NULL)
|
if (objfile == NULL)
|
||||||
return;
|
return;
|
||||||
|
pspace = objfile->pspace;
|
||||||
if (objfile->separate_debug_objfile_backlink)
|
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)
|
for (d = display_chain; d != NULL; d = d->next)
|
||||||
{
|
{
|
||||||
if (d->pspace != solib->pspace)
|
if (d->pspace != pspace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (lookup_objfile_from_block (d->block) == objfile
|
if (lookup_objfile_from_block (d->block) == objfile
|
||||||
|
@ -2487,7 +2490,7 @@ _initialize_printcmd (void)
|
||||||
|
|
||||||
current_display_number = -1;
|
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,
|
add_info ("address", address_info,
|
||||||
_("Describe where symbol SYM is stored."));
|
_("Describe where symbol SYM is stored."));
|
||||||
|
|
19
gdb/solib.c
19
gdb/solib.c
|
@ -1496,6 +1496,23 @@ gdb_bfd_lookup_symbol (bfd *abfd,
|
||||||
return symaddr;
|
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 != 0 && 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 */
|
extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1503,6 +1520,8 @@ _initialize_solib (void)
|
||||||
{
|
{
|
||||||
solib_data = gdbarch_data_register_pre_init (solib_init);
|
solib_data = gdbarch_data_register_pre_init (solib_init);
|
||||||
|
|
||||||
|
observer_attach_free_objfile (remove_user_added_objfile);
|
||||||
|
|
||||||
add_com ("sharedlibrary", class_files, sharedlibrary_command,
|
add_com ("sharedlibrary", class_files, sharedlibrary_command,
|
||||||
_("Load shared object library symbols for files matching REGEXP."));
|
_("Load shared object library symbols for files matching REGEXP."));
|
||||||
add_info ("sharedlibrary", info_sharedlibrary_command,
|
add_info ("sharedlibrary", info_sharedlibrary_command,
|
||||||
|
|
|
@ -2342,6 +2342,82 @@ 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: no symbol file provided"));
|
||||||
|
|
||||||
|
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 != 0
|
||||||
|
&& 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 != 0
|
||||||
|
&& 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;
|
typedef struct objfile *objfilep;
|
||||||
|
|
||||||
DEF_VEC_P (objfilep);
|
DEF_VEC_P (objfilep);
|
||||||
|
@ -3764,6 +3840,15 @@ with the text. SECT is a section name to be loaded at SECT_ADDR."),
|
||||||
&cmdlist);
|
&cmdlist);
|
||||||
set_cmd_completer (c, filename_completer);
|
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, _("\
|
c = add_cmd ("load", class_files, load_command, _("\
|
||||||
Dynamically load FILE into the running program, and record its symbols\n\
|
Dynamically load FILE into the running program, and record its symbols\n\
|
||||||
for access from GDB.\n\
|
for access from GDB.\n\
|
||||||
|
|
Loading…
Reference in New Issue