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:
Jan Kratochvil 2011-10-09 19:30:25 +00:00
parent 2d6c5dc2c7
commit 93d86cefdf
4 changed files with 229 additions and 113 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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))

View File

@ -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;
}