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 {
|
Event neg_sink_parm_call: |
Passing "fd" to "close", which cannot accept a negative. |
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)
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 ) {
|
Event negative_return: |
Calling "open", which might return a negative value. |
|
Event return_negative_fn: |
Returning the return value of "open", which might be negative. |
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