📄 printcmd.c
字号:
num -= print_frame_named_args(func, fi, &offset, stream); else if (num < 0) /* If we don't have a debugging symbol for this routine, and we can't tell how many args there are, we should at least print something useful */ num = default_funargs; /* Don't print nameless args in situations where we don't know enough about the stack to find them. */ if (num > 0) { CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); if (addr) print_frame_nameless_args (fi, addr, offset, num, func == 0, stream); }}/* Print nameless args on STREAM. ARGSADDR is the address of the arglist, START is the offset of the first nameless arg, and NUM is the number of nameless args to print. FIRST is nonzero if this is the first argument (not just the first nameless arg). */static voidprint_frame_nameless_args (fi, argsaddr, start, num, first, stream) struct frame_info *fi; CORE_ADDR argsaddr; long start; int num; int first; FILE *stream;{ int i; LONGEST v; extern int output_format; for (i = 0; i < num; i++) { QUIT; if (!first) fprintf_filtered (stream, ", "); first = 0;#ifdef NAMELESS_ARG NAMELESS_ARG(fi, i, v);#else v = read_memory_integer (argsaddr + start, sizeof (int));#endif#ifdef PRINT_TYPELESS_INTEGER PRINT_TYPELESS_INTEGER (stream, builtin_type_int, v);#else print_scalar_formatted ((char *)&v, builtin_type_int, output_format ? output_format : 'x', 0, stream);#endif start += sizeof (int); }}/* ARGSUSED */static voidprintf_command (arg, from_tty) char *arg; int from_tty;{ register char *f; register char *s = arg; char *string; value *val_args; int nargs = 0; int allocated_args = 20; char *arg_bytes; val_args = (value *) xmalloc (allocated_args * sizeof (value)); if (s == 0) error_no_arg ("format-control string and values to print"); /* Skip white space before format string */ while (*s == ' ' || *s == '\t') s++; /* A format string should follow, enveloped in double quotes */ if (*s++ != '"') error ("Bad format string, missing '\"'."); /* Parse the format-control string and copy it into the string STRING, processing some kinds of escape sequence. */ f = string = (char *) alloca (strlen (s) + 1); while (*s != '"') { int c = *s++; switch (c) { case '\0': error ("Bad format string, non-terminated '\"'."); /* doesn't return */ case '\\': switch (c = *s++) { case '\\': *f++ = '\\'; break; case 'n': *f++ = '\n'; break; case 't': *f++ = '\t'; break; case 'r': *f++ = '\r'; break; case '"': *f++ = '"'; break; default: /* ??? TODO: handle other escape sequences */ error ("Unrecognized \\ escape character in format string."); } break; default: *f++ = c; } } /* Skip over " and following space and comma. */ s++; *f++ = '\0'; while (*s == ' ' || *s == '\t') s++; if (*s != ',' && *s != 0) error ("Invalid argument syntax"); if (*s == ',') s++; while (*s == ' ' || *s == '\t') s++; { /* 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 (strchr ("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') { char *s1; if (nargs == allocated_args) val_args = (value *) xrealloc ((char *) 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; CORE_ADDR tem; int j; tem = value_as_pointer (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 { *((long *) &arg_bytes[argindex]) = value_as_long (val_args[i]); argindex += sizeof (long); } } } /* There is not a standard way to make a va_list, so we need to do various things for different systems. */#if defined (__INT_VARARGS_H) { va_list list; list.__va_arg = 0; list.__va_stk = (int *) arg_bytes; list.__va_reg = (int *) arg_bytes; vprintf (string, list); }#else /* No __INT_VARARGS_H. */ vprintf (string, arg_bytes);#endif /* No __INT_VARARGS_H. */}/* 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 intcontaining_function_bounds (pc, low, high) CORE_ADDR pc, *low, *high;{ int scan; if (!find_pc_partial_function (pc, 0, low)) return 0; scan = *low; do { scan++; if (!find_pc_partial_function (scan, 0, high)) return 0; } while (*low == *high); return 1;}/* 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. *//* ARGSUSED */static voiddisassemble_command (arg, from_tty) char *arg; int from_tty;{ CORE_ADDR low, high; CORE_ADDR pc; char *space_index; if (!arg) { if (!selected_frame) error ("No frame selected.\n"); 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 *) strchr (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); } 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 %s ", local_hex_string(low)); printf_filtered ("to %s:\n", local_hex_string(high)); /* 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);}/* * A command to dump out memory as an array of chars. Output is * much easier to read than "x /c". */static voidchardump_command (arg, from_tty) char *arg; int from_tty;{ register CORE_ADDR addr; register char *cp; register int len, cc; char buf[64]; if (arg == 0) error("Must supply address argument."); cp = (char *)strchr(arg, ' '); addr = parse_and_eval_address(arg); /* XXX Should take length arg as an expression. */ len = (cp != 0) ? atoi(cp) : 8 * sizeof(buf); while (len >= 0) {#ifndef MIN#define MIN(a,b) ((a)<(b)?(a):(b))#endif cc = MIN(len, sizeof(buf)); read_memory(addr, buf, sizeof(buf)); cp = buf; while (--cc >= 0) { register char c = *cp; if (c == 0) *cp = '*'; else if (!isprint(c)) *cp = '.'; ++cp; } len -= sizeof(buf); addr += sizeof(buf); }}void_initialize_printcmd (){ current_display_number = -1; add_info ("address", address_info, "Describe where variable VAR is stored."); add_com ("x", class_vars, x_command, "Examine memory: x/FMT ADDRESS.\n\ADDRESS is an expression for the memory address to examine.\n\FMT is a repeat count followed by a format letter and a size letter.\n\Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ f(float), a(address), i(instruction), c(char) and s(string).\n\Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\ g is meaningful only with f, for type double.\n\The specified number of objects of the specified size are printed\n\according to the format.\n\n\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\or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\The selected stack frame's lexical context is used to look up the name."); add_com ("whatis", class_vars, whatis_command, "Print data type of expression EXP.");#if 0 add_com ("whereis", class_vars, whereis_command, "Print line number and file of definition of variable.");#endif add_info ("display", display_info, "Expressions to display when program stops, with code numbers."); 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\\"delete display\" has the same effect as this command.\n\Do \"info display\" to see current list of code numbers.", &cmdlist); add_com ("display", class_vars, display_command, "Print value of expression EXP each time the program stops.\n\/FMT may be used before EXP as in the \"print\" command.\n\/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\as in the \"x\" command, and then EXP is used to get the address to examine\n\and examining is done as in the \"x\" command.\n\n\With no argument, display all currently requested auto-display expressions.\n\Use \"undisplay\" to cancel display requests previously made."); add_cmd ("display", class_vars, enable_display, "Enable some expressions to be displayed when program stops.\n\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_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\Do \"info display\" to see current list of code numbers.", &disablelist); add_cmd ("display", 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\Do \"info display\" to see current list of code numbers.", &deletelist); add_com ("printf", class_vars, printf_command, "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\This is useful for formatted output in user-defined commands."); add_com ("output", class_vars, output_command, "Like \"print\" but don't put in value history and don't print newline.\n\This is useful in user-defined commands."); add_prefix_cmd ("set", class_vars, set_command,"Perform an assignment VAR = EXP.\n\You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\(names starting with $), a register (a few standard names starting with $),\n\or an actual variable in the program being debugged. EXP is any expression.\n\Use \"set variable\" for variables with names identical to set subcommands.\n\\nWith a subcommand, this command modifies parts of the gdb environment.\n\You can see these environment settings with the \"show\" command.", &setlist, "set ", 1, &cmdlist); /* "call" is the same as "set", but handy for dbx users to call fns. */ add_com ("call", class_vars, call_command, "Call a function in the inferior process.\n\The argument is the function name and arguments, in the notation of the\n\current working language. The result is printed and saved in the value\n\history, if it is not void."); add_cmd ("variable", class_vars, set_command, "Perform an assignment VAR = EXP.\n\You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\(names starting with $), a register (a few standard names starting with $),\n\or an actual variable in the program being debugged. EXP is any expression.\n\This may usually be abbreviated to simply \"set\".", &setlist); add_com ("print", class_vars, print_command, concat ("Print value of expression EXP.\n\Variables accessible are those of the lexical environment of the selected\n\stack frame, plus all those whose scope is global or an entire file.\n\\n\$NUM gets previous value number NUM. $ and $$ are the last two values.\n\$$NUM refers to NUM'th value back from the last one.\n\Names starting with $ refer to registers (with the values they would have\n\if the program were to return to the stack frame now selected, restoring\n\all registers saved by frames farther in) or else to debugger\n\\"convenience\" variables (any such name not a known register).\n\Use assignment expressions to give values to convenience variables.\n", "\n\{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\@ is a binary operator for treating consecutive data objects\n\anywhere in memory as an array. FOO@NUM gives an array whose first\n\element is FOO, whose second element is stored in the space following\n\where FOO is stored, etc. FOO must be an expression whose value\n\resides in memory.\n", "\n\EXP may be preceded with /FMT, where FMT is a format letter\n\but no count or size letter (see \"x\" command).", NULL)); add_com_alias ("p", "print", class_vars, 1); add_com ("inspect", class_vars, inspect_command,"Same as \"print\" command, except that if you are running in the epoch\n\environment, the value is printed in its own window."); add_com ("chardump", class_vars, chardump_command,"Dump out a range of memory as characters. Two arguments are starting\n\address (as an arbitrary expression) and constant integer length."); add_show_from_set( add_set_cmd ("default-funargs", class_support, var_zinteger, (char *)&default_funargs,"Set the number of arguments to be printed for functions with\n\no debugging info.\n", &setlist), &showlist); add_show_from_set (add_set_cmd ("asm-symbolic", class_support, var_boolean, (char *)&asm_symbolic, "Set printing of symbolic offsets in disassmebly listings", &setprintlist), &showprintlist);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -