From a3247a22136e0b53cf5c40c67ee4f5e8eb92ec32 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Thu, 5 Mar 2009 23:45:14 +0000 Subject: [PATCH] 2009-03-05 Paul Pluzhnikov * printcmd.c (do_one_display): Reparse exp_string. (display_uses_solib_p): New function. (clear_dangling_display_expressions): New function. (_initialize_printcmd): Add observer. * solib.c (no_shared_libraries): Swap order of calls to clear_solib and objfile_purge_solibs. --- gdb/ChangeLog | 9 ++ gdb/printcmd.c | 94 +++++++++++++++- gdb/solib.c | 7 +- gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.base/solib-display-lib.c | 30 +++++ gdb/testsuite/gdb.base/solib-display-main.c | 32 ++++++ gdb/testsuite/gdb.base/solib-display.exp | 115 ++++++++++++++++++++ 7 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.base/solib-display-lib.c create mode 100644 gdb/testsuite/gdb.base/solib-display-main.c create mode 100644 gdb/testsuite/gdb.base/solib-display.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index eb4c4908bc1..5be5131f0db 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2009-03-05 Paul Pluzhnikov + + * printcmd.c (do_one_display): Reparse exp_string. + (display_uses_solib_p): New function. + (clear_dangling_display_expressions): New function. + (_initialize_printcmd): Add observer. + * solib.c (no_shared_libraries): Swap order of calls to + clear_solib and objfile_purge_solibs. + 2009-03-05 Joel Brobecker Implement the target-specific part of Ada tasking support diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 375f82ed753..58621615ac0 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -43,6 +43,11 @@ #include "disasm.h" #include "dfp.h" #include "valprint.h" +#include "exceptions.h" +#include "observer.h" +#include "solist.h" +#include "solib.h" +#include "parser-defs.h" #ifdef TUI #include "tui/tui.h" /* For tui_active et.al. */ @@ -1395,7 +1400,7 @@ display_command (char *exp, int from_tty) fmt.count = 0; } - innermost_block = 0; + innermost_block = NULL; expr = parse_expression (exp); new = (struct display *) xmalloc (sizeof (struct display)); @@ -1519,6 +1524,25 @@ do_one_display (struct display *d) if (d->enabled_p == 0) return; + if (d->exp == NULL) + { + volatile struct gdb_exception ex; + TRY_CATCH (ex, RETURN_MASK_ALL) + { + innermost_block = NULL; + d->exp = parse_expression (d->exp_string); + d->block = innermost_block; + } + if (ex.reason < 0) + { + /* Can't re-parse the expression. Disable this display item. */ + d->enabled_p = 0; + warning (_("Unable to display \"%s\": %s"), + d->exp_string, ex.message); + return; + } + } + if (d->block) within_current_scope = contained_in (get_selected_block (0), d->block); else @@ -1731,6 +1755,72 @@ disable_display_command (char *args, int from_tty) p++; } } + +/* Return 1 if D uses SOLIB (and will become dangling when SOLIB + is unloaded), otherwise return 0. */ + +static int +display_uses_solib_p (const struct display *d, + const struct so_list *solib) +{ + int i; + struct expression *const exp = d->exp; + + if (d->block != NULL + && solib_address (d->block->startaddr) == solib->so_name) + return 1; + + for (i = 0; i < exp->nelts; ) + { + int args, oplen = 0; + const union exp_element *const elts = exp->elts; + + if (elts[i].opcode == OP_VAR_VALUE) + { + const struct block *const block = elts[i + 1].block; + const struct symbol *const symbol = elts[i + 2].symbol; + const struct obj_section *const section = + SYMBOL_OBJ_SECTION (symbol); + + if (block != NULL + && solib_address (block->startaddr) == solib->so_name) + return 1; + + if (section && section->objfile == solib->objfile) + return 1; + } + exp->language_defn->la_exp_desc->operator_length (exp, i + 1, + &oplen, &args); + gdb_assert (oplen > 0); + i += oplen; + } + return 0; +} + +/* display_chain items point to blocks and expressions. Some expressions in + turn may point to symbols. + Both symbols and blocks are obstack_alloc'd on objfile_stack, and are + obstack_free'd when a shared library is unloaded. + Clear pointers that are about to become dangling. + Both .exp and .block fields will be restored next time we need to display + an item by re-parsing .exp_string field in the new execution context. */ + +static void +clear_dangling_display_expressions (struct so_list *solib) +{ + struct display *d; + struct objfile *objfile = NULL; + + for (d = display_chain; d; d = d->next) + { + if (d->exp && display_uses_solib_p (d, solib)) + { + xfree (d->exp); + d->exp = NULL; + d->block = NULL; + } + } +} /* Print the value in stack frame FRAME of a variable specified by a @@ -2367,6 +2457,8 @@ _initialize_printcmd (void) current_display_number = -1; + observer_attach_solib_unloaded (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 f3e03a16ef0..800319f0704 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -999,8 +999,13 @@ sharedlibrary_command (char *args, int from_tty) void no_shared_libraries (char *ignored, int from_tty) { - objfile_purge_solibs (); + /* The order of the two routines below is important: clear_solib notifies + the solib_unloaded observers, and some of these observers might need + access to their associated objfiles. Therefore, we can not purge the + solibs' objfiles before clear_solib has been called. */ + clear_solib (); + objfile_purge_solibs (); } static void diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e8868693345..50e61ce0731 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-03-05 Paul Pluzhnikov + + * solib-display.exp: New file. + * solib-display-main.c: New file. + * solib-display-lib.c: New file. + 2009-03-05 Pedro Alves * gdb.arch/i386-permbkpt.S, gdb.arch/i386-permbkpt.exp: New. diff --git a/gdb/testsuite/gdb.base/solib-display-lib.c b/gdb/testsuite/gdb.base/solib-display-lib.c new file mode 100644 index 00000000000..18cb257a0bd --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-display-lib.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 Free Software Foundation, Inc. + + 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 . */ + +int a_global = 41; +#ifndef NO_B_GLOBAL +int b_global = 42; +#endif +int c_global = 43; + +int foo () { + return a_global + +#ifndef NO_B_GLOBAL + b_global + +#endif + c_global; +} diff --git a/gdb/testsuite/gdb.base/solib-display-main.c b/gdb/testsuite/gdb.base/solib-display-main.c new file mode 100644 index 00000000000..be2a34a0765 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-display-main.c @@ -0,0 +1,32 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 Free Software Foundation, Inc. + + 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 . */ + +extern int foo (); + +int main_global = 44; +int bar () +{ + int a_local = 45; + static int a_static = 46; + return main_global + a_local + a_static; /* break here */ +} + +int main () +{ + bar (); + return foo (); +} diff --git a/gdb/testsuite/gdb.base/solib-display.exp b/gdb/testsuite/gdb.base/solib-display.exp new file mode 100644 index 00000000000..d4b49f35130 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-display.exp @@ -0,0 +1,115 @@ +# Copyright 2009 Free Software Foundation, Inc. +# 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 . +# +# Contributed by Paul Pluzhnikov +# + +# This test case verifies that if a display is active on a variable +# which belongs in a shared library, and that shared library is +# reloaded (e.g. due to re-execution of the program), GDB will continue +# to display it (gdb-6.8 crashed under this scenario). + +# Also test that a display of variable which is currently present in +# a shared library, but disappears before re-run, doesn't cause GDB +# difficulties, and that it continues to display other variables. + +# Finally, test that displays which refer to main executable +# (and thus aren't affected by shared library unloading) are not +# disabled prematurely. + +if [skip_shlib_tests] then { + return 0 +} + +# Library file. +set libname "solib-display-lib" +set srcfile_lib ${srcdir}/${subdir}/${libname}.c +set binfile_lib ${objdir}/${subdir}/${libname}.so +set lib_flags [list debug] +# Binary file. +set testfile "solib-display-main" +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set bin_flags [list debug shlib=${binfile_lib}] + +if [get_compiler_info ${binfile}] { + return -1 +} + +if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != "" + || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } { + untested "Could not compile $binfile_lib or $binfile." + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "display a_global" "1: a_global = 41" +gdb_test "display b_global" "2: b_global = 42" +gdb_test "display c_global" "3: c_global = 43" + +if { [gdb_start_cmd] < 0 } { + fail "Can't run to main (2)" + return 0 +} + +gdb_test "" "3: c_global = 43\\r\\n2: b_global = 42\\r\\n1: a_global = 41" "after rerun" + +# Now rebuild the library without b_global +if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} \ + "$lib_flags additional_flags=-DNO_B_GLOBAL"] != ""} { + fail "Can't rebuild $binfile_lib" +} + +if { [gdb_start_cmd] < 0 } { + fail "Can't run to main (3)" + return 0 +} + +gdb_test "" "3: c_global = 43\\r\\nwarning: .*b_global.*\\r\\n1: a_global = 41" "after rerun" + +# Now verify that displays which are not in the shared library +# are not cleared permaturely. + +gdb_test "break [gdb_get_line_number "break here" ${testfile}.c]" \ + ".*Breakpoint.* at .*" + +gdb_test "continue" +gdb_test "display main_global" "4: main_global = 44" +gdb_test "display a_local" "5: a_local = 45" +gdb_test "display a_static" "6: a_static = 46" + +if { [gdb_start_cmd] < 0 } { + fail "Can't run to main (4)" + return 0 +} + +gdb_test "" "6: a_static = 46\\r\\n4: main_global = 44\\r\\n.*" +gdb_test "break [gdb_get_line_number "break here" ${testfile}.c]" \ + ".*Breakpoint.* at .*" +gdb_test "continue" "6: a_static = 46\\r\\n5: a_local = 45\\r\\n4: main_global = 44\\r\\n.*" + +gdb_exit + +return 0 + + -- 2.30.2