1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2010 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3    	 *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
4    	 *                                                                          *
5    	 *   This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/src is free software: you can redistribute it and/or        *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	
23   	#define _GNU_SOURCE
24   	#define _XOPEN_SOURCE 500
25   	// These next two are defined in features.h based on the user macros above.
26   	// #define GNU_SRC
27   	// #define __USE_UNIX98
28   	
29   	#include <pthread.h>
30   	#include "syscallwrappers.h"
31   	// We should not need dlopen/dlsym
32   	// #include <dlfcn.h>
33   	#include <stdio.h>
34   	#include <stdlib.h>
35   	#include <string.h>
36   	#include "constants.h"
37   	#include "sockettable.h"
38   	#include <sys/select.h>
39   	#include <sys/time.h>
40   	#include <sys/types.h>
41   	#include <sys/stat.h>
42   	#include <fcntl.h>
43   	#include <sys/syscall.h>
44   	#include <unistd.h>
45   	#include <ctype.h>
46   	#include <syslog.h>
47   	
48   	
49   	// See syscallsreal.c for original model.  In dmtcphijack.so, system calls
50   	//   for XXX() in jalib call a wrapper which modifies it and calls
51   	//   syscallsreal.c:_real_XXX(), to directly calls kernel.
52   	// For other functions (dmtcp_checkpoint, dmtcp_restart, etc.),
53   	//   we want their invocations of jalib to directly call glibc with no wrappers.
54   	// Jalib has some calls to real_XXX() to avoid going through the wrapper.
55   	//   Those are defined in syscallsreal.cpp, but this is a simpler interface
56   	//   that avoids calling on dlsym() and syscallsreal.cpp (by calling this
57   	//   smaller image, jnosyscallsreal.cpp), in order to keep those
58   	//   binaries smaller, and to keep the code simpler and more maintainable.
59   	//   Can add wrapper code for libhijack.so without fear of contaminating
60   	//   the other DMTCP executables with that wrapper.
61   	
62   	// NOTE:  An alternative to this strategy would be to put this in a file,
63   	//   nosyscallwrappers.h and #define away the real_XXX() calls.
64   	//   But some files like uniquepid.cpp and connection.cpp could be
65   	//   linked either to dmtcphijack.so or to dmtcp_restart.
66   	
67   	/// FIXME:  dmtcpworker.cpp is linked into some ordinary executables.
68   	///         It should be modified to avoid this, so we don't need gratuitous
69   	///         extra reall_syscalls here like dmtcp_unsetenv(), dmtcp_lock()
70   	
71   	//////////////////////////
72   	//// DEFINE REAL VERSIONS OF NEEDED FUNCTIONS (based on syscallsreal.cpp)
73   	//// (Define only functions needed for dmtcp_checkpoint, dmtcp_restart, etc.
74   	
75   	static pthread_mutex_t theMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
76   	
77   	void _dmtcp_lock() { pthread_mutex_lock ( &theMutex ); }
78   	
79   	void _dmtcp_unlock() { pthread_mutex_unlock ( &theMutex ); }
80   	
81   	#define REAL_FUNC_PASSTHROUGH(name) return name
82   	
83   	#define REAL_FUNC_PASSTHROUGH_TYPED(type,name) REAL_FUNC_PASSTHROUGH(name)
84   	
85   	#define REAL_FUNC_PASSTHROUGH_PID_T(name) REAL_FUNC_PASSTHROUGH(name)
86   	
87   	// No return statement for functions returning void:
88   	#define REAL_FUNC_PASSTHROUGH_VOID(name) name
89   	
90   	/// call the libc version of this function via dlopen/dlsym
91   	int _real_socket ( int domain, int type, int protocol )
92   	{
93   	  REAL_FUNC_PASSTHROUGH ( socket ) ( domain,type,protocol );
94   	}
95   	
96   	/// call the libc version of this function via dlopen/dlsym
97   	int _real_connect ( int sockfd,  const  struct sockaddr *serv_addr, socklen_t addrlen )
98   	{
99   	  REAL_FUNC_PASSTHROUGH ( connect ) ( sockfd,serv_addr,addrlen );
100  	}
101  	
102  	/// call the libc version of this function via dlopen/dlsym
103  	int _real_bind ( int sockfd,  const struct  sockaddr  *my_addr,  socklen_t addrlen )
104  	{
105  	  REAL_FUNC_PASSTHROUGH ( bind ) ( sockfd,my_addr,addrlen );
106  	}
107  	
108  	/// call the libc version of this function via dlopen/dlsym
109  	int _real_listen ( int sockfd, int backlog )
110  	{
111  	  REAL_FUNC_PASSTHROUGH ( listen ) ( sockfd,backlog );
112  	}
113  	
114  	/// call the libc version of this function via dlopen/dlsym
115  	int _real_accept ( int sockfd, struct sockaddr *addr, socklen_t *addrlen )
116  	{
117  	  REAL_FUNC_PASSTHROUGH ( accept ) ( sockfd,addr,addrlen );
118  	}
119  	
120  	/// call the libc version of this function via dlopen/dlsym
121  	int _real_setsockopt ( int s, int  level,  int  optname,  const  void  *optval,
122  	                       socklen_t optlen )
123  	{
124  	  REAL_FUNC_PASSTHROUGH ( setsockopt ) ( s,level,optname,optval,optlen );
125  	}
126  	
127  	int _real_execve ( const char *filename, char *const argv[],
128  	                   char *const envp[] )
129  	{
130  	  REAL_FUNC_PASSTHROUGH ( execve ) ( filename,argv,envp );
131  	}
132  	
133  	int _real_execv ( const char *path, char *const argv[] )
134  	{
135  	  REAL_FUNC_PASSTHROUGH ( execv ) ( path,argv );
136  	}
137  	
138  	int _real_execvp ( const char *file, char *const argv[] )
139  	{
140  	  REAL_FUNC_PASSTHROUGH ( execvp ) ( file,argv );
141  	}
142  	
143  	int _real_system ( const char *cmd )
144  	{
145  	  REAL_FUNC_PASSTHROUGH ( system ) ( cmd );
146  	}
147  	
148  	pid_t _real_fork( void )
149  	{
150  	  REAL_FUNC_PASSTHROUGH_PID_T ( fork ) ();
151  	}
152  	
153  	int _real_close ( int fd )
154  	{
155  	  REAL_FUNC_PASSTHROUGH ( close ) ( fd );
156  	}
157  	
158  	void _real_exit ( int status )
159  	{
160  	  REAL_FUNC_PASSTHROUGH_VOID ( exit ) ( status );
161  	}
162  	
163  	int _real_ptsname_r ( int fd, char * buf, size_t buflen )
164  	{
165  	  REAL_FUNC_PASSTHROUGH ( ptsname_r ) ( fd, buf, buflen );
166  	}
167  	
168  	int _real_socketpair ( int d, int type, int protocol, int sv[2] )
169  	{
170  	  REAL_FUNC_PASSTHROUGH ( socketpair ) ( d,type,protocol,sv );
171  	}
172  	
173  	void _real_openlog ( const char *ident, int option, int facility )
174  	{
175  	  REAL_FUNC_PASSTHROUGH_VOID ( openlog ) ( ident,option,facility );
176  	}
177  	
178  	void _real_closelog ( void )
179  	{
180  	  REAL_FUNC_PASSTHROUGH_VOID ( closelog ) ();
181  	}
182  	
183  	int _dmtcp_unsetenv( const char *name ) {
184  	  REAL_FUNC_PASSTHROUGH ( unsetenv ) ( name );
185  	}
186  	
187  	#ifdef PID_VIRTUALIZATION
188  	pid_t _real_getpid(void){
189  	  REAL_FUNC_PASSTHROUGH_PID_T ( getpid ) ( );
190  	}
191  	
192  	pid_t _real_getppid(void){
193  	  REAL_FUNC_PASSTHROUGH_PID_T ( getppid ) ( );
194  	}
195  	
196  	int _real_tcsetpgrp(int fd, pid_t pgrp){
197  	  REAL_FUNC_PASSTHROUGH ( tcsetpgrp ) ( fd, pgrp );
198  	}
199  	
200  	int _real_tcgetpgrp(int fd) {
201  	  REAL_FUNC_PASSTHROUGH ( tcgetpgrp ) ( fd );
202  	}
203  	
204  	pid_t _real_getpgrp(void) {
205  	  REAL_FUNC_PASSTHROUGH_PID_T ( getpgrp ) ( );
206  	}
207  	
208  	pid_t _real_setpgrp(void) {
209  	  REAL_FUNC_PASSTHROUGH_PID_T ( setpgrp ) ( );
210  	}
211  	
212  	pid_t _real_getpgid(pid_t pid) {
213  	  REAL_FUNC_PASSTHROUGH_PID_T ( getpgid ) ( pid );
214  	}
215  	
216  	int   _real_setpgid(pid_t pid, pid_t pgid) {
217  	  REAL_FUNC_PASSTHROUGH ( setpgid ) ( pid, pgid );
218  	}
219  	
220  	pid_t _real_getsid(pid_t pid) {
221  	  REAL_FUNC_PASSTHROUGH_PID_T ( getsid ) ( pid );
222  	}
223  	
224  	pid_t _real_setsid(void) {
225  	  REAL_FUNC_PASSTHROUGH_PID_T ( setsid ) ( );
226  	}
227  	
228  	int   _real_kill(pid_t pid, int sig) {
229  	  REAL_FUNC_PASSTHROUGH ( kill ) ( pid, sig );
230  	}
231  	
232  	pid_t _real_wait(__WAIT_STATUS stat_loc) {
233  	  REAL_FUNC_PASSTHROUGH_PID_T ( wait ) ( stat_loc );
234  	}
235  	
236  	pid_t _real_waitpid(pid_t pid, int *stat_loc, int options) {
237  	  REAL_FUNC_PASSTHROUGH_PID_T ( waitpid ) ( pid, stat_loc, options );
238  	}
239  	
240  	int   _real_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
241  	  REAL_FUNC_PASSTHROUGH ( waitid ) ( idtype, id, infop, options );
242  	}
243  	
244  	pid_t _real_wait3(__WAIT_STATUS status, int options, struct rusage *rusage) {
245  	  REAL_FUNC_PASSTHROUGH_PID_T ( wait3 ) ( status, options, rusage );
246  	}
247  	
248  	pid_t _real_wait4(pid_t pid, __WAIT_STATUS status, int options, struct rusage *rusage) {
249  	  REAL_FUNC_PASSTHROUGH_PID_T ( wait4 ) ( pid, status, options, rusage );
250  	}
251  	
252  	int send_sigwinch; /* not used.  Only version in pidwrappers.cpp is used */
253  	int _real_ioctl(int d, unsigned long int request, ...) {
254  	  int i;
255  	  void * arg;
256  	  va_list ap;
257  	
258  	  // Most calls to ioctl take 'void *', 'int' or no extra argument
259  	  // A few specialized ones take more args, but we don't need to handle those.
260  	  va_start(ap, request);
261  	  arg = va_arg(ap, void *);
262  	  va_end(ap);
263  	
264  	  // /usr/include/unistd.h says syscall returns long int (contrary to man page)
Event implicit_func_decl: function "ioctl" declared implicitly
Event caretline: ^
265  	  REAL_FUNC_PASSTHROUGH_TYPED ( int, ioctl ) ( d, request, arg );
266  	}
267  	
268  	#endif
269  	
270  	// Needed for _real_gettid, etc.
271  	long int _real_syscall(long int sys_num, ... ) {
272  	  int i;
273  	  void * arg[7];
274  	  va_list ap;
275  	
276  	  va_start(ap, sys_num);
277  	  for (i = 0; i < 7; i++)
278  	    arg[i] = va_arg(ap, void *);
279  	  va_end(ap);
280  	
281  	  // /usr/include/unistd.h says syscall returns long int (contrary to man page)
282  	  REAL_FUNC_PASSTHROUGH_TYPED ( long int, syscall ) ( sys_num, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6] );
283  	}
284  	
285  	// gettid / tkill / tgkill are not defined in libc.
286  	// So, this is needed even if there is no PID_VIRTUALIZATION.
287  	pid_t _real_gettid(void){
288  	#ifdef PID_VIRTUALIZATION
289  	// IS THIS LIKE ORIGINAL?
290  	  REAL_FUNC_PASSTHROUGH_PID_T ( _real_syscall(SYS_gettid) );
291  	#else
292  	  REAL_FUNC_PASSTHROUGH_PID_T ( syscall(SYS_gettid) );
293  	#endif
294  	}
295  	
296  	int _real_open ( const char *pathname, int flags, mode_t mode ) {
297  	  REAL_FUNC_PASSTHROUGH ( open ) ( pathname, flags, mode );
298  	}
299  	
300  	int _real_shmget (key_t key, size_t size, int shmflg) {
301  	  REAL_FUNC_PASSTHROUGH ( shmget ) (key, size, shmflg);
302  	}
303  	
304  	void* _real_shmat (int shmid, const void *shmaddr, int shmflg) {
305  	  REAL_FUNC_PASSTHROUGH_TYPED ( void*, shmat ) (shmid, shmaddr, shmflg);
306  	}
307  	
308  	int _real_shmdt (const void *shmaddr) {
309  	  REAL_FUNC_PASSTHROUGH ( shmdt ) (shmaddr);
310  	}
311  	
312  	int _real_shmctl (int shmid, int cmd, struct shmid_ds *buf) {
313  	  REAL_FUNC_PASSTHROUGH ( shmctl ) (shmid, cmd, buf);
314  	}
315  	
316