/***************************************************************************/
/*                                                                         */
/*  procdbg.h  - Exported function definitions for low level process       */
/*               debugging routines in procdbg.c. Also contains critical   */
/*               defines for registers, stack alignment etc.               */
/*                                                                         */
/*  Copyright (C) 2000 Shaun Clowes                                        */
/*                                                                         */
/*  This program is free software; you can redistribute it and/or modify   */
/*  it under the terms of version 2 of the GNU General Public License as   */
/*  published by the Free Software Foundation;                             */
/*                                                                         */
/*  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., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                         */
/***************************************************************************/

#ifndef _PROCDBG_H
#define _PROCDBG_H

#include <config.h>
#include <sys/types.h>
#if OS_SOLARIS
   #include <procfs.h>
#elif OS_LINUX
   #include <sys/user.h>
#endif

#if OS_SOLARIS
   typedef struct pstatus SProcStatus;
   #define STOP_SIGNAL 0
#elif OS_LINUX
   typedef struct user SProcStatus;
   #define STOP_SIGNAL SIGSTOP
#endif

int call_proc(void *pvAddr);
void *push_stack_proc(void *pvAddr, int iSize);
size_t read_proc(void *pvAddr, void *pvBuffer, size_t iCount);
size_t write_proc(void *pvAddr, void *pvBuffer, size_t iCount);
size_t read_status(SProcStatus *ptStatus);
size_t write_regs(SProcStatus *ptStatus);
int restore_syscall(SProcStatus *ptStatus, int iOptNoSysRestart);
size_t peek_proc(int iOp, void *pvAddr, void *pvBuffer, size_t iCount, 
                 int iErrorHandle);
size_t poke_proc(int iOp, void *pvAddr, void *pvBuffer, size_t iCount, 
                 int iErrorHandle);
int dump_core();
unsigned long round_down(unsigned long uNum, unsigned long uBase);
unsigned long round_up(unsigned long uNum, unsigned long uBase);
int ptrace_attach(pid_t tAttachPid);
int wait_stop(int iExpectedSignal);
int ptrace_detach();

/* Various defined for registers etc.                                      */
#if CPU_SPARC 
   #define STACK_ALIGN 8    /* Sparc requires 8 byte stack alignment       */
   #define LINKAGE_SPACE 96 /* Required space at top of stack for saved    */
                            /* registers (incase interrupted). This space  */
                            /* must be present at ALL times                */
   #if OS_LINUX
      #define R_G1 0        /* We should probably use the UREG_ defines in */
      #define R_G2 1        /* asm-sparc/ptrace.h for these but it's a     */
      #define R_G3 2        /* pain because the user mode output           */
      #define R_G4 3        /* registers are referred to as input          */
      #define R_G5 4        /* registers (since they are to the kernel).   */
      #define R_G6 5        /* Worse, PTRACE_GETREGS chooses to renumber   */
      #define R_G7 6        /* them all so that UREG_G0 is not included    */
      #define R_O0 7        /* and that entry becomes UREG_G1              */
      #define R_O1 8
      #define R_O2 9
      #define R_O3 10
      #define R_O4 11
      #define R_O5 12
      #define R_O6 13
      #define R_SP R_O6
      #define R_O7 14
      #define R_SPC R_O7
      #define PSR_C 0x00100000 /* Carry bit in PSR (indicates syscall)     */
      #define TRAP ((unsigned long) (0x91d02010))  /* Syscall trap         */
      #define BTRAP ((unsigned long) (0x91d02001)) /* Breakpoint trap      */
      #define PC(status) ((status).regs.pc)
      #define NPC(status) ((status).regs.npc)
      #define SAVEDPC(status) ((status).regs.regs[R_SPC])
      #define SP(status) ((status).regs.regs[R_SP])
   #elif OS_SOLARIS
      #define R_SPC R_O7
      #define PC(status) ((status).pr_lwp.pr_reg[R_PC])
      #define NPC(status) ((status).pr_lwp.pr_reg[R_nPC])
      #define SAVEDPC(status) ((status).pr_lwp.pr_reg[R_SPC])
      #define SP(status) ((status).pr_lwp.pr_reg[R_SP])

      typedef struct _SStopFunc
      {
         unsigned long uFunc;
         unsigned long uArg;
      } SStopFunc;
      
      typedef struct _SRunFunc
      {
         unsigned long uFunc;
         unsigned long uArg;
      } SRunFunc;

      typedef struct _SKillFunc
      {
         unsigned long uFunc;
         unsigned long uArg;
      } SKillFunc;

      typedef struct _STraceFunc
      {
         unsigned long uFunc;
         sigset_t tSignals;
      } STraceFunc;

      typedef struct _SWriteRegsFunc
      {
         unsigned long uFunc;
         prgregset_t tRegs;
      } SWriteRegsFunc;

   #endif
#elif CPU_IA32
   #define PC(status) ((status).regs.eip)
   #define NPC(status) 0
   #define SP(status) ((status).regs.esp)
   #define STACK_ALIGN 4
#endif

#endif
