diff options
author | gdb-3.3 <gdb@fsf.org> | 1989-09-30 00:00:00 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2012-06-03 15:36:32 +0100 |
commit | 4187119d59afd156703cfcbc6be287c5085f1867 (patch) | |
tree | 8ea0d77175611df1eeec928858f629d410dd6e05 /gdb/printcmd.c | |
parent | e91b87a36830d061ef87d67be5f309e4d4ed918f (diff) | |
download | gdb-4187119d59afd156703cfcbc6be287c5085f1867.zip gdb-4187119d59afd156703cfcbc6be287c5085f1867.tar.gz gdb-4187119d59afd156703cfcbc6be287c5085f1867.tar.bz2 |
gdb-3.3
Diffstat (limited to 'gdb/printcmd.c')
-rw-r--r-- | gdb/printcmd.c | 719 |
1 files changed, 442 insertions, 277 deletions
diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 67b93a8..6a6cd34 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1,22 +1,21 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc. -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. +This file is part of GDB. -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. +GDB 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 1, or (at your option) +any later version. -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include "defs.h" @@ -70,6 +69,9 @@ void print_scalar_formatted (); /* Decode a format specification. *STRING_PTR should point to it. OFORMAT and OSIZE are used as defaults for the format and size if none are given in the format specification. + If OSIZE is zero, then the size field of the returned value + should be set only if a size is explicitly specified by the + user. The structure returned describes all the data found in the specification. In addition, *STRING_PTR is advanced past the specification and past all whitespace following it. */ @@ -83,8 +85,8 @@ decode_format (string_ptr, oformat, osize) struct format_data val; register char *p = *string_ptr; - val.format = oformat; - val.size = osize; + val.format = '?'; + val.size = '?'; val.count = 1; if (*p >= '0' && *p <= '9') @@ -120,6 +122,46 @@ decode_format (string_ptr, oformat, osize) while (*p == ' ' || *p == '\t') p++; *string_ptr = p; + /* Set defaults for format and size if not specified. */ + if (val.format == '?') + { + if (val.size == '?') + { + /* Neither has been specified. */ + val.format = oformat; + val.size = osize; + } + else + /* If a size is specified, any format makes a reasonable + default except 'i'. */ + val.format = oformat == 'i' ? 'x' : oformat; + } + else if (val.size == '?') + switch (val.format) + { + case 'a': + case 's': + /* Addresses must be words. */ + val.size = osize ? 'w' : osize; + break; + case 'f': + /* Floating point has to be word or giantword. */ + if (osize == 'w' || osize == 'g') + val.size = osize; + else + /* Default it to giantword if the last used size is not + appropriate. */ + val.size = osize ? 'g' : osize; + break; + case 'c': + /* Characters default to one byte. */ + val.size = osize ? 'b' : osize; + break; + default: + /* The default is the size most recently specified. */ + val.size = osize; + } + return val; } @@ -144,7 +186,7 @@ print_formatted (val, format, size) { case 's': next_address = VALUE_ADDRESS (val) - + value_print (value_addr (val), stdout, 0); + + value_print (value_addr (val), stdout, 0, Val_pretty_default); break; case 'i': @@ -158,7 +200,7 @@ print_formatted (val, format, size) || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION || VALUE_REPEATED (val)) - value_print (val, stdout, format); + value_print (val, stdout, format, Val_pretty_default); else print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), format, size, stdout); @@ -200,11 +242,11 @@ print_scalar_formatted (valaddr, type, format, size, stream) v1 = v2; v2 = tmp; #endif - + switch (format) { case 'x': - fprintf (stream, "0x%08x%08x", v1, v2); + fprintf_filtered (stream, "0x%08x%08x", v1, v2); break; default: error ("Output size \"g\" unimplemented for format \"%c\".", @@ -235,17 +277,17 @@ print_scalar_formatted (valaddr, type, format, size, stream) switch (size) { case 'b': - fprintf (stream, "0x%02llx", val_long); + fprintf_filtered (stream, "0x%02llx", val_long); break; case 'h': - fprintf (stream, "0x%04llx", val_long); + fprintf_filtered (stream, "0x%04llx", val_long); break; case 0: /* no size specified, like in print */ case 'w': - fprintf (stream, "0x%08llx", val_long); + fprintf_filtered (stream, "0x%08llx", val_long); break; case 'g': - fprintf (stream, "0x%16llx", val_long); + fprintf_filtered (stream, "0x%016llx", val_long); break; default: error ("Undefined output size \"%c\".", size); @@ -254,17 +296,17 @@ print_scalar_formatted (valaddr, type, format, size, stream) switch (size) { case 'b': - fprintf (stream, "0x%02x", val_long); + fprintf_filtered (stream, "0x%02x", val_long); break; case 'h': - fprintf (stream, "0x%04x", val_long); + fprintf_filtered (stream, "0x%04x", val_long); break; case 0: /* no size specified, like in print */ case 'w': - fprintf (stream, "0x%08x", val_long); + fprintf_filtered (stream, "0x%08x", val_long); break; case 'g': - fprintf (stream, "0x%16x", val_long); + fprintf_filtered (stream, "0x%o16x", val_long); break; default: error ("Undefined output size \"%c\".", size); @@ -274,29 +316,29 @@ print_scalar_formatted (valaddr, type, format, size, stream) case 'd': #ifdef LONG_LONG - fprintf (stream, "%lld", val_long); + fprintf_filtered (stream, "%lld", val_long); #else - fprintf (stream, "%d", val_long); + fprintf_filtered (stream, "%d", val_long); #endif break; case 'u': #ifdef LONG_LONG - fprintf (stream, "%llu", val_long); + fprintf_filtered (stream, "%llu", val_long); #else - fprintf (stream, "%u", val_long); + fprintf_filtered (stream, "%u", val_long); #endif break; case 'o': if (val_long) #ifdef LONG_LONG - fprintf (stream, "0%llo", val_long); + fprintf_filtered (stream, "0%llo", val_long); #else - fprintf (stream, "0%o", val_long); + fprintf_filtered (stream, "0%o", val_long); #endif else - fprintf (stream, "0"); + fprintf_filtered (stream, "0"); break; case 'a': @@ -304,7 +346,8 @@ print_scalar_formatted (valaddr, type, format, size, stream) break; case 'c': - value_print (value_from_long (builtin_type_char, val_long), stream, 0); + value_print (value_from_long (builtin_type_char, val_long), stream, 0, + Val_pretty_default); break; case 'f': @@ -312,24 +355,22 @@ print_scalar_formatted (valaddr, type, format, size, stream) type = builtin_type_float; else if (len == sizeof (double)) type = builtin_type_double; - else abort(); - #ifdef IEEE_FLOAT - if (is_nan (valaddr, len)) + if (is_nan (type, valaddr)) { - fprintf (stream, "NaN"); + fprintf_filtered (stream, "Nan"); break; } #endif { double doub; int inv; - + doub = unpack_double (type, valaddr, &inv); if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, len > 4? "%.16g": "%.6g", doub); + fprintf_filtered (stream, "Invalid float value"); + else + fprintf_filtered (stream, len > 4 ? "%.16g" : "%.6g", doub); } break; @@ -364,37 +405,24 @@ print_address (addr, stream) CORE_ADDR addr; FILE *stream; { - register int i; - struct symbol *fs; + register int i = 0; + register char *format; + register struct symbol *fs; char *name; int name_location; - fprintf (stream, "0x%x", addr); - - fs = find_pc_function (addr); - - if (!fs) - { - i = find_pc_misc_function (addr); - - if (i < 0) return; /* If nothing comes through, don't - print anything symbolic */ + i = find_pc_partial_function (addr, &name, &name_location); - name = misc_function_vector[i].name; - name_location = misc_function_vector[i].address; - } + /* If nothing comes out, don't print anything symbolic. */ + + if (i == 0) + format = "0x%x"; + else if (addr - name_location) + format = "0x%x <%s+%d>"; else - { - name = fs->name; - name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs)); - } + format = "0x%x <%s>"; - if (addr - name_location) - fprintf (stream, " <%s+%d>", - name, - addr - name_location); - else - fprintf (stream, " <%s>", name); + fprintf_filtered (stream, format, addr, name, addr - name_location); } /* Examine data at address ADDR in format FMT. @@ -449,19 +477,19 @@ do_examine (fmt, addr) while (count > 0) { print_address (next_address, stdout); - fputc (':', stdout); + printf_filtered (":"); for (i = maxelts; i > 0 && count > 0; i--, count--) { - fputc ('\t', stdout); + printf_filtered ("\t"); /* Note that print_formatted sets next_address for the next object. */ last_examine_address = next_address; last_examine_value = value_at (val_type, next_address); print_formatted (last_examine_value, format, size); } - fputc ('\n', stdout); + printf_filtered ("\n"); fflush (stdout); } } @@ -512,10 +540,10 @@ print_command (exp) val = access_value_history (0); histindex = record_latest_value (val); - if (histindex >= 0) printf ("$%d = ", histindex); + if (histindex >= 0) printf_filtered ("$%d = ", histindex); print_formatted (val, format, fmt.size); - printf ("\n"); + printf_filtered ("\n"); if (cleanup) do_cleanups (old_chain); @@ -580,7 +608,7 @@ address_info (exp) if (is_a_field_of_this) { - printf("Symbol \"%s\" is a field of the local class variable `this'\n", exp); + printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp); return; } @@ -630,6 +658,10 @@ address_info (exp) printf ("a local variable at frame offset %d", val); break; + case LOC_REF_ARG: + printf ("a reference argument at offset %d", val); + break; + case LOC_TYPEDEF: printf ("a typedef"); break; @@ -650,6 +682,7 @@ x_command (exp, from_tty) struct expression *expr; struct format_data fmt; struct cleanup *old_chain; + struct value *val; fmt.format = last_format; fmt.size = last_size; @@ -674,7 +707,13 @@ x_command (exp, from_tty) if (from_tty) *exp = 0; old_chain = make_cleanup (free_current_contents, &expr); - next_address = (CORE_ADDR) value_as_long (evaluate_expression (expr)); + val = evaluate_expression (expr); + if (last_format == 'i' + && TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_PTR + && VALUE_LVAL (val) == lval_memory) + next_address = VALUE_ADDRESS (val); + else + next_address = (CORE_ADDR) value_as_long (val); do_cleanups (old_chain); } @@ -712,9 +751,12 @@ whatis_command (exp) else val = access_value_history (0); - printf ("type = "); - type_print (VALUE_TYPE (val), "", stdout, 1); - printf ("\n"); + printf_filtered ("type = "); + /* Most of the time users do not want to see all the fields + in a structure. If they do they can use the "ptype" command. + Hence the "-1" below. */ + type_print (VALUE_TYPE (val), "", stdout, -1); + printf_filtered ("\n"); if (exp) do_cleanups (old_chain); @@ -753,28 +795,28 @@ ptype_command (typename) = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0); if (sym == 0) error ("No type named %s.", typename); - printf ("No type named %s, but there is a ", + printf_filtered ("No type named %s, but there is a ", typename); switch (TYPE_CODE (SYMBOL_TYPE (sym))) { case TYPE_CODE_STRUCT: - printf ("struct"); + printf_filtered ("struct"); break; case TYPE_CODE_UNION: - printf ("union"); + printf_filtered ("union"); break; case TYPE_CODE_ENUM: - printf ("enum"); + printf_filtered ("enum"); } - printf (" %s. Type \"help ptype\".\n", typename); + printf_filtered (" %s. Type \"help ptype\".\n", typename); type = SYMBOL_TYPE (sym); } } type_print (type, "", stdout, 1); - printf ("\n"); + printf_filtered ("\n"); } enum display_status {disabled, enabled}; @@ -972,21 +1014,21 @@ do_one_display (d) current_display_number = d->number; - printf ("%d: ", d->number); + printf_filtered ("%d: ", d->number); if (d->format.size) { - printf ("x/"); + printf_filtered ("x/"); if (d->format.count != 1) - printf ("%d", d->format.count); - printf ("%c", d->format.format); + printf_filtered ("%d", d->format.count); + printf_filtered ("%c", d->format.format); if (d->format.format != 'i' && d->format.format != 's') - printf ("%c", d->format.size); - printf (" "); + printf_filtered ("%c", d->format.size); + printf_filtered (" "); print_expression (d->exp, stdout); if (d->format.count != 1) - printf ("\n"); + printf_filtered ("\n"); else - printf (" "); + printf_filtered (" "); do_examine (d->format, (CORE_ADDR) value_as_long (evaluate_expression (d->exp))); @@ -994,12 +1036,12 @@ do_one_display (d) else { if (d->format.format) - printf ("/%c ", d->format.format); + printf_filtered ("/%c ", d->format.format); print_expression (d->exp, stdout); - printf (" = "); + printf_filtered (" = "); print_formatted (evaluate_expression (d->exp), d->format.format, d->format.size); - printf ("\n"); + printf_filtered ("\n"); } fflush (stdout); @@ -1022,12 +1064,27 @@ do_displays () This is done when there is an error or a signal. */ void -delete_current_display () +disable_display (num) + int num; +{ + register struct display *d; + + for (d = display_chain; d; d = d->next) + if (d->number == num) + { + d->status = disabled; + return; + } + printf ("No display number %d.\n", num); +} + +void +disable_current_display () { if (current_display_number >= 0) { - delete_display (current_display_number); - fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n", + disable_display (current_display_number); + fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n", current_display_number); } current_display_number = -1; @@ -1041,21 +1098,21 @@ display_info () if (!display_chain) printf ("There are no auto-display expressions now.\n"); else - printf ("Auto-display expressions now in effect:\n\ + printf_filtered ("Auto-display expressions now in effect:\n\ Num Enb Expression\n"); for (d = display_chain; d; d = d->next) { - printf ("%d: %c ", d->number, "ny"[(int)d->status]); + printf_filtered ("%d: %c ", d->number, "ny"[(int)d->status]); if (d->format.size) - printf ("/%d%c%c ", d->format.count, d->format.size, + printf_filtered ("/%d%c%c ", d->format.count, d->format.size, d->format.format); else if (d->format.format) - printf ("/%c ", d->format.format); + printf_filtered ("/%c ", d->format.format); print_expression (d->exp, stdout); if (d->block && !contained_in (get_selected_block (), d->block)) - printf (" (cannot be evaluated in the current context)"); - printf ("\n"); + printf_filtered (" (cannot be evaluated in the current context)"); + printf_filtered ("\n"); fflush (stdout); } } @@ -1071,7 +1128,7 @@ enable_display (args) if (p == 0) { - for (d = display_chain; d; d->next) + for (d = display_chain; d; d = d->next) d->status = enabled; } else @@ -1100,8 +1157,9 @@ enable_display (args) } void -disable_display (args) +disable_display_command (args, from_tty) char *args; + int from_tty; { register char *p = args; register char *p1; @@ -1110,7 +1168,7 @@ disable_display (args) if (p == 0) { - for (d = display_chain; d; d->next) + for (d = display_chain; d; d = d->next) d->status = disabled; } else @@ -1124,14 +1182,8 @@ disable_display (args) num = atoi (p); - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = disabled; - goto win; - } - printf ("No display number %d.\n", num); - win: + disable_display (atoi (p)); + p = p1; while (*p == ' ' || *p == '\t') p++; @@ -1149,7 +1201,14 @@ print_variable_value (var, frame, stream) FILE *stream; { value val = read_var_value (var, frame); - value_print (val, stream, 0); + value_print (val, stream, 0, Val_pretty_default); +} + +static int +compare_ints (i, j) + int *i, *j; +{ + return *i - *j; } /* Print the arguments of a stack frame, given the function FUNC @@ -1169,10 +1228,10 @@ print_frame_args (func, fi, num, stream) int nsyms = 0; int first = 1; register int i; - register int last_offset = FRAME_ARGS_SKIP; register int last_regparm = 0; register struct symbol *lastsym, *sym, *nextsym; register value val; + CORE_ADDR highest_offset = 0; register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); if (func) @@ -1181,72 +1240,66 @@ print_frame_args (func, fi, num, stream) nsyms = BLOCK_NSYMS (b); } - lastsym = 0; - while (1) + for (i = 0; i < nsyms; i++) { - /* Find first arg that is not before LAST_OFFSET. */ - nextsym = 0; - for (i = 0; i < nsyms; i++) - { - QUIT; - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG) - { - if (SYMBOL_VALUE (sym) >= last_offset - && (nextsym == 0 - || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) - nextsym = sym; - } - else if (SYMBOL_CLASS (sym) == LOC_REGPARM) - { - /* This shouldn't be sorted by number. Since we can't - find nameless args with register parameters, print - this out in order by .stabs. */ - if (sym > lastsym && nextsym == 0) - nextsym = sym; - } - } - if (nextsym == 0) - break; - sym = nextsym; - /* Print any nameless args between the last arg printed - and the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_ARG - && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) - { - print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), - stream); - first = 0; - } + QUIT; + sym = BLOCK_SYM (b, i); + + if (SYMBOL_CLASS (sym) != LOC_REGPARM + && SYMBOL_CLASS (sym) != LOC_ARG + && SYMBOL_CLASS (sym) != LOC_REF_ARG) + continue; + /* Print the next arg. */ if (SYMBOL_CLASS (sym) == LOC_REGPARM) val = value_from_register (SYMBOL_TYPE (sym), SYMBOL_VALUE (sym), FRAME_INFO_ID (fi)); else - val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); + { + int current_offset = SYMBOL_VALUE (sym); + int arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym)); + + if (SYMBOL_CLASS (sym) == LOC_REF_ARG) + val = value_at (SYMBOL_TYPE (sym), + read_memory_integer (addr + current_offset, + sizeof (CORE_ADDR))); + else + val = value_at (SYMBOL_TYPE (sym), addr + current_offset); + + /* Round up address of next arg to multiple of size of int. */ + current_offset + = (((current_offset + sizeof (int) - 1) / sizeof (int)) + * sizeof (int)); + + if ((current_offset + + (arg_size - sizeof (int) + 3) / (sizeof (int))) + > highest_offset) + highest_offset = current_offset; + } if (! first) - fprintf (stream, ", "); - fprintf (stream, "%s=", SYMBOL_NAME (sym)); - value_print (val, stream, 0); + fprintf_filtered (stream, ", "); + fputs_filtered (SYMBOL_NAME (sym), stream); + fputs_filtered ("=", stream); + value_print (val, stream, 0, Val_no_prettyprint); first = 0; - if (SYMBOL_CLASS (sym) == LOC_ARG) - last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); - else - { - last_regparm = SYMBOL_VALUE (sym) + 1; - last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); - } - - /* Round up address of next arg to multiple of size of int. */ - last_offset - = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); - lastsym = sym; } - if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) - print_frame_nameless_args (addr, last_offset, - num * sizeof (int) + FRAME_ARGS_SKIP, stream); + + /* Don't print nameless args in situations where we don't know + enough about the stack to find them. */ + if (num != -1) + { + if (i && num * sizeof (int) + FRAME_ARGS_SKIP > highest_offset) + print_frame_nameless_args (addr, + highest_offset + sizeof (int), + num * sizeof (int) + FRAME_ARGS_SKIP, + stream); + else + print_frame_nameless_args (addr, FRAME_ARGS_SKIP, + num * sizeof (int) + FRAME_ARGS_SKIP, + stream); + } } static void @@ -1260,9 +1313,16 @@ print_frame_nameless_args (argsaddr, start, end, stream) { QUIT; if (start != FRAME_ARGS_SKIP) - fprintf (stream, ", "); - fprintf (stream, "%d", + fprintf_filtered (stream, ", "); +#ifndef PRINT_TYPELESS_INTEGER + fprintf_filtered (stream, "%d", read_memory_integer (argsaddr + start, sizeof (int))); +#else + PRINT_TYPELESS_INTEGER (stream, builtin_type_int, + (LONGEST) + read_memory_integer (argsaddr + start, + sizeof (int))); +#endif start += sizeof (int); } } @@ -1278,10 +1338,6 @@ printf_command (arg) int nargs = 0; int allocated_args = 20; char *arg_bytes; - char *argclass; - int i; - int argindex; - int nargs_wanted; val_args = (value *) xmalloc (allocated_args * sizeof (value)); @@ -1348,113 +1404,217 @@ printf_command (arg) if (*s == ',') s++; while (*s == ' ' || *s == '\t') s++; - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] is set to 1 if the Ith arg should be a string. - It's set to 2 if the Ith arg should be floating point. */ - - argclass = (char *) alloca (strlen (s)); - nargs_wanted = 0; - f = string; - while (*f) - if (*f++ == '%') + { + /* Now scan the string for %-specs and see what kinds of args they want. + argclass[I] classifies the %-specs so we can give vprintf something + of the right size. */ + + enum argclass {int_arg, string_arg, double_arg, long_long_arg}; + enum argclass *argclass; + int nargs_wanted; + int argindex; + int lcount; + int i; + + argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass); + nargs_wanted = 0; + f = string; + while (*f) + if (*f++ == '%') + { + lcount = 0; + while (index ("0123456789.hlL-+ #", *f)) + { + if (*f == 'l' || *f == 'L') + lcount++; + f++; + } + if (*f == 's') + argclass[nargs_wanted++] = string_arg; + else if (*f == 'e' || *f == 'f' || *f == 'g') + argclass[nargs_wanted++] = double_arg; + else if (lcount > 1) + argclass[nargs_wanted++] = long_long_arg; + else if (*f != '%') + argclass[nargs_wanted++] = int_arg; + f++; + } + + /* Now, parse all arguments and evaluate them. + Store the VALUEs in VAL_ARGS. */ + + while (*s != '\0') { - while (index ("0123456789.hlL-+ #", *f)) f++; - if (*f == 's') - argclass[nargs_wanted++] = 1; - else if (*f == 'e' || *f == 'f' || *f == 'g') - argclass[nargs_wanted++] = 2; - else if (*f != '%') - argclass[nargs_wanted++] = 0; - f++; + char *s1; + if (nargs == allocated_args) + val_args = (value *) xrealloc (val_args, + (allocated_args *= 2) + * sizeof (value)); + s1 = s; + val_args[nargs] = parse_to_comma_and_eval (&s1); + + /* If format string wants a float, unchecked-convert the value to + floating point of the same size */ + + if (argclass[nargs] == double_arg) + { + if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) + VALUE_TYPE (val_args[nargs]) = builtin_type_float; + if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) + VALUE_TYPE (val_args[nargs]) = builtin_type_double; + } + nargs++; + s = s1; + if (*s == ',') + s++; + } + + if (nargs != nargs_wanted) + error ("Wrong number of arguments for specified format-string"); + + /* Now lay out an argument-list containing the arguments + as doubles, integers and C pointers. */ + + arg_bytes = (char *) alloca (sizeof (double) * nargs); + argindex = 0; + for (i = 0; i < nargs; i++) + { + if (argclass[i] == string_arg) + { + char *str; + int tem, j; + tem = value_as_long (val_args[i]); + + /* This is a %s argument. Find the length of the string. */ + for (j = 0; ; j++) + { + char c; + QUIT; + read_memory (tem + j, &c, 1); + if (c == 0) + break; + } + + /* Copy the string contents into a string inside GDB. */ + str = (char *) alloca (j + 1); + read_memory (tem, str, j); + str[j] = 0; + + /* Pass address of internal copy as the arg to vprintf. */ + *((int *) &arg_bytes[argindex]) = (int) str; + argindex += sizeof (int); + } + else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) + { + *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); + argindex += sizeof (double); + } + else +#ifdef LONG_LONG + if (argclass[i] == long_long_arg) + { + *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); + argindex += sizeof (long long); + } + else +#endif + { + *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); + argindex += sizeof (int); + } } + } + vprintf (string, arg_bytes); +} + +/* Helper function for asdump_command. Finds the bounds of a function + for a specified section of text. PC is an address within the + function which you want bounds for; *LOW and *HIGH are set to the + beginning (inclusive) and end (exclusive) of the function. This + function returns 1 on success and 0 on failure. */ + +static int +containing_function_bounds (pc, low, high) + CORE_ADDR pc, *low, *high; +{ + int scan; - /* Now, parse all arguments and evaluate them. - Store the VALUEs in VAL_ARGS. */ + if (!find_pc_partial_function (pc, 0, low)) + return 0; - while (*s != '\0') - { - char *s1; - if (nargs == allocated_args) - val_args = (value *) xrealloc (val_args, - (allocated_args *= 2) - * sizeof (value)); - s1 = s; - val_args[nargs] = parse_to_comma_and_eval (&s1); - - /* If format string wants a float, unchecked-convert the value to - floating point of the same size */ - - if (argclass[nargs] == 2) - { - argclass[nargs] = 0; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) - VALUE_TYPE (val_args[nargs]) = builtin_type_float; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) - VALUE_TYPE (val_args[nargs]) = builtin_type_double; - } - nargs++; - s = s1; - if (*s == ',') - s++; - } + scan = *low; + do { + scan++; + if (!find_pc_partial_function (scan, 0, high)) + return 0; + } while (*low == *high); - if (nargs != nargs_wanted) - error ("Wrong number of arguments for specified format-string"); + return 1; +} - /* Now lay out an argument-list containing the arguments - as doubles, integers and C pointers. */ +/* Dump a specified section of assembly code. With no command line + arguments, this command will dump the assembly code for the + function surrounding the pc value in the selected frame. With one + argument, it will dump the assembly code surrounding that pc value. + Two arguments are interpeted as bounds within which to dump + assembly. */ - arg_bytes = (char *) alloca (sizeof (double) * nargs); - argindex = 0; - for (i = 0; i < nargs; i++) - { - if (argclass[i]) - { - char *str; - int tem, j; - tem = value_as_long (val_args[i]); +static void +disassemble_command (arg, from_tty) + char *arg; + int from_tty; +{ + CORE_ADDR low, high; + CORE_ADDR pc; + char *space_index; - /* This is a %s argument. Find the length of the string. */ - for (j = 0; ; j++) - { - char c; - QUIT; - read_memory (tem + j, &c, 1); - if (c == 0) - break; - } + if (!arg) + { + if (!selected_frame) + error ("No frame selected.\n"); - /* Copy the string contents into a string inside GDB. */ - str = (char *) alloca (j + 1); - read_memory (tem, str, j); - str[j] = 0; + pc = get_frame_pc (selected_frame); + if (!containing_function_bounds (pc, &low, &high)) + error ("No function contains pc specified by selected frame.\n"); + } + else if (!(space_index = (char *) index (arg, ' '))) + { + /* One argument. */ + pc = parse_and_eval_address (arg); + if (!containing_function_bounds (pc, &low, &high)) + error ("No function contains specified pc.\n"); + } + else + { + /* Two arguments. */ + *space_index = '\0'; + low = parse_and_eval_address (arg); + high = parse_and_eval_address (space_index + 1); + } - /* Pass address of internal copy as the arg to vprintf. */ - *((int *) &arg_bytes[argindex]) = (int) str; - argindex += sizeof (int); - } - else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) - { - *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); - argindex += sizeof (double); - } - else -#ifdef LONG_LONG - if (TYPE_LENGTH (VALUE_TYPE (val_args[i])) == sizeof (long long)) - { - *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); - argindex += sizeof (long long); - } - else -#endif - { - *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); - argindex += sizeof (int); - } + printf_filtered ("Dump of assembler code "); + if (!space_index) + { + char *name; + find_pc_partial_function (pc, &name, 0); + printf_filtered ("for function %s:\n", name); } + else + printf_filtered ("from 0x%x to 0x%x:\n", low, high); - vprintf (string, arg_bytes); + /* Dump the specified range. */ + for (pc = low; pc < high; ) + { + QUIT; + print_address (pc, stdout); + printf_filtered (":\t"); + pc += print_insn (pc, stdout); + printf_filtered ("\n"); + } + printf_filtered ("End of assembler dump.\n"); + fflush (stdout); } + extern struct cmd_list_element *enablelist, *disablelist, *deletelist; extern struct cmd_list_element *cmdlist, *setlist; @@ -1481,6 +1641,12 @@ Defaults for format and size letters are those previously used.\n\ Default count is 1. Default address is following last thing printed\n\ with this command or \"print\"."); + add_com ("disassemble", class_vars, disassemble_command, + "Disassemble a specified section of memory.\n\ +Default is the function surrounding the pc of the selected frame.\n\ +With a single argument, the function surrounding that address is dumped.\n\ +Two arguments are taken as a range of memory to dump."); + add_com ("ptype", class_vars, ptype_command, "Print definition of type TYPE.\n\ Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ @@ -1493,7 +1659,7 @@ The selected stack frame's lexical context is used to look up the name."); add_info ("display", display_info, "Expressions to display when program stops, with code numbers."); - add_abbrev_cmd ("undisplay", class_vars, undisplay_command, + add_cmd ("undisplay", class_vars, undisplay_command, "Cancel some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to stop displaying.\n\ No argument means cancel all automatic-display expressions.\n\ @@ -1516,7 +1682,7 @@ Arguments are the code numbers of the expressions to resume displaying.\n\ No argument means enable all automatic-display expressions.\n\ Do \"info display\" to see current list of code numbers.", &enablelist); - add_cmd ("display", class_vars, disable_display, + add_cmd ("display", class_vars, disable_display_command, "Disable some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to stop displaying.\n\ No argument means disable all automatic-display expressions.\n\ @@ -1576,4 +1742,3 @@ EXP may be preceded with /FMT, where FMT is a format letter\n\ but no count or size letter (see \"x\" command).")); add_com_alias ("p", "print", class_vars, 1); } - |