Code Search for Developers
 
 
  

child_process.cc from Gdb at Krugle


Show child_process.cc syntax highlighted

/* child_process.cc

   Copyright 2000, 2002 Red Hat, Inc.

   This file is part of RDA, the Red Hat Debug Agent (and library).

   This program 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 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 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 this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
   
   Alternative licenses for RDA may be arranged by contacting Red Hat,
   Inc.  */

#include "config.h"

#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#if !HAVE_WINDOWS_H
#error The windows.h header is required when compiling for a Win32 target.
#endif
#include <windows.h>
#include <sys/cygwin.h>

#include "server.h"

struct {
  DWORD exc;
  const char *exc_txt;
  DWORD sig;
} sigmap[] = {
  EXCEPTION_ACCESS_VIOLATION,	   "EXCEPTION_ACCESS_VIOLATION",	SIGSEGV,
  EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED",	SIGSEGV,
  EXCEPTION_BREAKPOINT,		   "EXCEPTION_BREAKPOINT",		SIGTRAP,
  EXCEPTION_DATATYPE_MISALIGNMENT, "EXCEPTION_DATATYPE_MISALIGNMENT",	SIGBUS,
  EXCEPTION_FLT_DENORMAL_OPERAND,  "EXCEPTION_FLT_DENORMAL_OPERAND",	SIGFPE,
  EXCEPTION_FLT_DIVIDE_BY_ZERO,	   "EXCEPTION_FLT_DIVIDE_BY_ZERO",	SIGFPE,
  EXCEPTION_FLT_INEXACT_RESULT,	   "EXCEPTION_FLT_INEXACT_RESULT",	SIGFPE,
  EXCEPTION_FLT_INVALID_OPERATION, "EXCEPTION_FLT_INVALID_OPERATION",	SIGILL,
  EXCEPTION_FLT_OVERFLOW,	   "EXCEPTION_FLT_OVERFLOW",		SIGFPE,
  EXCEPTION_FLT_STACK_CHECK,	   "EXCEPTION_FLT_STACK_CHECK",		SIGFPE,
  EXCEPTION_FLT_UNDERFLOW,	   "EXCEPTION_FLT_UNDERFLOW",		SIGFPE,
  EXCEPTION_ILLEGAL_INSTRUCTION,   "EXCEPTION_ILLEGAL_INSTRUCTION",	SIGILL,
  EXCEPTION_IN_PAGE_ERROR,	   "EXCEPTION_IN_PAGE_ERROR",		SIGSEGV,
  EXCEPTION_INT_DIVIDE_BY_ZERO,	   "EXCEPTION_INT_DIVIDE_BY_ZERO",	SIGFPE,
  EXCEPTION_INT_OVERFLOW,	   "EXCEPTION_INT_OVERFLOW",		SIGFPE,
  EXCEPTION_INVALID_DISPOSITION,   "EXCEPTION_INVALID_DISPOSITION",	SIGILL,
  EXCEPTION_NONCONTINUABLE_EXCEPTION,
  				   "EXCEPTION_NONCONTINUABLE_EXCEPTION",SIGILL,
  EXCEPTION_PRIV_INSTRUCTION,	   "EXCEPTION_PRIV_INSTRUCTION",	SIGILL,
  EXCEPTION_SINGLE_STEP,	   "EXCEPTION_SINGLE_STEP",		SIGTRAP,
  EXCEPTION_STACK_OVERFLOW,	   "EXCEPTION_STACK_OVERFLOW",		SIGSEGV,
  DBG_CONTROL_C,		   "DBG_CONTROL_C",			SIGINT,
  0,				   "Unknown exception",			SIGUSR1
};

/* Debug output method similar to fprintf. */
void
child_process::debug (const char *format, ...)
{
  if (!debug_backend)
    return;
  
  va_list ap;

  va_start (ap, format);
  vfprintf (stderr, format, ap);
  va_end (ap);
}

void
child_process::handle_exception (DEBUG_EVENT &ev)
{
  DWORD exc_code = ev.u.Exception.ExceptionRecord.ExceptionCode;
  DWORD exc_flag = ev.u.Exception.ExceptionRecord.ExceptionFlags;

  int i;
  for (i = 0; sigmap[i].exc && sigmap[i].exc != exc_code; ++i)
    ;

  debug ("Win32: Got exception 0x%08x = \"%s\", mapped to signal %d\n",
  	   	  exc_code, sigmap[i].exc_txt, sigmap[i].sig);

  if (exc_flag == EXCEPTION_NONCONTINUABLE)
    set_term (sigmap[i].sig);
  else
    set_break (sigmap[i].sig);
}

/* fetch registers vector. */
void
child_process::fetch_regs ()
{
  if (!suspend_cnt)
    {
      HANDLE thread_hdl = threads[cur_thread_id];
      suspend_cnt = SuspendThread (thread_hdl) + 1;
      context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
      GetThreadContext (thread_hdl, &context);
    }
}

void
child_process::store_regs ()
{
  SetThreadContext (threads[cur_thread_id], &context);
}

BOOL
child_process::resume_program (BOOL step)
{
  fetch_regs ();

  if (step)
    context.EFlags |= FLAG_TRACE_BIT;

  store_regs ();

  if (ContinueDebugEvent (cur_process_id,
  			  cur_thread_id,
			  stop_signal () && stop_signal () != SIGTRAP
			  ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE))
    {
      int i;

      for (i = 0; i < suspend_cnt; ++i)
        ResumeThread (threads[cur_thread_id]);
      suspend_cnt = 0;
      set_running ();
      return TRUE;
    }
  return FALSE;
}

