1 /* Copyright (C) 2009 Pierre-Marc Fournier
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <ust/tracectl.h>
32 static pid_t (*plibc_func
)(void) = NULL
;
33 ust_fork_info_t fork_info
;
37 if(plibc_func
== NULL
) {
38 plibc_func
= dlsym(RTLD_NEXT
, "fork");
39 if(plibc_func
== NULL
) {
40 fprintf(stderr
, "libcwrap: unable to find fork\n");
45 ust_before_fork(&fork_info
);
47 /* Do the real fork */
48 retval
= plibc_func();
52 ust_after_fork_child(&fork_info
);
55 ust_after_fork_parent(&fork_info
);
61 int execve(const char *filename
, char *const argv
[], char *const envp
[])
63 static int (*plibc_func
)(const char *filename
, char *const argv
[], char *const envp
[]) = NULL
;
67 if(plibc_func
== NULL
) {
68 plibc_func
= dlsym(RTLD_NEXT
, "execve");
69 if(plibc_func
== NULL
) {
70 fprintf(stderr
, "libinterfork: unable to find execve\n");
77 retval
= plibc_func(filename
, argv
, envp
);
82 struct interfork_clone_info
{
85 ust_fork_info_t fork_info
;
88 static int clone_fn(void *arg
)
90 struct interfork_clone_info
*info
= (struct interfork_clone_info
*)arg
;
92 /* clone is now done and we are in child */
93 ust_after_fork_child(&info
->fork_info
);
95 return info
->fn(info
->arg
);
98 int clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, ...)
100 static int (*plibc_func
)(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
, pid_t
*ptid
, struct user_desc
*tls
, pid_t
*ctid
) = NULL
;
104 struct user_desc
*tls
;
112 ptid
= va_arg(ap
, pid_t
*);
113 tls
= va_arg(ap
, struct user_desc
*);
114 ctid
= va_arg(ap
, pid_t
*);
117 if(plibc_func
== NULL
) {
118 plibc_func
= dlsym(RTLD_NEXT
, "clone");
119 if(plibc_func
== NULL
) {
120 fprintf(stderr
, "libinterfork: unable to find clone\n");
125 if(flags
& CLONE_VM
) {
126 /* creating a thread, no need to intervene, just pass on the arguments */
127 retval
= plibc_func(fn
, child_stack
, flags
, arg
, ptid
, tls
, ctid
);
130 /* creating a real process, we need to intervene */
131 struct interfork_clone_info info
= { fn
: fn
, arg
: arg
};
133 ust_before_fork(&info
.fork_info
);
135 retval
= plibc_func(clone_fn
, child_stack
, flags
, &info
, ptid
, tls
, ctid
);
137 /* The child doesn't get here */
138 ust_after_fork_parent(&info
.fork_info
);