📄 utils.c
字号:
/* General utility routines for GDB, the GNU debugger. Copyright 1986, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#if !defined(__GO32__)#include <sys/ioctl.h>#include <sys/param.h>#include <pwd.h>#endif#include <varargs.h>#include <ctype.h>#include <string.h>#include "signals.h"#include "gdbcmd.h"#include "terminal.h"#include "bfd.h"#include "target.h"#include "demangle.h"/* Prototypes for local functions */#if !defined (NO_MALLOC_CHECK)static voidmalloc_botch PARAMS ((void));#endif /* NO_MALLOC_CHECK */static voidfatal_dump_core (); /* Can't prototype with <varargs.h> usage... */static voidprompt_for_continue PARAMS ((void));static void set_width_command PARAMS ((char *, int, struct cmd_list_element *));/* If this definition isn't overridden by the header files, assume that isatty and fileno exist on this system. */#ifndef ISATTY#define ISATTY(FP) (isatty (fileno (FP)))#endif/* Chain of cleanup actions established with make_cleanup, to be executed if an error happens. */static struct cleanup *cleanup_chain;/* Nonzero means a quit has been requested. */int quit_flag;/* Nonzero means quit immediately if Control-C is typed now, rather than waiting until QUIT is executed. */int immediate_quit;/* Nonzero means that encoded C++ names should be printed out in their C++ form rather than raw. */int demangle = 1;/* Nonzero means that encoded C++ names should be printed out in their C++ form even in assembler language displays. If this is set, but DEMANGLE is zero, names are printed raw, i.e. DEMANGLE controls. */int asm_demangle = 0;/* Nonzero means that strings with character values >0x7F should be printed as octal escapes. Zero means just print the value (e.g. it's an international character, and the terminal or window can cope.) */int sevenbit_strings = 0;/* String to be printed before error messages, if any. */char *error_pre_print;char *warning_pre_print = "\nwarning: ";/* Add a new cleanup to the cleanup_chain, and return the previous chain pointer to be passed later to do_cleanups or discard_cleanups. Args are FUNCTION to clean up with, and ARG to pass to it. */struct cleanup *make_cleanup (function, arg) void (*function) PARAMS ((PTR)); PTR arg;{ register struct cleanup *new = (struct cleanup *) xmalloc (sizeof (struct cleanup)); register struct cleanup *old_chain = cleanup_chain; new->next = cleanup_chain; new->function = function; new->arg = arg; cleanup_chain = new; return old_chain;}/* Discard cleanups and do the actions they describe until we get back to the point OLD_CHAIN in the cleanup_chain. */voiddo_cleanups (old_chain) register struct cleanup *old_chain;{ register struct cleanup *ptr; while ((ptr = cleanup_chain) != old_chain) { cleanup_chain = ptr->next; /* Do this first incase recursion */ (*ptr->function) (ptr->arg); free (ptr); }}/* Discard cleanups, not doing the actions they describe, until we get back to the point OLD_CHAIN in the cleanup_chain. */voiddiscard_cleanups (old_chain) register struct cleanup *old_chain;{ register struct cleanup *ptr; while ((ptr = cleanup_chain) != old_chain) { cleanup_chain = ptr->next; free ((PTR)ptr); }}/* Set the cleanup_chain to 0, and return the old cleanup chain. */struct cleanup *save_cleanups (){ struct cleanup *old_chain = cleanup_chain; cleanup_chain = 0; return old_chain;}/* Restore the cleanup chain from a previously saved chain. */voidrestore_cleanups (chain) struct cleanup *chain;{ cleanup_chain = chain;}/* This function is useful for cleanups. Do foo = xmalloc (...); old_chain = make_cleanup (free_current_contents, &foo); to arrange to free the object thus allocated. */voidfree_current_contents (location) char **location;{ free (*location);}/* Provide a known function that does nothing, to use as a base for for a possibly long chain of cleanups. This is useful where we use the cleanup chain for handling normal cleanups as well as dealing with cleanups that need to be done as a result of a call to error(). In such cases, we may not be certain where the first cleanup is, unless we have a do-nothing one to always use as the base. *//* ARGSUSED */voidnull_cleanup (arg) char **arg;{}/* Provide a hook for modules wishing to print their own warning messages to set up the terminal state in a compatible way, without them having to import all the target_<...> macros. */voidwarning_setup (){ target_terminal_ours (); wrap_here(""); /* Force out any buffered output */ fflush (stdout);}/* Print a warning message. The first argument STRING is the warning message, used as a fprintf string, and the remaining args are passed as arguments to it. The primary difference between warnings and errors is that a warning does not force the return to command level. *//* VARARGS */voidwarning (va_alist) va_dcl{ va_list args; char *string; va_start (args); target_terminal_ours (); wrap_here(""); /* Force out any buffered output */ fflush (stdout); if (warning_pre_print) fprintf (stderr, warning_pre_print); string = va_arg (args, char *); vfprintf (stderr, string, args); fprintf (stderr, "\n"); va_end (args);}/* Print an error message and return to command level. The first argument STRING is the error message, used as a fprintf string, and the remaining args are passed as arguments to it. *//* VARARGS */NORETURN voiderror (va_alist) va_dcl{ va_list args; char *string; va_start (args); target_terminal_ours (); wrap_here(""); /* Force out any buffered output */ fflush (stdout); if (error_pre_print) fprintf_filtered (stderr, error_pre_print); string = va_arg (args, char *); vfprintf_filtered (stderr, string, args); fprintf_filtered (stderr, "\n"); va_end (args); return_to_top_level ();}/* Print an error message and exit reporting failure. This is for a error that we cannot continue from. The arguments are printed a la printf. This function cannot be declared volatile (NORETURN) in an ANSI environment because exit() is not declared volatile. *//* VARARGS */NORETURN voidfatal (va_alist) va_dcl{ va_list args; char *string; va_start (args); string = va_arg (args, char *); fprintf (stderr, "\ngdb: "); vfprintf (stderr, string, args); fprintf (stderr, "\n"); va_end (args); exit (1);}/* Print an error message and exit, dumping core. The arguments are printed a la printf (). *//* VARARGS */static voidfatal_dump_core (va_alist) va_dcl{ va_list args; char *string; va_start (args); string = va_arg (args, char *); /* "internal error" is always correct, since GDB should never dump core, no matter what the input. */ fprintf (stderr, "\ngdb internal error: "); vfprintf (stderr, string, args); fprintf (stderr, "\n"); va_end (args); signal (SIGQUIT, SIG_DFL); kill (getpid (), SIGQUIT); /* We should never get here, but just in case... */ exit (1);}/* The strerror() function can return NULL for errno values that are out of range. Provide a "safe" version that always returns a printable string. */char *safe_strerror (errnum) int errnum;{ char *msg; static char buf[32]; if ((msg = strerror (errnum)) == NULL) { sprintf (buf, "(undocumented errno %d)", errnum); msg = buf; } return (msg);}/* The strsignal() function can return NULL for signal values that are out of range. Provide a "safe" version that always returns a printable string. */char *safe_strsignal (signo) int signo;{ char *msg; static char buf[32]; if ((msg = strsignal (signo)) == NULL) { sprintf (buf, "(undocumented signal %d)", signo); msg = buf; } return (msg);}/* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. Then return to command level. */voidperror_with_name (string) char *string;{ char *err; char *combined; err = safe_strerror (errno); combined = (char *) alloca (strlen (err) + strlen (string) + 3); strcpy (combined, string); strcat (combined, ": "); strcat (combined, err); /* I understand setting these is a matter of taste. Still, some people may clear errno but not know about bfd_error. Doing this here is not unreasonable. */ bfd_error = no_error; errno = 0; error ("%s.", combined);}/* Print the system error message for ERRCODE, and also mention STRING as the file name for which the error was encountered. */voidprint_sys_errmsg (string, errcode) char *string; int errcode;{ char *err; char *combined; err = safe_strerror (errcode); combined = (char *) alloca (strlen (err) + strlen (string) + 3); strcpy (combined, string); strcat (combined, ": "); strcat (combined, err); fprintf (stderr, "%s.\n", combined);}/* Control C eventually causes this to be called, at a convenient time. */voidquit (){ target_terminal_ours (); wrap_here ((char *)0); /* Force out any pending output */#if !defined(__GO32__)#ifdef HAVE_TERMIO ioctl (fileno (stdout), TCFLSH, 1);#else /* not HAVE_TERMIO */ ioctl (fileno (stdout), TIOCFLUSH, 0);#endif /* not HAVE_TERMIO */#ifdef TIOCGPGRP error ("Quit");#else error ("Quit (expect signal %d when inferior is resumed)", SIGINT);#endif /* TIOCGPGRP */#endif}/* Control C comes here */voidrequest_quit (signo) int signo;{ quit_flag = 1;#ifdef USG /* Restore the signal handler. */ signal (signo, request_quit);#endif if (immediate_quit) quit ();}/* Memory management stuff (malloc friends). */#if defined (NO_MMALLOC)PTRmmalloc (md, size) PTR md; long size;{ return (malloc (size));}PTRmrealloc (md, ptr, size) PTR md; PTR ptr; long size;{ if (ptr == 0) /* Guard against old realloc's */ return malloc (size); else return realloc (ptr, size);}voidmfree (md, ptr) PTR md; PTR ptr;{ free (ptr);}#endif /* NO_MMALLOC */#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)voidinit_malloc (md) PTR md;{}#else /* have mmalloc and want corruption checking */static voidmalloc_botch (){ fatal_dump_core ("Memory corruption");}/* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified by MD, to detect memory corruption. Note that MD may be NULL to specify the default heap that grows via sbrk. Note that for freshly created regions, we must call mmcheck prior to any mallocs in the region. Otherwise, any region which was allocated prior to installing the checking hooks, which is later reallocated or freed, will fail the checks! The mmcheck function only allows initial hooks to be installed before the first mmalloc. However, anytime after we have called mmcheck the first time to install the checking hooks, we can call it again to update the function pointer to the memory corruption handler. Returns zero on failure, non-zero on success. */voidinit_malloc (md) PTR md;{ if (!mmcheck (md, malloc_botch)) { warning ("internal error: failed to install memory consistency checks"); } mmtrace ();}#endif /* Have mmalloc and want corruption checking *//* Called when a memory allocation fails, with the number of bytes of memory requested in SIZE. */NORETURN voidnomem (size) long size;{ if (size > 0) { fatal ("virtual memory exhausted: can't allocate %ld bytes.", size); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -