/***************************************************************************/
/*                                                                         */
/*  intercept.h - Function prototypes and external variable declarations   */
/*                for optional interception routines in injection          */
/*                libraries                                                */
/*                                                                         */
/*  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 _INTERCEPT_H
#define _INTERCEPT_H

#include <config.h>

typedef struct _SIntercept {
   char *sFuncName;     /* Name of function to be intercepted              */
   void *pvNewFunc;     /* Function to which the call should be redirected */
   void *pvRelAddr;     /* Pointer to where the relocation entry for this  */
                        /* function points. On Linux x86 this is actually  */
                        /* the location of an address in the GOT where     */
                        /* the address of the function is stored. On       */
                        /* Linux and Solaris Sparc it is actually the      */
                        /* address of the PLT routine for the function     */
   void **ppvOldAddr;   /* Address of a pointer into which the address of  */
                        /* the original function should be stored          */
   int  iFlags;         /* Flags for this symbol's interception, see below */
} SIntercept;

/* The following flags are valid in the iFlags field of the SIntercept     */
/* structure                                                               */
#define int_ignore (1 << 0)           /* Ignore this entry, do not pass go */
                                      /* do not collect $200               */
                                      /* (Not currently implemented)       */
#define int_always_overwrite (1 << 1) /* Always overwrite the PLT pointer  */
                                      /* to this function on calls to      */
                                      /* intercept_check() even if the     */
                                      /* function appears to have already  */
                                      /* been lazily resolved (and thus    */
                                      /* should not change)                */
                                      /* (Not currently implemented)       */
#define int_always_find (1 << 2)      /* Always find this symbols          */
                                      /* relocation (and Got entry) again  */
                                      /* on every call to intercept_check  */
                                      /* i.e set pvGotAddr every time      */
                                      /* (Not currently implemented)       */
#define int_redirect_prologue (1 << 3)/* Intercept the call by overwriting */
                                      /* the function prologue instead of  */
                                      /* changing the PLT                  */
                                      /* (Not currently implemented)       */

/* Users of the intercept routines need to define a null terminated array  */
/* of functions they wish to override called pptInterceptFuncs (made up of */
/* pointers to SIntercept structs                                          */
/* TODO: Define a weak sym with an empty array so that people can choose   */
/*       not to provice anything here                                      */
extern SIntercept *pptInterceptFuncs[];

/* If the following flag is set to true (its off by default) the routines */
/* will output debugging information to stderr                            */
extern int iInterceptDebug;

/* Patch the PLT to redirect the functions to be intercepted to their     */
/* nominated replacements. For symbols that have not yet been lazily      */
/* bound this function MUST be called after a call to the old function    */
/* since our patch will have been overwritten by the dynamic linker       */
/* A particular entry to override can be specified (which is more         */
/* efficient) but if NULL is specified all the tInterceptFuncs will be    */
/* overriden as necessary                                                 */
extern int intercept_override(SIntercept *pvEntry);

/* On Sparc when intercept_override redirects the PLT entry for a         */
/* function that has not yet been lazily bound it is forced to overwrite  */
/* the entry in such a way that it is impossible to call the old function */
/* (and have it resolved) without restoring the PLT entry and then        */
/* calling it. This function does just that for a specified function or   */
/* for all unresolved functions if NULL is specified. On IA32 this        */
/* function has no meaning and is defined to nothing. Calls to this       */
/* function should always be followed by calls to intercept_override to   */
/* insure the PLT redirection remains in effect (is not overwritten by    */
/* the dynamic linker)                                                    */
#if CPU_SPARC
   extern int intercept_fix_unresolved(SIntercept *pvEntry);
#else
   #define intercept_fix_unresolved(x)
#endif

/* TODO: (or more to think about) we can modify the relocation of the     */
/* function to point to some memory we've allocated, copy the normal      */
/* relocation, patch in the replacement function and set the old address  */
/* to the replacement relocation area (we can call mprotect() to allow    */
/* execution etc). Although obviously PaX with restrict mprotect won't    */
/* like that very much, but there are heaps of ways around that, like     */
/* making a really long function and mprotecting it to be writable and    */
/* the using the executable space there (in the "code" segment)           */
/* We could also set the old address to an address known to segfault and  */
/* intercept it and restore the right address, but that still leaves us   */
/* with a question of how to restore the PLT patch after execution of the */
/* function                                                               */

#endif
