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

📄 strace.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* strace.cc   Copyright 2000, 2001, 2002 Red Hat Inc.   Written by Chris Faylor <cgf@redhat.com>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. */#define cygwin_internal cygwin_internal_dontuse#include <stdio.h>#include <fcntl.h>#include <getopt.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <windows.h>#include <signal.h>#include <errno.h>#include "cygwin/include/sys/strace.h"#include "cygwin/include/sys/cygwin.h"#undef cygwin_internal/*  GCC runtime library's C++ EH code unfortunately pulls in stdio, and we   get undefine references to __impure_ptr, and hence the following   hack. It should be reasonably safe however as long as this file   is built using -mno-cygwin as is intended.  */int _impure_ptr;/* we *know* we're being built with GCC */#define alloca __builtin_alloca// Version string.static const char version[] = "$Revision: 1.21 $";static const char *pgm;static int forkdebug = 1;static int numerror = 1;static int usecs = 1;static int delta = 1;static int hhmmss = 0;static int bufsize = 0;static int new_window = 0;static long flush_period = 0;static BOOL close_handle (HANDLE h, DWORD ok);#define CloseHandle(h) close_handle(h, 0)struct child_list{  DWORD id;  HANDLE hproc;  int saw_stars;  char nfields;  long long start_time;  DWORD last_usecs;  struct child_list *next;    child_list ():id (0), hproc (NULL), saw_stars (0), nfields (0),    start_time (0), last_usecs (0), next (NULL)  {  }};child_list children;static voidwarn (int geterrno, const char *fmt, ...){  va_list args;  char buf[4096];  va_start (args, fmt);  sprintf (buf, "%s: ", pgm);  vsprintf (strchr (buf, '\0'), fmt, args);  if (geterrno)    perror (buf);  else    {      fputs (buf, stderr);      fputs ("\n", stderr);    }}static void __attribute__ ((noreturn))error (int geterrno, const char *fmt, ...){  va_list args;  char buf[4096];  va_start (args, fmt);  sprintf (buf, "%s: ", pgm);  vsprintf (strchr (buf, '\0'), fmt, args);  if (geterrno)    perror (buf);  else    {      fputs (buf, stderr);      fputs ("\n", stderr);    }  exit (1);}DWORD lastid = 0;HANDLE lasth;#define PROCFLAGS \ PROCESS_ALL_ACCESS		/*(PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_VM_WRITE) */static voidadd_child (DWORD id, HANDLE hproc){  child_list *c = children.next;  children.next = (child_list *) calloc (1, sizeof (child_list));  children.next->next = c;  lastid = children.next->id = id;  lasth = children.next->hproc = hproc;}static child_list *get_child (DWORD id){  child_list *c;  for (c = &children; (c = c->next) != NULL;)    if (c->id == id)      return c;  error (0, "no process id %d found", id);}static voidremove_child (DWORD id){  child_list *c;  if (id == lastid)    lastid = 0;  for (c = &children; c->next != NULL; c = c->next)    if (c->next->id == id)      {	child_list *c1 = c->next;	c->next = c1->next;	free (c1);	return;      }  error (0, "no process id %d found", id);}#define LINE_BUF_CHUNK 128class linebuf{  size_t alloc;public:    size_t ix;  char *buf;  linebuf ()  {    ix = 0;    alloc = 0;    buf = NULL;  } ~linebuf ()  {    if (buf)      free (buf);  }  void add (const char *what, int len);  void add (const char *what)  {    add (what, strlen (what));  }  void prepend (const char *what, int len);};voidlinebuf::add (const char *what, int len){  size_t newix;  if ((newix = ix + len) >= alloc)    {      alloc += LINE_BUF_CHUNK + len;      buf = (char *) realloc (buf, alloc + 1);    }  memcpy (buf + ix, what, len);  ix = newix;  buf[ix] = '\0';}voidlinebuf::prepend (const char *what, int len){  int buflen;  size_t newix;  if ((newix = ix + len) >= alloc)    {      alloc += LINE_BUF_CHUNK + len;      buf = (char *) realloc (buf, alloc + 1);      buf[ix] = '\0';    }  if ((buflen = strlen (buf)))    memmove (buf + len, buf, buflen + 1);  else    buf[newix] = '\0';  memcpy (buf, what, len);  ix = newix;}static voidmake_command_line (linebuf & one_line, char **argv){  for (; *argv; argv++)    {      char *p = NULL;      const char *a = *argv;      int len = strlen (a);      if (len != 0 && !(p = strpbrk (a, " \t\n\r\"")))	one_line.add (a, len);      else	{	  one_line.add ("\"", 1);	  for (; p; a = p, p = strchr (p, '"'))	    {	      one_line.add (a, ++p - a);	      if (p[-1] == '"')		one_line.add ("\"", 1);	    }	  if (*a)	    one_line.add (a);	  one_line.add ("\"", 1);	}      one_line.add (" ", 1);    }  if (one_line.ix)    one_line.buf[one_line.ix - 1] = '\0';  else    one_line.add ("", 1);}static DWORD child_pid;static BOOL WINAPIctrl_c (DWORD){  static int tic = 1;  if ((tic ^= 1) && !GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0))    error (0, "couldn't send CTRL-C to child, win32 error %d\n",	   GetLastError ());  return TRUE;}DWORD (*cygwin_internal) (int, ...);static intload_cygwin (){  static HMODULE h;  if (cygwin_internal)    return 1;  if (h)    return 0;  if (!(h = LoadLibrary ("cygwin1.dll")))    {      errno = ENOENT;      return 0;    }  if (!(cygwin_internal = (DWORD (*) (int, ...)) GetProcAddress (h, "cygwin_internal")))    {      errno = ENOSYS;      return 0;    }  return 1;}static voidattach_process (pid_t pid){  load_cygwin ();  child_pid = (DWORD) cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);  if (!child_pid)    {      warn (0, "no such cygwin pid - %d", pid);      child_pid = pid;    }  if (!DebugActiveProcess (child_pid))    error (0, "couldn't attach to pid %d<%d> for debugging", pid, child_pid);  printf ("Attached to pid %d (windows pid %u)\n", pid, (unsigned) child_pid);  return;}static voidcreate_child (char **argv){  linebuf one_line;  STARTUPINFO si;  PROCESS_INFORMATION pi;  BOOL ret;  DWORD flags;  memset (&si, 0, sizeof (si));  si.cb = sizeof (si);  flags = CREATE_DEFAULT_ERROR_MODE	  | (forkdebug ? DEBUG_PROCESS : DEBUG_ONLY_THIS_PROCESS);  if (new_window)    flags |= CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;  make_command_line (one_line, argv);  SetConsoleCtrlHandler (NULL, 0);  ret = CreateProcess (0, one_line.buf,	/* command line */		       NULL,	/* Security */		       NULL,	/* thread */		       TRUE,	/* inherit handles */		       flags,	/* start flags */		       NULL, NULL,	/* current directory */		       &si, &pi);  if (!ret)    error (0, "error creating process %s, (error %d)", *argv,	   GetLastError ());  CloseHandle (pi.hThread);  CloseHandle (pi.hProcess);  child_pid = pi.dwProcessId;  SetConsoleCtrlHandler (ctrl_c, 1);}static intoutput_winerror (FILE *ofile, char *s){  char *winerr = strstr (s, "Win32 error ");  if (!winerr)    return 0;  DWORD errnum = atoi (winerr + sizeof ("Win32 error ") - 1);  if (!errnum)    return 0;  /*   * NOTE: Currently there is no policy for how long the   * the buffers are, and looks like 256 is a smallest one   * (dlfcn.cc). Other than error 1395 (length 213) and   * error 1015 (length 249), the rest are all under 188   * characters, and so I'll use 189 as the buffer length.   * For those longer error messages, FormatMessage will   * return FALSE, and we'll get the old behaviour such as   * ``Win32 error 1395'' etc.   */  char buf[4096];  if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM		      | FORMAT_MESSAGE_IGNORE_INSERTS,		      NULL,		      errnum,		      MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),		      (LPTSTR) buf, sizeof (buf), NULL))    return 0;  /* Get rid the trailing CR/NL pair. */  char *p = strchr (buf, '\0');  p[-2] = '\n';  p[-1] = '\0';  *winerr = '\0';  fputs (s, ofile);  fputs (buf, ofile);  return 1;}static SYSTEMTIME *syst (long long t){  FILETIME n;  static SYSTEMTIME st;  long long now = t + ((long long) usecs * 10);  n.dwHighDateTime = now >> 32;  n.dwLowDateTime = now & 0xffffffff;  FileTimeToSystemTime (&n, &st);  return &st;}static void __stdcallhandle_output_debug_string (DWORD id, LPVOID p, unsigned mask, FILE *ofile){  int len;  int special;  char alen[3 + 8 + 1];  DWORD nbytes;  child_list *child = get_child (id);  HANDLE hchild = child->hproc;#define INTROLEN (sizeof (alen) - 1)  if (id == lastid && hchild != lasth)    warn (0, "%p != %p", hchild, lasth);  alen[INTROLEN] = '\0';  if (!ReadProcessMemory (hchild, p, alen, INTROLEN, &nbytes))#ifndef DEBUGGING    return;#else    error (0,	   "couldn't get message length from subprocess %d<%p>, windows error %d",	   id, hchild, GetLastError ());#endif  if (strncmp (alen, "cYg", 3))    return;  len = (int) strtoul (alen + 3, NULL, 16);  if (!len)    return;  if (len > 0)    special = 0;  else    {      special = len;      if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)	len = 17;    }  char *buf;  buf = (char *) alloca (len + 65) + 10;  if (!ReadProcessMemory (hchild, ((char *) p) + INTROLEN, buf, len, &nbytes))    error (0, "couldn't get message from subprocess, windows error %d",	   GetLastError ());  buf[len] = '\0';  char *s = strtok (buf, " ");  unsigned n = strtoul (s, NULL, 16);  s = strchr (s, '\0') + 1;  if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)    {      DWORD new_flag = 1;      if (!WriteProcessMemory (hchild, (LPVOID) n, &new_flag,			       sizeof (new_flag), &nbytes))	error (0,	       "couldn't write strace flag to subprocess, windows error %d",	       GetLastError ());      return;    }  char *origs = s;  if (mask & n)    /* got it */ ;  else if (!(mask & _STRACE_ALL) || (n & _STRACE_NOTALL))    return;			/* This should not be included in "all" output */  DWORD dusecs, usecs;  char *ptusec, *ptrest;  dusecs = strtoul (s, &ptusec, 10);  char *q = ptusec;  while (*q == ' ')    q++;  if (*q != '[')    {      usecs = strtoul (q, &ptrest, 10);      while (*ptrest == ' ')	ptrest++;    }  else    {      ptrest = q;      ptusec = s;      usecs = dusecs;    }  if (child->saw_stars == 0)    {      FILETIME st;      char *news;      GetSystemTimeAsFileTime (&st);      FileTimeToLocalFileTime (&st, &st);      child->start_time = st.dwHighDateTime;      child->start_time <<= 32;      child->start_time |= st.dwLowDateTime;      if (*(news = ptrest) != '[')	child->saw_stars = 2;      else	{	  child->saw_stars++;	  while ((news = strchr (news, ' ')) != NULL && *++news != '*')	    child->nfields++;	  if (news == NULL)	    child->saw_stars++;	  else	    {	      s = news;

⌨️ 快捷键说明

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