gdb/
Code reshuffle. * frame.h (struct frame_arg): New definition. (read_frame_arg): New declaration. * mi/mi-cmd-stack.c (list_arg_or_local): New functiom from ... (list_args_or_locals): ... the code here. New variable arg, call read_frame_arg and list_arg_or_local with it. Unify the PRINT_SIMPLE_VALUES and PRINT_ALL_VALUES cases. Call xfree for arg.error. * stack.c (print_frame_arg): New functiom from the code of print_frame_args. (read_frame_arg): New function. (print_frame_args): Remove variable val. New variable arg, call read_frame_arg and print_frame_arg with it. Call xfree for arg.error.
This commit is contained in:
parent
2d6c5dc2c7
commit
93d86cefdf
@ -1,3 +1,19 @@
|
||||
2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Code reshuffle.
|
||||
* frame.h (struct frame_arg): New definition.
|
||||
(read_frame_arg): New declaration.
|
||||
* mi/mi-cmd-stack.c (list_arg_or_local): New functiom from ...
|
||||
(list_args_or_locals): ... the code here. New variable arg, call
|
||||
read_frame_arg and list_arg_or_local with it. Unify the
|
||||
PRINT_SIMPLE_VALUES and PRINT_ALL_VALUES cases. Call xfree for
|
||||
arg.error.
|
||||
* stack.c (print_frame_arg): New functiom from the code of
|
||||
print_frame_args.
|
||||
(read_frame_arg): New function.
|
||||
(print_frame_args): Remove variable val. New variable arg, call
|
||||
read_frame_arg and print_frame_arg with it. Call xfree for arg.error.
|
||||
|
||||
2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Protect entry values against self tail calls.
|
||||
|
20
gdb/frame.h
20
gdb/frame.h
@ -711,6 +711,26 @@ extern int frame_register_read (struct frame_info *frame, int regnum,
|
||||
gdb_byte *buf);
|
||||
|
||||
/* From stack.c. */
|
||||
|
||||
/* Inferior function parameter value read in from a frame. */
|
||||
|
||||
struct frame_arg
|
||||
{
|
||||
/* Symbol for this parameter used for example for its name. */
|
||||
struct symbol *sym;
|
||||
|
||||
/* Value of the parameter. It is NULL if ERROR is not NULL; if both VAL and
|
||||
ERROR are NULL this parameter's value should not be printed. */
|
||||
struct value *val;
|
||||
|
||||
/* String containing the error message, it is more usually NULL indicating no
|
||||
error occured reading this parameter. */
|
||||
char *error;
|
||||
};
|
||||
|
||||
extern void read_frame_arg (struct symbol *sym, struct frame_info *frame,
|
||||
struct frame_arg *argp);
|
||||
|
||||
extern void args_info (char *, int);
|
||||
|
||||
extern void locals_info (char *, int);
|
||||
|
@ -236,6 +236,72 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
|
||||
list_args_or_locals (all, parse_print_values (argv[0]), frame);
|
||||
}
|
||||
|
||||
/* Print single local or argument. ARG must be already read in. For WHAT and
|
||||
VALUES see list_args_or_locals.
|
||||
|
||||
Errors are printed as if they would be the parameter value. Use zeroed ARG
|
||||
iff it should not be printed accoring to VALUES. */
|
||||
|
||||
static void
|
||||
list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
|
||||
enum print_values values)
|
||||
{
|
||||
struct cleanup *cleanup_tuple = NULL;
|
||||
struct ui_out *uiout = current_uiout;
|
||||
struct ui_stream *stb = ui_out_stream_new (uiout);
|
||||
|
||||
gdb_assert (!arg->val || !arg->error);
|
||||
gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
|
||||
&& arg->error == NULL)
|
||||
|| values == PRINT_SIMPLE_VALUES
|
||||
|| (values == PRINT_ALL_VALUES
|
||||
&& (arg->val != NULL || arg->error != NULL)));
|
||||
|
||||
if (values != PRINT_NO_VALUES || what == all)
|
||||
cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
|
||||
|
||||
ui_out_field_string (uiout, "name", SYMBOL_PRINT_NAME (arg->sym));
|
||||
|
||||
if (what == all && SYMBOL_IS_ARGUMENT (arg->sym))
|
||||
ui_out_field_int (uiout, "arg", 1);
|
||||
|
||||
if (values == PRINT_SIMPLE_VALUES)
|
||||
{
|
||||
check_typedef (arg->sym->type);
|
||||
type_print (arg->sym->type, "", stb->stream, -1);
|
||||
ui_out_field_stream (uiout, "type", stb);
|
||||
}
|
||||
|
||||
if (arg->val || arg->error)
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
if (arg->error)
|
||||
except.message = arg->error;
|
||||
else
|
||||
{
|
||||
/* TRY_CATCH has two statements, wrap it in a block. */
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
get_raw_print_options (&opts);
|
||||
opts.deref_ref = 1;
|
||||
common_val_print (arg->val, stb->stream, 0, &opts,
|
||||
language_def (SYMBOL_LANGUAGE (arg->sym)));
|
||||
}
|
||||
}
|
||||
if (except.message)
|
||||
fprintf_filtered (stb->stream, _("<error reading variable: %s>"),
|
||||
except.message);
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
}
|
||||
|
||||
ui_out_stream_delete (stb);
|
||||
if (values != PRINT_NO_VALUES || what == all)
|
||||
do_cleanups (cleanup_tuple);
|
||||
}
|
||||
|
||||
/* Print a list of the locals or the arguments for the currently
|
||||
selected frame. If the argument passed is 0, printonly the names
|
||||
@ -313,16 +379,8 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
|
||||
}
|
||||
if (print_me)
|
||||
{
|
||||
struct cleanup *cleanup_tuple = NULL;
|
||||
struct symbol *sym2;
|
||||
struct value *val;
|
||||
|
||||
if (values != PRINT_NO_VALUES || what == all)
|
||||
cleanup_tuple =
|
||||
make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
|
||||
ui_out_field_string (uiout, "name", SYMBOL_PRINT_NAME (sym));
|
||||
if (what == all && SYMBOL_IS_ARGUMENT (sym))
|
||||
ui_out_field_int (uiout, "arg", 1);
|
||||
struct frame_arg arg;
|
||||
|
||||
if (SYMBOL_IS_ARGUMENT (sym))
|
||||
sym2 = lookup_symbol (SYMBOL_NATURAL_NAME (sym),
|
||||
@ -330,64 +388,26 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
|
||||
(int *) NULL);
|
||||
else
|
||||
sym2 = sym;
|
||||
|
||||
memset (&arg, 0, sizeof (arg));
|
||||
arg.sym = sym2;
|
||||
|
||||
switch (values)
|
||||
{
|
||||
case PRINT_SIMPLE_VALUES:
|
||||
type = check_typedef (sym2->type);
|
||||
type_print (sym2->type, "", stb->stream, -1);
|
||||
ui_out_field_stream (uiout, "type", stb);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_ARRAY
|
||||
&& TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
val = read_var_value (sym2, fi);
|
||||
get_raw_print_options (&opts);
|
||||
opts.deref_ref = 1;
|
||||
common_val_print
|
||||
(val, stb->stream, 0, &opts,
|
||||
language_def (SYMBOL_LANGUAGE (sym2)));
|
||||
}
|
||||
if (except.reason < 0)
|
||||
fprintf_filtered (stb->stream,
|
||||
_("<error reading variable: %s>"),
|
||||
except.message);
|
||||
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
}
|
||||
break;
|
||||
case PRINT_ALL_VALUES:
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
val = read_var_value (sym2, fi);
|
||||
get_raw_print_options (&opts);
|
||||
opts.deref_ref = 1;
|
||||
common_val_print
|
||||
(val, stb->stream, 0, &opts,
|
||||
language_def (SYMBOL_LANGUAGE (sym2)));
|
||||
}
|
||||
if (except.reason < 0)
|
||||
fprintf_filtered (stb->stream,
|
||||
_("<error reading variable: %s>"),
|
||||
except.message);
|
||||
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
}
|
||||
read_frame_arg (sym2, fi, &arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (values != PRINT_NO_VALUES || what == all)
|
||||
do_cleanups (cleanup_tuple);
|
||||
list_arg_or_local (&arg, what, values);
|
||||
xfree (arg.error);
|
||||
}
|
||||
}
|
||||
if (BLOCK_FUNCTION (block))
|
||||
|
176
gdb/stack.c
176
gdb/stack.c
@ -162,6 +162,113 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num,
|
||||
}
|
||||
}
|
||||
|
||||
/* Print single argument of inferior function. ARG must be already
|
||||
read in.
|
||||
|
||||
Errors are printed as if they would be the parameter value. Use zeroed ARG
|
||||
iff it should not be printed accoring to user settings. */
|
||||
|
||||
static void
|
||||
print_frame_arg (const struct frame_arg *arg)
|
||||
{
|
||||
struct ui_out *uiout = current_uiout;
|
||||
volatile struct gdb_exception except;
|
||||
struct cleanup *old_chain;
|
||||
struct ui_stream *stb;
|
||||
|
||||
stb = ui_out_stream_new (uiout);
|
||||
old_chain = make_cleanup_ui_out_stream_delete (stb);
|
||||
|
||||
gdb_assert (!arg->val || !arg->error);
|
||||
|
||||
annotate_arg_begin ();
|
||||
|
||||
make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
|
||||
fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (arg->sym),
|
||||
SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI);
|
||||
ui_out_field_stream (uiout, "name", stb);
|
||||
annotate_arg_name_end ();
|
||||
ui_out_text (uiout, "=");
|
||||
|
||||
if (!arg->val && !arg->error)
|
||||
ui_out_text (uiout, "...");
|
||||
else
|
||||
{
|
||||
if (arg->error)
|
||||
except.message = arg->error;
|
||||
else
|
||||
{
|
||||
/* TRY_CATCH has two statements, wrap it in a block. */
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
const struct language_defn *language;
|
||||
struct value_print_options opts;
|
||||
|
||||
/* Avoid value_print because it will deref ref parameters. We
|
||||
just want to print their addresses. Print ??? for args whose
|
||||
address we do not know. We pass 2 as "recurse" to val_print
|
||||
because our standard indentation here is 4 spaces, and
|
||||
val_print indents 2 for each recurse. */
|
||||
|
||||
annotate_arg_value (value_type (arg->val));
|
||||
|
||||
/* Use the appropriate language to display our symbol, unless the
|
||||
user forced the language to a specific language. */
|
||||
if (language_mode == language_mode_auto)
|
||||
language = language_def (SYMBOL_LANGUAGE (arg->sym));
|
||||
else
|
||||
language = current_language;
|
||||
|
||||
get_raw_print_options (&opts);
|
||||
opts.deref_ref = 0;
|
||||
|
||||
/* True in "summary" mode, false otherwise. */
|
||||
opts.summary = !strcmp (print_frame_arguments, "scalars");
|
||||
|
||||
common_val_print (arg->val, stb->stream, 2, &opts, language);
|
||||
}
|
||||
}
|
||||
if (except.message)
|
||||
fprintf_filtered (stb->stream, _("<error reading variable: %s>"),
|
||||
except.message);
|
||||
}
|
||||
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
|
||||
/* Aleo invoke ui_out_tuple_end. */
|
||||
do_cleanups (old_chain);
|
||||
|
||||
annotate_arg_end ();
|
||||
}
|
||||
|
||||
/* Read in inferior function parameter SYM at FRAME into ARGP. Caller is
|
||||
responsible for xfree of ARGP->ERROR. This function never throws an
|
||||
exception. */
|
||||
|
||||
void
|
||||
read_frame_arg (struct symbol *sym, struct frame_info *frame,
|
||||
struct frame_arg *argp)
|
||||
{
|
||||
struct value *val = NULL;
|
||||
char *val_error = NULL;
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
val = read_var_value (sym, frame);
|
||||
}
|
||||
if (!val)
|
||||
{
|
||||
val_error = alloca (strlen (except.message) + 1);
|
||||
strcpy (val_error, except.message);
|
||||
}
|
||||
|
||||
argp->sym = sym;
|
||||
argp->val = val;
|
||||
argp->error = val_error ? xstrdup (val_error) : NULL;
|
||||
}
|
||||
|
||||
/* Print the arguments of frame FRAME on STREAM, given the function
|
||||
FUNC running in that frame (as a symbol), where NUM is the number
|
||||
of arguments according to the stack frame (or -1 if the number of
|
||||
@ -198,10 +305,11 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
|
||||
struct block *b = SYMBOL_BLOCK_VALUE (func);
|
||||
struct dict_iterator iter;
|
||||
struct symbol *sym;
|
||||
struct value *val;
|
||||
|
||||
ALL_BLOCK_SYMBOLS (b, iter, sym)
|
||||
{
|
||||
struct frame_arg arg;
|
||||
|
||||
QUIT;
|
||||
|
||||
/* Keep track of the highest stack argument offset seen, and
|
||||
@ -314,65 +422,17 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
|
||||
ui_out_text (uiout, ", ");
|
||||
ui_out_wrap_hint (uiout, " ");
|
||||
|
||||
annotate_arg_begin ();
|
||||
if (!print_args)
|
||||
{
|
||||
memset (&arg, 0, sizeof (arg));
|
||||
arg.sym = sym;
|
||||
}
|
||||
else
|
||||
read_frame_arg (sym, frame, &arg);
|
||||
|
||||
list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
|
||||
fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (sym),
|
||||
SYMBOL_LANGUAGE (sym),
|
||||
DMGL_PARAMS | DMGL_ANSI);
|
||||
ui_out_field_stream (uiout, "name", stb);
|
||||
annotate_arg_name_end ();
|
||||
ui_out_text (uiout, "=");
|
||||
print_frame_arg (&arg);
|
||||
|
||||
if (print_args)
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
const struct language_defn *language;
|
||||
struct value_print_options opts;
|
||||
|
||||
/* Avoid value_print because it will deref ref parameters.
|
||||
We just want to print their addresses. Print ??? for
|
||||
args whose address we do not know. We pass 2 as
|
||||
"recurse" to val_print because our standard indentation
|
||||
here is 4 spaces, and val_print indents 2 for each
|
||||
recurse. */
|
||||
val = read_var_value (sym, frame);
|
||||
|
||||
annotate_arg_value (value_type (val));
|
||||
|
||||
/* Use the appropriate language to display our symbol,
|
||||
unless the user forced the language to a specific
|
||||
language. */
|
||||
if (language_mode == language_mode_auto)
|
||||
language = language_def (SYMBOL_LANGUAGE (sym));
|
||||
else
|
||||
language = current_language;
|
||||
|
||||
get_raw_print_options (&opts);
|
||||
opts.deref_ref = 0;
|
||||
opts.summary = summary;
|
||||
common_val_print (val, stb->stream, 2, &opts, language);
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
}
|
||||
if (except.reason < 0)
|
||||
{
|
||||
fprintf_filtered (stb->stream,
|
||||
_("<error reading variable: %s>"),
|
||||
except.message);
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
}
|
||||
}
|
||||
else
|
||||
ui_out_text (uiout, "...");
|
||||
|
||||
|
||||
/* Invoke ui_out_tuple_end. */
|
||||
do_cleanups (list_chain);
|
||||
|
||||
annotate_arg_end ();
|
||||
xfree (arg.error);
|
||||
|
||||
first = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user