/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- pid_initialize_wrappers
- _real_dlsym
- _real_getpid
- _real_getppid
- _real_tcgetsid
- _real_tcsetpgrp
- _real_tcgetpgrp
- _real_getpgrp
- _real_setpgrp
- _real_getpgid
- _real_setpgid
- _real_getsid
- _real_setsid
- _real_kill
- _real_wait
- _real_waitpid
- _real_waitid
- _real_wait3
- _real_wait4
- _real_ioctl
- _real_setgid
- _real_setuid
- _real_ptrace
- _real_gettid
- _real_tkill
- _real_tgkill
- _real_syscall
- _real_fork
- _real_clone
- _real_shmget
- _real_shmat
- _real_shmdt
- _real_shmctl
- _real_semctl
- _real_msgctl
- _real_mq_notify
- _real_clock_getcpuclockid
- _real_timer_create
- _real_pthread_exit
- _real_fcntl
- _real_open
- _real_open64
- _real_fopen
- _real_fopen64
- _real_fclose
- _real_xstat
- _real_xstat64
- _real_lxstat
- _real_lxstat64
- _real_readlink
1 /****************************************************************************
2 * Copyright (C) 2006-2013 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 #include <dlfcn.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/syscall.h>
32 #include <unistd.h>
33 #include "pidwrappers.h"
34
35 typedef int ( *funcptr_t ) ();
36 typedef pid_t ( *funcptr_pid_t ) ();
37 typedef funcptr_t ( *signal_funcptr_t ) ();
38 typedef void* (*dlsym_fnptr_t) (void *handle, const char *symbol);
39
40 static void *pid_real_func_addr[numPidVirtWrappers];
41 static int pid_wrappers_initialized = 0;
42
43 #define GET_FUNC_ADDR(name) \
44 pid_real_func_addr[PIDVIRT_ENUM(name)] = _real_dlsym(RTLD_NEXT, #name);
45
46 #define GET_FUNC_ADDR_V(name, v) \
47 pid_real_func_addr[PIDVIRT_ENUM(name)] = dlvsym(RTLD_NEXT, #name, v); \
48 if (pid_real_func_addr[PIDVIRT_ENUM(name)] == NULL) { \
49 /* Symbol version not found, try the default and hope for the best */ \
50 GET_FUNC_ADDR(name); \
51 }
52
53 #ifdef __i386__
54 // On 32-bit Linuxes, glibc provides two versions (GLIBC_2.0 and GLIBC_2.2) for
55 // semctl, msgctl and shmctl. dlsym(RTLD_NEXT, ...) returns the address of the
56 // GLIBC_2.0 version, whereas we need the GLIBC_2.2 version. In 64-bit glibc,
57 // there is only one version.
58 // Similarly, for fopen/fclose/fdopen, there is a GLIBC_2.1 in addition to
59 // GLIBC_2.0 version.
60 # define GET_SYSVIPC_CTL_FUNC_ADDR(name) GET_FUNC_ADDR_V(name, "GLIBC_2.2")
61 # define GET_FOPEN_FUNC_ADDR(name) GET_FUNC_ADDR_V(name, "GLIBC_2.1")
62 #else
63 # define GET_SYSVIPC_CTL_FUNC_ADDR(name) GET_FUNC_ADDR(name)
64 # define GET_FOPEN_FUNC_ADDR(name) GET_FUNC_ADDR(name)
65 #endif
66
67 LIB_PRIVATE
68 void pid_initialize_wrappers()
69 {
70 if (!pid_wrappers_initialized) {
71 FOREACH_PIDVIRT_WRAPPER(GET_FUNC_ADDR);
72 FOREACH_SYSVIPC_CTL_WRAPPER(GET_SYSVIPC_CTL_FUNC_ADDR);
73 FOREACH_FOPEN_WRAPPER(GET_FOPEN_FUNC_ADDR);
74 pid_wrappers_initialized = 1;
75 }
76 }
77
78
79 #define REAL_FUNC_PASSTHROUGH_WORK(name) \
80 if (fn == NULL) { \
81 if (pid_real_func_addr[PIDVIRT_ENUM(name)] == NULL) \
82 pid_initialize_wrappers(); \
83 fn = pid_real_func_addr[PIDVIRT_ENUM(name)]; \
84 if (fn == NULL) { \
85 fprintf(stderr, "%s:%d: *** DMTCP: Error: lookup failed for %s.\n" \
86 " The symbol wasn't found in current library" \
87 " loading sequence.\n" \
88 " Aborting.\n", __FILE__, __LINE__, #name); \
89 abort(); \
90 } \
91 }
92
93 #define REAL_FUNC_PASSTHROUGH(name) REAL_FUNC_PASSTHROUGH_TYPED(int, name)
94
95 #define REAL_FUNC_PASSTHROUGH_TYPED(type,name) \
96 static type (*fn)() = NULL; \
97 REAL_FUNC_PASSTHROUGH_WORK(name) \
98 return (*fn)
99
100 #define REAL_FUNC_PASSTHROUGH_VOID(name) \
101 static void (*fn)() = NULL; \
102 REAL_FUNC_PASSTHROUGH_WORK(name) \
103 (*fn)
104
105 #define REAL_FUNC_PASSTHROUGH_NORETURN(name) \
106 static void (*fn)() __attribute__ ((__noreturn__)) = NULL; \
107 REAL_FUNC_PASSTHROUGH_WORK(name) \
108 (*fn)
109
110 void *dmtcp_get_libc_dlsym_addr();
111
112 LIB_PRIVATE
113 void *_real_dlsym ( void *handle, const char *symbol ) {
114 static dlsym_fnptr_t _libc_dlsym_fnptr = NULL;
115 if (_libc_dlsym_fnptr == NULL) {
116 _libc_dlsym_fnptr = (dlsym_fnptr_t) dmtcp_get_libc_dlsym_addr();
117 }
118
119 return (void*) (*_libc_dlsym_fnptr) ( handle, symbol );
120 }
121
122
123 LIB_PRIVATE
124 pid_t _real_getpid(void){
125 // libc caches pid of the process and hence after restart, libc:getpid()
126 // returns the pre-ckpt value.
127 return (pid_t) _real_syscall(SYS_getpid);
128 }
129
130 LIB_PRIVATE
131 pid_t _real_getppid(void){
132 // libc caches ppid of the process and hence after restart, libc:getppid()
133 // returns the pre-ckpt value.
134 return (pid_t) _real_syscall(SYS_getppid);
135 }
136
137 LIB_PRIVATE
138 pid_t _real_tcgetsid(int fd){
139 REAL_FUNC_PASSTHROUGH ( tcgetsid ) ( fd );
140 }
141
142 LIB_PRIVATE
143 int _real_tcsetpgrp(int fd, pid_t pgrp){
144 REAL_FUNC_PASSTHROUGH ( tcsetpgrp ) ( fd, pgrp );
145 }
146
147 LIB_PRIVATE
148 pid_t _real_tcgetpgrp(int fd) {
149 REAL_FUNC_PASSTHROUGH ( tcgetpgrp ) ( fd );
150 }
151
152 LIB_PRIVATE
153 pid_t _real_getpgrp(void) {
154 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, getpgrp ) ( );
155 }
156
157 LIB_PRIVATE
158 pid_t _real_setpgrp(void) {
159 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, setpgrp ) ( );
160 }
161
162 LIB_PRIVATE
163 pid_t _real_getpgid(pid_t pid) {
164 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, getpgid ) ( pid );
165 }
166
167 LIB_PRIVATE
168 int _real_setpgid(pid_t pid, pid_t pgid) {
169 REAL_FUNC_PASSTHROUGH ( setpgid ) ( pid, pgid );
170 }
171
172 LIB_PRIVATE
173 pid_t _real_getsid(pid_t pid) {
174 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, getsid ) ( pid );
175 }
176
177 LIB_PRIVATE
178 pid_t _real_setsid(void) {
179 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, setsid ) ( );
180 }
181
182 LIB_PRIVATE
183 int _real_kill(pid_t pid, int sig) {
184 REAL_FUNC_PASSTHROUGH ( kill ) ( pid, sig );
185 }
186
187 LIB_PRIVATE
188 pid_t _real_wait(__WAIT_STATUS stat_loc) {
189 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, wait ) ( stat_loc );
190 }
191
192 LIB_PRIVATE
193 pid_t _real_waitpid(pid_t pid, int *stat_loc, int options) {
194 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, waitpid ) ( pid, stat_loc, options );
195 }
196
197 LIB_PRIVATE
198 int _real_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
199 REAL_FUNC_PASSTHROUGH ( waitid ) ( idtype, id, infop, options );
200 }
201
202 LIB_PRIVATE
203 pid_t _real_wait3(__WAIT_STATUS status, int options, struct rusage *rusage) {
204 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, wait3 ) ( status, options, rusage );
205 }
206
207 LIB_PRIVATE
208 pid_t _real_wait4(pid_t pid, __WAIT_STATUS status, int options, struct rusage *rusage) {
209 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, wait4 ) ( pid, status, options, rusage );
210 }
211
212 LIB_PRIVATE
213 int _real_ioctl(int d, unsigned long int request, ...) {
214 void * arg;
215 va_list ap;
216
217 // Most calls to ioctl take 'void *', 'int' or no extra argument
218 // A few specialized ones take more args, but we don't need to handle those.
219 va_start(ap, request);
220 arg = va_arg(ap, void *);
221 va_end(ap);
222
223 // /usr/include/unistd.h says syscall returns long int (contrary to man page)
224 REAL_FUNC_PASSTHROUGH_TYPED ( int, ioctl ) ( d, request, arg );
225 }
226
227 LIB_PRIVATE
228 int _real_setgid(gid_t gid) {
229 REAL_FUNC_PASSTHROUGH( setgid ) (gid);
230 }
231
232 LIB_PRIVATE
233 int _real_setuid(uid_t uid) {
234 REAL_FUNC_PASSTHROUGH( setuid ) (uid);
235 }
236
237 LIB_PRIVATE
238 long _real_ptrace(enum __ptrace_request request, pid_t pid, void *addr,
239 void *data) {
240 REAL_FUNC_PASSTHROUGH_TYPED ( long, ptrace ) ( request, pid, addr, data );
241 }
242
243 // gettid / tkill / tgkill are not defined in libc.
244 LIB_PRIVATE
245 pid_t _real_gettid(void){
246 // No glibc wrapper for gettid, although even if it had one, we would have
247 // the issues similar to getpid/getppid().
248 return (pid_t) _real_syscall(SYS_gettid);
249 }
250
251 LIB_PRIVATE
252 int _real_tkill(int tid, int sig) {
253 // No glibc wrapper for tkill, although even if it had one, we would have
254 // the issues similar to getpid/getppid().
255 return (int) _real_syscall(SYS_tkill, tid, sig);
256 }
257
258 LIB_PRIVATE
259 int _real_tgkill(int tgid, int tid, int sig) {
260 // No glibc wrapper for tgkill, although even if it had one, we would have
261 // the issues similar to getpid/getppid().
262 return (int) _real_syscall(SYS_tgkill, tgid, tid, sig);
263 }
264
265 LIB_PRIVATE
266 long _real_syscall(long sys_num, ... ) {
267 int i;
268 void * arg[7];
269 va_list ap;
270
271 va_start(ap, sys_num);
272 for (i = 0; i < 7; i++)
273 arg[i] = va_arg(ap, void *);
274 va_end(ap);
275
276 // /usr/include/unistd.h says syscall returns long int (contrary to man page)
277 REAL_FUNC_PASSTHROUGH_TYPED ( long, syscall ) (sys_num, arg[0], arg[1],
278 arg[2], arg[3], arg[4],
279 arg[5], arg[6] );
280 }
281
282 LIB_PRIVATE
283 pid_t _real_fork() {
284 REAL_FUNC_PASSTHROUGH_TYPED ( pid_t, fork ) ();
285 }
286
287 LIB_PRIVATE
288 int _real_clone ( int ( *function ) (void *), void *child_stack, int flags, void *arg, int *parent_tidptr, struct user_desc *newtls, int *child_tidptr )
289 {
290 REAL_FUNC_PASSTHROUGH ( __clone ) ( function, child_stack, flags, arg,
291 parent_tidptr, newtls, child_tidptr );
292 }
293
294 LIB_PRIVATE
295 int _real_shmget (key_t key, size_t size, int shmflg) {
296 REAL_FUNC_PASSTHROUGH ( shmget ) (key, size, shmflg);
297 }
298
299 LIB_PRIVATE
300 void* _real_shmat (int shmid, const void *shmaddr, int shmflg) {
301 REAL_FUNC_PASSTHROUGH_TYPED ( void*, shmat ) (shmid, shmaddr, shmflg);
302 }
303
304 LIB_PRIVATE
305 int _real_shmdt (const void *shmaddr) {
306 REAL_FUNC_PASSTHROUGH ( shmdt ) (shmaddr);
307 }
308
309 LIB_PRIVATE
310 int _real_shmctl (int shmid, int cmd, struct shmid_ds *buf) {
311 REAL_FUNC_PASSTHROUGH ( shmctl ) (shmid, cmd, buf);
312 }
313
314 LIB_PRIVATE
315 int _real_semctl(int semid, int semnum, int cmd, ...) {
316 union semun uarg;
317 va_list arg;
318 va_start (arg, cmd);
319 uarg = va_arg (arg, union semun);
320 va_end (arg);
321 REAL_FUNC_PASSTHROUGH ( semctl ) (semid, semnum, cmd, uarg);
322 }
323
324 LIB_PRIVATE
325 int _real_msgctl(int msqid, int cmd, struct msqid_ds *buf)
326 {
327 REAL_FUNC_PASSTHROUGH (msgctl) (msqid, cmd, buf);
328 }
329
330 LIB_PRIVATE
331 int _real_mq_notify(mqd_t mqdes, const struct sigevent *sevp) {
332 REAL_FUNC_PASSTHROUGH (mq_notify) (mqdes, sevp);
333 }
334
335 LIB_PRIVATE
336 int _real_clock_getcpuclockid(pid_t pid, clockid_t *clock_id) {
337 REAL_FUNC_PASSTHROUGH (clock_getcpuclockid) (pid, clock_id);
338 }
339
340 LIB_PRIVATE
341 int _real_timer_create(clockid_t clockid,
342 struct sigevent *sevp,
343 timer_t *timerid) {
344 REAL_FUNC_PASSTHROUGH (timer_create) (clockid, sevp, timerid);
345 }
346
347 LIB_PRIVATE
348 void _real_pthread_exit (void *retval) {
349 REAL_FUNC_PASSTHROUGH_VOID ( pthread_exit ) (retval);
350 }
351
352 LIB_PRIVATE
353 int _real_fcntl(int fd, int cmd, void *arg) {
354 REAL_FUNC_PASSTHROUGH (fcntl) (fd, cmd, arg);
355 }
356
357
358 int _real_open(const char *path, int flags, ...) {
359 mode_t mode = 0;
360 // Handling the variable number of arguments
361 if (flags & O_CREAT) {
362 va_list arg;
363 va_start (arg, flags);
364 mode = va_arg (arg, int);
365 va_end (arg);
366 }
367 REAL_FUNC_PASSTHROUGH(open) (path, flags, mode);
368 }
369
370 int _real_open64(const char *path, int flags, ...) {
371 mode_t mode = 0;
372 // Handling the variable number of arguments
373 if (flags & O_CREAT) {
374 va_list arg;
375 va_start (arg, flags);
376 mode = va_arg (arg, int);
377 va_end (arg);
378 }
379 REAL_FUNC_PASSTHROUGH(open64) (path, flags, mode);
380 }
381
382 FILE* _real_fopen(const char *path, const char *mode) {
383 REAL_FUNC_PASSTHROUGH_TYPED(FILE*, fopen) (path, mode);
384 }
385
386 FILE* _real_fopen64(const char *path, const char *mode) {
387 REAL_FUNC_PASSTHROUGH_TYPED(FILE*, fopen) (path, mode);
388 }
389
390 int _real_fclose(FILE *fp) {
391 REAL_FUNC_PASSTHROUGH(fclose) (fp);
392 }
393
394 int _real_xstat(int vers, const char *path, struct stat *buf) {
395 REAL_FUNC_PASSTHROUGH(__xstat) (vers, path, buf);
396 }
397
398 int _real_xstat64(int vers, const char *path, struct stat64 *buf) {
399 REAL_FUNC_PASSTHROUGH(__xstat64) (vers, path, buf);
400 }
401
402 int _real_lxstat(int vers, const char *path, struct stat *buf) {
403 REAL_FUNC_PASSTHROUGH(__lxstat) (vers, path, buf);
404 }
405
406 int _real_lxstat64(int vers, const char *path, struct stat64 *buf) {
407 REAL_FUNC_PASSTHROUGH(__lxstat64) (vers, path, buf);
408 }
409
410 ssize_t _real_readlink(const char *path, char *buf, size_t bufsiz) {
411 REAL_FUNC_PASSTHROUGH(readlink) (path, buf, bufsiz);
412 }
413