⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exceptions.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 3 页
字号:
/* exceptions.cc   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <imagehlp.h>#include <errno.h>#include <stdlib.h>#include "exceptions.h"#include "sync.h"#include "sigproc.h"#include "pinfo.h"#include "cygerrno.h"#include "perthread.h"#include "shared_info.h"#include "perprocess.h"#include "security.h"#define CALL_HANDLER_RETRY 20char debugger_command[2 * MAX_PATH + 20];extern "C" {static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);extern void sigreturn ();extern void sigdelayed ();extern void sigdelayed0 ();extern void siglast ();extern DWORD __no_sig_start, __no_sig_end;};extern DWORD sigtid;extern HANDLE hExeced;extern DWORD dwExeced;static BOOL WINAPI ctrl_c_handler (DWORD);static void signal_exit (int) __attribute__ ((noreturn));static char windows_system_directory[1024];static size_t windows_system_directory_length;/* This is set to indicate that we have already exited.  */static NO_COPY int exit_already = 0;static NO_COPY muto *mask_sync = NULL;HMODULE NO_COPY cygwin_hmodule;NO_COPY static struct{  unsigned int code;  const char *name;} status_info[] ={#define X(s) s, #s  { X (STATUS_ABANDONED_WAIT_0) },  { X (STATUS_ACCESS_VIOLATION) },  { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },  { X (STATUS_BREAKPOINT) },  { X (STATUS_CONTROL_C_EXIT) },  { X (STATUS_DATATYPE_MISALIGNMENT) },  { X (STATUS_FLOAT_DENORMAL_OPERAND) },  { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },  { X (STATUS_FLOAT_INEXACT_RESULT) },  { X (STATUS_FLOAT_INVALID_OPERATION) },  { X (STATUS_FLOAT_OVERFLOW) },  { X (STATUS_FLOAT_STACK_CHECK) },  { X (STATUS_FLOAT_UNDERFLOW) },  { X (STATUS_GUARD_PAGE_VIOLATION) },  { X (STATUS_ILLEGAL_INSTRUCTION) },  { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },  { X (STATUS_INTEGER_OVERFLOW) },  { X (STATUS_INVALID_DISPOSITION) },  { X (STATUS_IN_PAGE_ERROR) },  { X (STATUS_NONCONTINUABLE_EXCEPTION) },  { X (STATUS_NO_MEMORY) },  { X (STATUS_PENDING) },  { X (STATUS_PRIVILEGED_INSTRUCTION) },  { X (STATUS_SINGLE_STEP) },  { X (STATUS_STACK_OVERFLOW) },  { X (STATUS_TIMEOUT) },  { X (STATUS_USER_APC) },  { X (STATUS_WAIT_0) },  { 0, 0 }#undef X};/* Initialization code.  */#ifdef __i386__// Set up the exception handler for the current thread.  The PowerPC & Mips// use compiler generated tables to set up the exception handlers for each// region of code, and the kernel walks the call list until it finds a region// of code that handles exceptions.  The x86 on the other hand uses segment// register fs, offset 0 to point to the current exception handler.asm (".equ __except_list,0");extern exception_list *_except_list asm ("%fs:__except_list");static voidinit_exception_handler (exception_list *el){  el->handler = handle_exceptions;  el->prev = _except_list;  _except_list = el;}#endifvoidearly_stuff_init (){  (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);  if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))    system_printf ("SetConsoleCtrlHandler failed, %E");  /* Initialize global security attribute stuff */  sec_none.nLength = sec_none_nih.nLength =  sec_all.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);  sec_none.bInheritHandle = sec_all.bInheritHandle = TRUE;  sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;  sec_none.lpSecurityDescriptor = sec_none_nih.lpSecurityDescriptor = NULL;  sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =    get_null_sd ();}extern "C" voidinit_exceptions (exception_list *el){  init_exception_handler (el);}extern "C" voiderror_start_init (const char *buf){  if (!buf || !*buf)    {      debugger_command[0] = '\0';      return;    }  char pgm[MAX_PATH + 1];  if (!GetModuleFileName (NULL, pgm, MAX_PATH))    strcpy (pgm, "cygwin1.dll");  for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))    *p = '/';  __small_sprintf (debugger_command, "%s %s", buf, pgm);}static voidopen_stackdumpfile (){  if (myself->progname[0])    {      const char *p;      /* write to progname.stackdump if possible */      if (!myself->progname[0])	p = "unknown";      else if ((p = strrchr (myself->progname, '\\')))	p++;      else	p = myself->progname;      char corefile[strlen (p) + sizeof (".stackdump")];      __small_sprintf (corefile, "%s.stackdump", p);      HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,			     CREATE_ALWAYS, 0, 0);      if (h != INVALID_HANDLE_VALUE)	{	  if (!myself->ppid_handle)	    system_printf ("Dumping stack trace to %s", corefile);	  else	    debug_printf ("Dumping stack trace to %s", corefile);	  SetStdHandle (STD_ERROR_HANDLE, h);	}    }}/* Utilities for dumping the stack, etc.  */static voidexception (EXCEPTION_RECORD *e,  CONTEXT *in){  const char *exception_name = NULL;  if (e)    {      for (int i = 0; status_info[i].name; i++)	{	  if (status_info[i].code == e->ExceptionCode)	    {	      exception_name = status_info[i].name;	      break;	    }	}    }#ifdef __i386__#define HAVE_STATUS  if (exception_name)    small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);  else    small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);  small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",	      in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);  small_printf ("ebp=%08x esp=%08x program=%s\r\n",	      in->Ebp, in->Esp, myself->progname);  small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",	      in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);#endif#ifndef HAVE_STATUS  system_printf ("Had an exception");#endif}#ifdef __i386__/* Print a stack backtrace. */#define HAVE_STACK_TRACE/* A class for manipulating the stack. */class stack_info{  int walk ();			/* Uses the "old" method */  char *next_offset () {return *((char **) sf.AddrFrame.Offset);}  bool needargs;  DWORD dummy_frame;public:  STACKFRAME sf;		 /* For storing the stack information */  void init (DWORD, bool, bool); /* Called the first time that stack info is needed */  /* Postfix ++ iterates over the stack, returning zero when nothing is left. */  int operator ++(int) { return this->walk (); }};/* The number of parameters used in STACKFRAME */#define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))/* This is the main stack frame info for this process. */static NO_COPY stack_info thestack;static signal_dispatch sigsave;/* Initialize everything needed to start iterating. */voidstack_info::init (DWORD ebp, bool wantargs, bool goodframe){# define debp ((DWORD *) ebp)  memset (&sf, 0, sizeof (sf));  if (!goodframe)    sf.AddrFrame.Offset = ebp;  else    {      dummy_frame = ebp;      sf.AddrFrame.Offset = (DWORD) &dummy_frame;    }  sf.AddrReturn.Offset = debp[1];  sf.AddrFrame.Mode = AddrModeFlat;  needargs = wantargs;# undef debp}/* Walk the stack by looking at successive stored 'bp' frames.   This is not foolproof. */intstack_info::walk (){  char **ebp;  if ((ebp = (char **) next_offset ()) == NULL)    return 0;  sf.AddrFrame.Offset = (DWORD) ebp;  sf.AddrPC.Offset = sf.AddrReturn.Offset;  if (!sf.AddrPC.Offset)    return 0;		/* stack frames are exhausted */  /* The return address always follows the stack pointer */  sf.AddrReturn.Offset = (DWORD) *++ebp;  if (needargs)    /* The arguments follow the return address */    for (unsigned i = 0; i < NPARAMS; i++)      sf.Params[i] = (DWORD) *++ebp;  return 1;}static voidstackdump (DWORD ebp, int open_file, bool isexception){  extern unsigned long rlim_core;  if (rlim_core == 0UL)    return;  if (open_file)    open_stackdumpfile ();  int i;  thestack.init (ebp, 1, !isexception);	/* Initialize from the input CONTEXT */  small_printf ("Stack trace:\r\nFrame     Function  Args\r\n");  for (i = 0; i < 16 && thestack++; i++)    {      small_printf ("%08x  %08x ", thestack.sf.AddrFrame.Offset,		    thestack.sf.AddrPC.Offset);      for (unsigned j = 0; j < NPARAMS; j++)	small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);      small_printf (")\r\n");    }  small_printf ("End of stack trace%s",	      i == 16 ? " (more stack frames may be present)" : "");}/* Temporary (?) function for external callers to get a stack dump */extern "C" voidcygwin_stackdump (){  CONTEXT c;  c.ContextFlags = CONTEXT_FULL;  GetThreadContext (GetCurrentThread (), &c);  stackdump (c.Ebp, 0, 0);}#define TIME_TO_WAIT_FOR_DEBUGGER 10000extern "C" inttry_to_debug (bool waitloop){  debug_printf ("debugger_command '%s'", debugger_command);  if (*debugger_command == '\0' || being_debugged ())    return 0;  __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());  SetThreadPriority (hMainThread, THREAD_PRIORITY_HIGHEST);  PROCESS_INFORMATION pi = {NULL, 0, 0, 0};  STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};  si.lpReserved = NULL;  si.lpDesktop = NULL;  si.dwFlags = 0;  si.cb = sizeof (si);  /* FIXME: need to know handles of all running threads to     suspend_all_threads_except (current_thread_id);  */  /* if any of these mutexes is owned, we will fail to start any cygwin app     until trapped app exits */  ReleaseMutex (title_mutex);  /* prevent recursive exception handling */  char* rawenv = GetEnvironmentStrings () ;  for (char* p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1)    {      if (strncmp (p, "CYGWIN=", sizeof ("CYGWIN=") - 1) == 0)	{	  char* q = strstr (p, "error_start") ;	  /* replace 'error_start=...' with '_rror_start=...' */	  if (q) *q = '_' ;	  SetEnvironmentVariable ("CYGWIN", p + sizeof ("CYGWIN=")) ;	  break ;	}    }  BOOL dbg;  dbg = CreateProcess (NULL,		       debugger_command,		       NULL,		       NULL,		       FALSE,		       CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,		       NULL,		       NULL,		       &si,		       &pi);  if (!dbg)    system_printf ("Failed to start debugger: %E");  else    {      SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);      if (!waitloop)	return 1;      while (!being_debugged ())	/* spin */;      Sleep (4000);      small_printf ("*** continuing from debugger call\n");    }  /* FIXME: need to know handles of all running threads to    resume_all_threads_except (current_thread_id);  */  return 0;}/* Main exception handler. */static inthandle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *){  int sig;  static int NO_COPY debugging = 0;  static int NO_COPY recursed = 0;  if (debugging && ++debugging < 500000)    {      SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);      return 0;    }  /* If we've already exited, don't do anything here.  Returning 1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -