This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [patch] Fix dangling displays in separate debug
On Monday 19 April 2010 15:25:03, Jan Kratochvil wrote:
> On Sun, 11 Apr 2010 03:27:35 +0200, Pedro Alves wrote:
> > On Friday 09 April 2010 21:00:46, Jan Kratochvil wrote:
> > > I was convinced due to some invalid reasons solib->objfile cannot be NULL.
> >
> > There's an easy way to see that state:
> >
> > (gdb) nosharedlibrary
> > (gdb) info sharedlibrary
>
> Nice reproducer, thanks.
>
>
> > Doesn't this make it so that only the separate debug info
> > case is exercised, and, it stops exercising the non-separate
> > debug info case? I think we should instead be running the
> > relevant parts the test twice instead?
>
> I was asking about it before. Therefore reworked it as promised.
>
> On Sat, 03 Apr 2010 11:55:58 +0200, Jan Kratochvil wrote:
> # One may only address that gdb.base/solib-display.exp was testing symbol
> # in-objfile while now it tests only symbol in-sepdebug-objfile and no longer
> # the in-objfile case. I find the in-sepdebug-objfile as a superset of
> # in-objfile test but I can rework it if anyones addresses this test change.
Thanks.
>
>
> > > +if {[gdb_gnu_strip_debug $binfile_lib] != 0} {
> > > + fail $test
> >
> > Not all systems support this, so this should be `unsupported' instead.
>
> You are right, found at least one such target - i386-msdos:
> + ./binutils/objcopy --add-gnu-debuglink=1.o-debug 1.o-stripped 1.o-dest
> BFD: 1.o-dest: can not represent section `.gnu_debuglink' in a.out object file format
> ./binutils/objcopy:1.o-dest: cannot fill debug link section `1.o-debug': Nonrepresentable section on output
>
>
> With the extended requirements I rather pushed the former patch posted at:
> Re: [patch 3/8] Types GC [display_uses_solib_p to exp_iterate]
> http://sourceware.org/ml/gdb-patches/2009-07/msg00054.html
Yikes. I don't understand what is the extended requirement, but anyway,
I'll take a look.
>
> There was forgotten handling of TYPE_INSTANCE, UNOP_DYNAMIC_CAST and
> UNOP_REINTERPRET_CAST. Reduced it only for the current applicable use case;
> to be extended one day for the types garbage collector on its resubmit.
>
>
> No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu.
>
>
> Thanks,
> Jan
>
>
> gdb/
> 2010-04-19 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> Fix crashes on dangling display expressions.
> * ada-lang.c (ada_operator_check): New function.
> (ada_exp_descriptor): Fill-in the field operator_check.
> * c-lang.c (exp_descriptor_c): Fill-in the field operator_check.
> * jv-lang.c (exp_descriptor_java): Likewise.
> * m2-lang.c (exp_descriptor_modula2): Likewise.
> * scm-lang.c (exp_descriptor_scm): Likewise.
> * parse.c (exp_descriptor_standard): Likewise.
> (operator_check_standard): New function.
> (exp_iterate, exp_uses_objfile_iter, exp_uses_objfile): New functions.
> * parser-defs.h (struct exp_descriptor): New field operator_check.
> (operator_check_standard, exp_uses_objfile): New declarations.
> * printcmd.c: Remove the inclusion of solib.h.
> (display_uses_solib_p): Remove the function.
> (clear_dangling_display_expressions): Call lookup_objfile_from_block
> and exp_uses_objfile instead of display_uses_solib_p.
> * solist.h (struct so_list) <objfile>: New comment.
> * symtab.c (lookup_objfile_from_block): Remove the static qualifier.
> * symtab.h (lookup_objfile_from_block): New declaration.
> (struct general_symbol_info) <obj_section>: Extend the comment.
>
> gdb/testsuite/
> 2010-04-19 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> Fix crashes on dangling display expressions.
> * gdb.base/solib-display.exp: Call gdb_gnu_strip_debug if LIBSEPDEBUG
> is SEP.
> (lib_flags): Remove the "debug" keyword.
> (libsepdebug): New variable for iterating new loop.
> (save_pf_prefix): New variable wrapping the loop.
> (sep_lib_flags): New variable derived from LIB_FLAGS. Use it.
> * lib/gdb.exp (gdb_gnu_strip_debug): Document the return code.
>
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -10868,6 +10868,36 @@ ada_operator_length (struct expression *exp, int pc, int *oplenp, int *argsp)
> }
> }
>
> +/* Implementation of the exp_descriptor method operator_check. */
> +
> +static int
> +ada_operator_check (struct expression *exp, int pos,
> + int (*objfile_func) (struct objfile *objfile, void *data),
> + void *data)
> +{
> + const union exp_element *const elts = exp->elts;
> + struct type *type = NULL;
> +
> + switch (elts[pos].opcode)
> + {
> + case UNOP_IN_RANGE:
> + case UNOP_QUAL:
> + type = elts[pos + 1].type;
> + break;
> +
> + default:
> + return operator_check_standard (exp, pos, objfile_func, data);
> + }
> +
> + /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */
> +
> + if (type && TYPE_OBJFILE (type)
> + && (*objfile_func) (TYPE_OBJFILE (type), data))
> + return 1;
> +
> + return 0;
> +}
> +
> static char *
> ada_op_name (enum exp_opcode opcode)
> {
> @@ -11256,6 +11286,7 @@ parse (void)
> static const struct exp_descriptor ada_exp_descriptor = {
> ada_print_subexp,
> ada_operator_length,
> + ada_operator_check,
> ada_op_name,
> ada_dump_subexp_body,
> ada_evaluate_subexp
> --- a/gdb/c-lang.c
> +++ b/gdb/c-lang.c
> @@ -1139,6 +1139,7 @@ static const struct exp_descriptor exp_descriptor_c =
> {
> print_subexp_standard,
> operator_length_standard,
> + operator_check_standard,
> op_name_standard,
> dump_subexp_body_standard,
> evaluate_subexp_c
> --- a/gdb/jv-lang.c
> +++ b/gdb/jv-lang.c
> @@ -1162,6 +1162,7 @@ const struct exp_descriptor exp_descriptor_java =
> {
> print_subexp_standard,
> operator_length_standard,
> + operator_check_standard,
> op_name_standard,
> dump_subexp_body_standard,
> evaluate_subexp_java
> --- a/gdb/m2-lang.c
> +++ b/gdb/m2-lang.c
> @@ -356,6 +356,7 @@ const struct exp_descriptor exp_descriptor_modula2 =
> {
> print_subexp_standard,
> operator_length_standard,
> + operator_check_standard,
> op_name_standard,
> dump_subexp_body_standard,
> evaluate_subexp_modula2
> --- a/gdb/parse.c
> +++ b/gdb/parse.c
> @@ -62,6 +62,7 @@ const struct exp_descriptor exp_descriptor_standard =
> {
> print_subexp_standard,
> operator_length_standard,
> + operator_check_standard,
> op_name_standard,
> dump_subexp_body_standard,
> evaluate_subexp_standard
> @@ -1373,6 +1374,150 @@ parser_fprintf (FILE *x, const char *y, ...)
> va_end (args);
> }
>
> +/* Implementation of the exp_descriptor method operator_check. */
> +
> +int
> +operator_check_standard (struct expression *exp, int pos,
> + int (*objfile_func) (struct objfile *objfile,
> + void *data),
> + void *data)
> +{
> + const union exp_element *const elts = exp->elts;
> + struct type *type = NULL;
> + struct objfile *objfile = NULL;
> +
> + /* Extended operators should have been already handled by exp_descriptor
> + iterate method of its specific language. */
> + gdb_assert (elts[pos].opcode < OP_EXTENDED0);
> +
> + /* Track the callers of write_exp_elt_type for this table. */
> +
> + switch (elts[pos].opcode)
> + {
> + case BINOP_VAL:
> + case OP_COMPLEX:
> + case OP_DECFLOAT:
> + case OP_DOUBLE:
> + case OP_LONG:
> + case OP_SCOPE:
> + case OP_TYPE:
> + case UNOP_CAST:
> + case UNOP_DYNAMIC_CAST:
> + case UNOP_REINTERPRET_CAST:
> + case UNOP_MAX:
> + case UNOP_MEMVAL:
> + case UNOP_MIN:
> + type = elts[pos + 1].type;
> + break;
> +
> + case TYPE_INSTANCE:
> + {
> + LONGEST arg, nargs = elts[pos + 1].longconst;
> +
> + for (arg = 0; arg < nargs; arg++)
> + {
> + struct type *type = elts[pos + 2 + arg].type;
> + struct objfile *objfile = TYPE_OBJFILE (type);
> +
> + if (objfile && (*objfile_func) (objfile, data))
> + return 1;
> + }
> + }
> + break;
> +
> + case UNOP_MEMVAL_TLS:
> + objfile = elts[pos + 1].objfile;
> + type = elts[pos + 2].type;
> + break;
> +
> + case OP_VAR_VALUE:
> + {
> + const struct block *const block = elts[pos + 1].block;
> + const struct symbol *const symbol = elts[pos + 2].symbol;
> +
> + /* Check objfile where the variable itself is placed.
> + SYMBOL_OBJ_SECTION (symbol) may be NULL. */
> + if ((*objfile_func) (SYMBOL_SYMTAB (symbol)->objfile, data))
> + return 1;
> +
> + /* Check objfile where is placed the code touching the variable. */
> + objfile = lookup_objfile_from_block (block);
> +
> + type = SYMBOL_TYPE (symbol);
> + }
> + break;
> + }
> +
> + /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */
> +
> + if (type && TYPE_OBJFILE (type)
> + && (*objfile_func) (TYPE_OBJFILE (type), data))
> + return 1;
> + if (objfile && (*objfile_func) (objfile, data))
> + return 1;
> +
> + return 0;
> +}
> +
> +/* Call OBJFILE_FUNC for any TYPE and OBJFILE found being referenced by EXP.
> + The functions are never called with NULL OBJFILE. Functions get passed an
> + arbitrary caller supplied DATA pointer. If any of the functions returns
> + non-zero value then (any other) non-zero value is immediately returned to
> + the caller. Otherwise zero is returned after iterating through whole EXP.
> + */
> +
> +static int
> +exp_iterate (struct expression *exp,
> + int (*objfile_func) (struct objfile *objfile, void *data),
> + void *data)
> +{
> + int endpos;
> + const union exp_element *const elts = exp->elts;
> +
> + for (endpos = exp->nelts; endpos > 0; )
> + {
> + int pos, args, oplen = 0;
> +
> + exp->language_defn->la_exp_desc->operator_length (exp, endpos,
> + &oplen, &args);
> + gdb_assert (oplen > 0);
> +
> + pos = endpos - oplen;
> + if (exp->language_defn->la_exp_desc->operator_check (exp, pos,
> + objfile_func, data))
> + return 1;
> +
> + endpos = pos;
> + }
> +
> + return 0;
> +}
> +
> +/* Helper for exp_uses_objfile. */
> +
> +static int
> +exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp)
> +{
> + struct objfile *objfile = objfile_voidp;
> +
> + if (exp_objfile->separate_debug_objfile_backlink)
> + exp_objfile = exp_objfile->separate_debug_objfile_backlink;
> +
> + return exp_objfile == objfile;
> +}
> +
Most things look good. This is get's a little blury though. You have
this nice iterator that can determine if a given expression involved an
obfile, so, you could accurately now disable a "display" when an objfile
is unloaded from gdb --- _any_ objfile, even in principly when you
do "file" to unload the main exec's symbols, say, so that _all_ cases
of dangling displays would be cured. Still, you only call this when an
solib is unloaded. Can't we in principle be unloading a separate debug info
objfile, but still have the main one loaded, hence OBJFILE_VOIDP could be
a separate debug objfile? An expression could in principle be using
symbols from either, why would we care for that here? Doesn't this just
beg for a new `objfile_unloaded' observer (called from, say free_objfile)?
Anyway, I'm not going to require you do that for this patch, your patch
looks good already. Just dumping my thoughts, on what looks like an
opportunity to keep the solib/objfile concepts cleanly separate, and get
rid of all the objfile backlinking here.
> +/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE
> + is unloaded), otherwise return 0. OBJFILE must not be a separate debug info
> + file. */
> +
> +int
> +exp_uses_objfile (struct expression *exp, struct objfile *objfile)
> +{
> + gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
> +
> + return exp_iterate (exp, exp_uses_objfile_iter, objfile);
> +}
> +
> void
> _initialize_parse (void)
> {
> --- a/gdb/parser-defs.h
> +++ b/gdb/parser-defs.h
> @@ -192,6 +192,11 @@ extern void operator_length (struct expression *, int, int *, int *);
>
> extern void operator_length_standard (struct expression *, int, int *, int *);
>
> +extern int operator_check_standard (struct expression *exp, int pos,
> + int (*objfile_func)
> + (struct objfile *objfile, void *data),
> + void *data);
> +
> extern char *op_name_standard (enum exp_opcode);
>
> extern struct type *follow_types (struct type *);
> @@ -270,6 +275,19 @@ struct exp_descriptor
> the number of subexpressions it takes. */
> void (*operator_length) (struct expression*, int, int*, int *);
>
> + /* Call TYPE_FUNC and OBJFILE_FUNC for any TYPE and OBJFILE found being
> + referenced by the single operator of EXP at position POS. Operator
> + parameters are located at positive (POS + number) offsets in EXP.
> + The functions should never be called with NULL TYPE or NULL OBJFILE.
> + Functions should get passed an arbitrary caller supplied DATA pointer.
> + If any of the functions returns non-zero value then (any other) non-zero
> + value should be immediately returned to the caller. Otherwise zero
> + should be returned. */
> + int (*operator_check) (struct expression *exp, int pos,
> + int (*objfile_func) (struct objfile *objfile,
> + void *data),
> + void *data);
> +
> /* Name of this operator for dumping purposes. */
> char *(*op_name) (enum exp_opcode);
>
> @@ -302,4 +320,6 @@ extern void print_subexp_standard (struct expression *, int *,
>
> extern void parser_fprintf (FILE *, const char *, ...) ATTR_FORMAT (printf, 2 ,3);
>
> +extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile);
> +
> #endif /* PARSER_DEFS_H */
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -46,7 +46,6 @@
> #include "exceptions.h"
> #include "observer.h"
> #include "solist.h"
> -#include "solib.h"
> #include "parser-defs.h"
> #include "charset.h"
> #include "arch-utils.h"
> @@ -1859,51 +1858,6 @@ disable_display_command (char *args, int from_tty)
> }
> }
>
> -/* 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 endpos;
> - struct expression *const exp = d->exp;
> - const union exp_element *const elts = exp->elts;
> -
> - if (d->block != NULL
> - && d->pspace == solib->pspace
> - && solib_contains_address_p (solib, d->block->startaddr))
> - return 1;
Is there any `solib_contains_address_p' check left after the patch?
What about displays that don't involve symbols, like:
`display *0xaddr_in_solib'.
They'll probably still disable themselves when memory reading
fails, but, will we now see an ugly error, or something?
> -
> - for (endpos = exp->nelts; endpos > 0; )
> - {
> - int i, args, oplen = 0;
> -
> - exp->language_defn->la_exp_desc->operator_length (exp, endpos,
> - &oplen, &args);
> - gdb_assert (oplen > 0);
> -
> - i = endpos - oplen;
> - 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;
> -
> - if (block != NULL
> - && solib_contains_address_p (solib,
> - block->startaddr))
> - return 1;
> -
> - /* SYMBOL_OBJ_SECTION (symbol) may be NULL. */
> - if (SYMBOL_SYMTAB (symbol)->objfile == solib->objfile)
> - return 1;
> - }
> - endpos -= 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
> @@ -1915,17 +1869,28 @@ display_uses_solib_p (const struct display *d,
> static void
> clear_dangling_display_expressions (struct so_list *solib)
> {
> + struct objfile *objfile = solib->objfile;
> struct display *d;
> - struct objfile *objfile = NULL;
>
> - for (d = display_chain; d; d = d->next)
> + /* With no symbol file we cannot have a block or expression from it. */
> + if (objfile == NULL)
> + return;
> + if (objfile->separate_debug_objfile_backlink)
> + objfile = objfile->separate_debug_objfile_backlink;
> + gdb_assert (objfile->pspace == solib->pspace);
> +
> + for (d = display_chain; d != NULL; d = d->next)
> {
> - if (d->exp && display_uses_solib_p (d, solib))
> - {
> - xfree (d->exp);
> - d->exp = NULL;
> - d->block = NULL;
> - }
> + if (d->pspace != solib->pspace)
> + continue;
> +
> + if (lookup_objfile_from_block (d->block) == objfile
> + || (d->exp && exp_uses_objfile (d->exp, objfile)))
> + {
> + xfree (d->exp);
> + d->exp = NULL;
> + d->block = NULL;
> + }
> }
> }
>
> --- a/gdb/scm-lang.c
> +++ b/gdb/scm-lang.c
> @@ -231,6 +231,7 @@ const struct exp_descriptor exp_descriptor_scm =
> {
> print_subexp_standard,
> operator_length_standard,
> + operator_check_standard,
> op_name_standard,
> dump_subexp_body_standard,
> evaluate_exp
> --- a/gdb/solist.h
> +++ b/gdb/solist.h
> @@ -63,7 +63,12 @@ struct so_list
>
> bfd *abfd;
> char symbols_loaded; /* flag: symbols read in yet? */
> - struct objfile *objfile; /* objfile for loaded lib */
> +
> + /* objfile with symbols for a loaded library. Target memory is read from
> + ABFD. OBJFILE may be NULL either before symbols have been loaded, if
> + the file cannot be found or after the command "nosharedlibrary". */
> + struct objfile *objfile;
> +
> struct target_section *sections;
> struct target_section *sections_end;
>
> --- a/gdb/symtab.c
> +++ b/gdb/symtab.c
> @@ -1150,7 +1150,7 @@ lookup_symbol_aux_local (const char *name, const struct block *block,
>
> /* Look up OBJFILE to BLOCK. */
>
> -static struct objfile *
> +struct objfile *
> lookup_objfile_from_block (const struct block *block)
> {
> struct objfile *obj;
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -148,7 +148,7 @@ struct general_symbol_info
>
> short section;
>
> - /* The section associated with this symbol. */
> + /* The section associated with this symbol. It can be NULL. */
>
> struct obj_section *obj_section;
> };
> @@ -1206,4 +1206,6 @@ int producer_is_realview (const char *producer);
> void fixup_section (struct general_symbol_info *ginfo,
> CORE_ADDR addr, struct objfile *objfile);
>
> +struct objfile *lookup_objfile_from_block (const struct block *block);
> +
> #endif /* !defined(SYMTAB_H) */
> --- a/gdb/testsuite/gdb.base/solib-display.exp
> +++ b/gdb/testsuite/gdb.base/solib-display.exp
> @@ -36,7 +36,7 @@ if { [skip_shlib_tests] || [is_remote target] } {
> set libname "solib-display-lib"
> set srcfile_lib ${srcdir}/${subdir}/${libname}.c
> set binfile_lib ${objdir}/${subdir}/${libname}.so
> -set lib_flags [list debug]
> +set lib_flags {}
> # Binary file.
> set testfile "solib-display-main"
> set srcfile ${srcdir}/${subdir}/${testfile}.c
> @@ -48,60 +48,92 @@ 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
> +set save_pf_prefix $pf_prefix
> +# SEP must be last for the possible `unsupported' error path.
> +foreach libsepdebug {NO IN SEP} {
Could you please add $libsepdebug or something of the sorts
to each test within the loop, so that when we analyise the logs we
can distinguish FAIL/PASSes for each iteration?
> +
> + set pf_prefix $save_pf_prefix
> + lappend pf_prefix "$libsepdebug:"
> +
> + set sep_lib_flags $lib_flags
> + if {$libsepdebug != "NO"} {
> + lappend sep_lib_flags {debug}
> + }
> + if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $sep_lib_flags] != ""
> + || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
> + untested "Could not compile $binfile_lib or $binfile."
> + return -1
> + }
> +
> + if {$libsepdebug == "SEP"} {
> + if {[gdb_gnu_strip_debug $binfile_lib] != 0} {
> + unsupported "Could not split debug of $binfile_lib."
> + return
> + } else {
> + pass "split solib"
> + }
> + }
> +
> + clean_restart $executable
> +
> + 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)"
> + continue
> + }
> +
> + 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} \
> + "$sep_lib_flags additional_flags=-DNO_B_GLOBAL"] != ""} {
> + fail "Can't rebuild $binfile_lib"
> + }
> +
> + if {$libsepdebug == "SEP"} {
> + set test "split solib second time"
> + if {[gdb_gnu_strip_debug $binfile_lib] != 0} {
> + fail $test
> + continue
> + } else {
> + pass $test
> + }
> + }
> +
> + if { [gdb_start_cmd] < 0 } {
> + fail "Can't run to main (3)"
> + continue
> + }
> +
> + gdb_test "" "3: c_global = 43\\r\\nwarning: .*b_global.*\\r\\n1: a_global = 41" "after rerun (2)"
> +
> + # 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)"
> + continue
> + }
> +
> + 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.*"
> }
> -
> -clean_restart ${executable}
> -
> -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.*"
> +set pf_prefix $save_pf_prefix
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -2896,6 +2896,9 @@ proc build_id_debug_filename_get { exec } {
> # Create stripped files for DEST, replacing it. If ARGS is passed, it is a
> # list of optional flags. The only currently supported flag is no-main,
> # which removes the symbol entry for main from the separate debug file.
> +#
> +# Function returns zero on success. Function will return non-zero failure code
> +# on some targets not supporting separate debug info (such as i386-msdos).
>
> proc gdb_gnu_strip_debug { dest args } {
>
>
Otherwise, looks good to me.
--
Pedro Alves