void
child_process::load_dll_event (DEBUG_EVENT &ev)
{
  void *ptr;
  char buf[512];
  DWORD processed = 0;

  if (!debug ())
    return;

  if (ev.dwProcessId == process_id
      && ev.u.LoadDll.lpImageName
      && ReadProcessMemory (process_hdl, ev.u.LoadDll.lpImageName,
                            &ptr, sizeof ptr, &processed)
      && ptr
      && ReadProcessMemory (process_hdl, ptr, 
                            buf, sizeof buf, &processed))
    {
      buf[511] = '\0';
      char *name = buf;
      if (ev.u.LoadDll.fUnicode)
	{
	  name = (char *) alloca (256);
	  WideCharToMultiByte (CP_ACP, 0, (const WCHAR *) buf, -1,
			       name, 256, NULL, NULL);
	}
      debug ("Win32: Load DLL \"%s\"\n", name);
    }
  else
    debug ("Win32: Load DLL\n");
}

BOOL
child_process::create_child ()
{
  char real_path[PATH_MAX];
  char *winenv;
  char *temp;
  int envlen;
  int len, i;
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  BOOL ret;
  DWORD flags;
  char *args;

  memset (&si, 0, sizeof (si));
  si.cb = sizeof (si);

  cygwin_conv_to_win32_path (executable, real_path);

  flags = DEBUG_ONLY_THIS_PROCESS;

  if (new_group)
    flags |= CREATE_NEW_PROCESS_GROUP;

  if (new_console)
    flags |= CREATE_NEW_CONSOLE;

  len = strlen (real_path);
  for (i = 1; i < argc; ++i)
    len += strlen (argv[i]) + 1;
  
  args = (char *) alloca (len + 2);

  strcpy (args, real_path);

  for (i = 1; i < argc; ++i)
    {
      strcat (args, " ");
      strcat (args, argv[i]);
    }

  SetConsoleCtrlHandler (NULL, 0);
  ret = CreateProcess (0,
                       args,    /* command line */
                       NULL,    /* Security */
                       NULL,    /* thread */
                       TRUE,    /* inherit handles */
                       flags,   /* start flags */
                       NULL,
                       NULL,    /* current directory */
                       &si,
                       &pi);
  if (!ret)
    return FALSE;

  process_id = pi.dwProcessId;

  return TRUE;
}

int
child_process::check_state ()
{
  static DEBUG_EVENT ev;

#if 0
  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
#endif

  if (!WaitForDebugEvent (&ev, 1000))
    return 0;

  /* found an event */

  cur_process_id = ev.dwProcessId;
  cur_thread_id = ev.dwThreadId;

  fetch_regs ();

  switch (ev.dwDebugEventCode)
    {
    case CREATE_PROCESS_DEBUG_EVENT:
      if (ev.dwProcessId != process_id)
        {
          debug ("Win32: Inferior process created\n");
	  set_break (SIGTRAP);
	  return 1;
	}
      else
        debug ("Win32: A child process was created\n");
      process_hdl = ev.u.CreateProcessInfo.hProcess;
      threads += ev;
      break;

    case CREATE_THREAD_DEBUG_EVENT:
      debug ("Win32: Create Thread\n");
      if (ev.dwProcessId == process_id)
	threads += ev;
      break;

    case LOAD_DLL_DEBUG_EVENT:
      load_dll_event (ev);
      break;

    case UNLOAD_DLL_DEBUG_EVENT:
      debug ("Win32: Unload DLL\n");
      break;

    case OUTPUT_DEBUG_STRING_EVENT:
      debug ("Win32: OutputDebugString\n");
      if (ev.dwProcessId == process_id
          && win32_output_debug_string (this, ev))
	return 1;
      break;

    case EXIT_PROCESS_DEBUG_EVENT:
      if (ev.dwProcessId == process_id)
        {
          debug ("Win32: Inferior exited with retcode = %d\n",
                          ev.u.ExitProcess.dwExitCode);
	  set_exit (ev.u.ExitProcess.dwExitCode);
	  return 1;
	}
      else
        debug ("Win32: Some child exited with retcode = %d\n",
                        ev.u.ExitProcess.dwExitCode);
      break;

    case EXIT_THREAD_DEBUG_EVENT:
      debug ("Win32: Thread exited with retcode = %d\n",
      	       ev.u.ExitThread.dwExitCode);
      threads -= ev;
      /* What to return??? */
      break;

    case EXCEPTION_DEBUG_EVENT:
      handle_exception (ev);
      return 1;
    }

  if (!resume_program (FALSE))
    {
      set_term (SIGILL);
      return 1;
    }
  return 0;
}

void
child_process::fromtarget_break ()
{
  debug ("Win32: from_target break\n");
  gdbserv_fromtarget_break (serv, stop_signal ());
}

void
child_process::fromtarget_exit ()
{
  debug ("Win32: from_target exit\n");
  gdbserv_fromtarget_exit (serv, exit_code ());
}

void
child_process::fromtarget_terminate ()
{
  debug ("Win32: from_target terminate\n");
  gdbserv_fromtarget_terminate (serv, term_signal ());
}





See more files for this project here

Gdb

GDB, the GNU Project debugger, allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed.

Project homepage: http://sources.redhat.com/gdb/
Programming language(s): Assembly,C,C++,Expect
License: other

  ChangeLog
  Makefile.am
  Makefile.in
  aclocal.m4
  child_process.cc
  config.in
  configure
  configure.in
  server.cc
  server.h
  stamp-h.in
  win32-strace.cc
  win32-target.cc