Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / tests / src / test2.mutatee.c
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /* Test application (Mutatee) */
33
34 /* $Id: test2.mutatee.c,v 1.38 2006/02/17 21:15:16 tlmiller Exp $ */
35
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <signal.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <assert.h>
43
44 #if defined(i386_unknown_nt4_0)
45 #define WIN32_LEAN_AND_MEAN
46 #include <windows.h>
47 #else
48 #include <unistd.h>
49 #endif
50
51 #if defined(sparc_sun_solaris2_4) \
52  || defined(i386_unknown_solaris2_5) \
53  || defined(i386_unknown_linux2_0) \
54  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
55  || defined(mips_sgi_irix6_4) \
56  || defined(alpha_dec_osf4_0) \
57  || defined(rs6000_ibm_aix4_1) \
58  || defined(ia64_unknown_linux2_4)
59 #include <dlfcn.h>
60 #endif
61
62 #ifdef __cplusplus
63 int mutateeCplusplus = 1;
64 #else
65 int mutateeCplusplus = 0;
66 #endif
67
68 #ifndef COMPILER
69 #define COMPILER ""
70 #endif
71 const char *Builder_id=COMPILER; /* defined on compile line */
72
73 #include "test2.h"
74
75 /* Empty functions are sometimes compiled too tight for entry and exit
76    points.  The following macro is used to flesh out these
77    functions. (expanded to use on all platforms for non-gcc compilers jkh 10/99) */
78 #define DUMMY_FN_BODY \
79   int dummy1__ = 1; \
80   int dummy2__ = 2; \
81   int dummy3__ = dummy1__ + dummy2__
82
83 /* XXX Currently, there's a bug in the library that prevents a subroutine call
84  * instrumentation point from being recognized if it is the first instruction
85  * in a function.  The following variable is used in this program in a number
86  * of kludges to get around this.  */
87 int kludge;
88
89 /* control debug printf statements */
90 #define dprintf if (debugPrint) printf
91 int debugPrint = 0;
92
93 #define TRUE    1
94 #define FALSE   0
95
96 #define MAX_TEST 14
97 int runTest[MAX_TEST+1];
98 int passedTest[MAX_TEST+1];
99
100 int isAttached = 0;
101
102 void doFork();
103
104 /*
105  * Check to see if the mutator has attached to us.
106  */
107 int checkIfAttached()
108 {
109     return isAttached;
110 }
111
112 #ifdef DETACH_ON_THE_FLY
113 /*
114  All this to stop ourselves.  We may be detached, but the mutator
115  needs to notice the stop.  We must send a SIGILL to ourselves, not
116  SIGSTOP, to get the mutator to notice.
117
118  DYNINSTsigill is a runtime library function that does this.  Here we
119  obtain a pointer to DYNINSTsigill from the runtime loader and then
120  call it.  Note that this depends upon the mutatee having
121  DYNINSTAPI_RT_LIB defined (with the same value as mutator) in its
122  environment, so this technique does not work for ordinary mutatees.
123
124  We could call kill to send ourselves SIGILL, but this is unsupported
125  because it complicates the SIGILL signal handler.  */
126 static void
127 dotf_stop_process()
128 {
129      void *h;
130      char *rtlib;
131      static void (*DYNINSTsigill)() = NULL;
132
133      if (!DYNINSTsigill) {
134           /* Obtain the name of the runtime library linked with this process */
135           rtlib = getenv("DYNINSTAPI_RT_LIB");
136           if (!rtlib) {
137                fprintf(stderr, "ERROR: Mutatee can't find the runtime library pathname\n");
138                assert(0);
139           }
140
141           /* Obtain a handle for the runtime library */
142           h = dlopen(rtlib, RTLD_LAZY); /* It should already be loaded */
143           if (!h) {
144                fprintf(stderr, "ERROR: Mutatee can't find its runtime library: %s\n",
145                        dlerror());
146                assert(0);
147           }
148
149           /* Obtain a pointer to the function DYNINSTsigill in the runtime library */
150           DYNINSTsigill = (void(*)()) dlsym(h, "DYNINSTsigill");
151           if (!DYNINSTsigill) {
152                fprintf(stderr, "ERROR: Mutatee can't find DYNINSTsigill in the runtime library: %s\n",
153                        dlerror());
154                assert(0);
155           }
156      }
157      DYNINSTsigill();
158 }
159 #endif /* DETACH_ON_THE_FLY */
160
161 /*
162  * Stop the process (in order to wait for the mutator to finish what it's
163  * doing and restart us).
164  */
165 void stop_process()
166 {
167 #ifdef i386_unknown_nt4_0
168     DebugBreak();
169 #else
170
171 #ifdef DETACH_ON_THE_FLY
172     dotf_stop_process();
173     return;
174 #endif
175
176 #if !defined(bug_irix_broken_sigstop)
177     kill(getpid(), SIGSTOP);
178 #else
179     kill(getpid(), SIGEMT);
180 #endif
181
182 #endif
183 }
184
185
186 void func6_1()
187 {
188 #if defined(sparc_sun_solaris2_4) \
189  || defined(i386_unknown_solaris2_5) \
190  || defined(i386_unknown_linux2_0) \
191  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
192  || defined(mips_sgi_irix6_4) \
193  || defined(alpha_dec_osf4_0) \
194  || defined(rs6000_ibm_aix4_1) \
195  || defined(ia64_unknown_linux2_4)
196
197     void *ref;
198     /* now use the dlopen interface to force an object to load. */
199 #if defined(alpha_dec_osf4_0)
200     ref = dlopen(TEST_DYNAMIC_LIB, RTLD_NOW);
201 #else
202     ref = dlopen(TEST_DYNAMIC_LIB, RTLD_NOW | RTLD_GLOBAL);
203 #endif
204
205     if (!ref) {
206         fprintf(stderr, "%s[%d]: %s\n", __FILE__, __LINE__, dlerror() );
207         fflush(stderr);
208     }
209 #endif
210 }
211
212 void func8_1()
213 {
214     /* Does nothing.  Will be instrumented with a BPatch_breakPointExpr */
215     DUMMY_FN_BODY;
216 }
217
218 void func11_1()
219 {
220     /* Does nothing. */
221     DUMMY_FN_BODY;
222 }
223
224 void func12_1()
225 {
226     /* Does nothing. */
227     DUMMY_FN_BODY;
228 }
229
230 #ifdef i386_unknown_nt4_0
231 #define USAGE "Usage: test2.mutatee [-attach] [-verbose] -run <num> .."
232 #else
233 #define USAGE "Usage: test2.mutatee [-attach <fd>] [-verbose] -run <num> .."
234 #endif
235
236 int main(int iargc, char *argv[])
237 {                                       /* despite different conventions */
238     unsigned argc=(unsigned)iargc;      /* make argc consistently unsigned */
239     unsigned int i, j;
240 #if !defined(i386_unknown_nt4_0)
241     int pfd;
242 #endif
243     int useAttach = FALSE;
244  
245     for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
246
247     for (i=1; i < argc; i++) {
248         if (!strcmp(argv[i], "-verbose")) {
249             debugPrint = 1;
250         } else if (!strcmp(argv[i], "-attach")) {
251             useAttach = TRUE;
252 #ifndef i386_unknown_nt4_0
253             if (++i >= argc) {
254                 printf("attach usage\n");
255                 fprintf(stderr, "%s\n", USAGE);
256                 exit(-1);
257             }
258             pfd = atoi(argv[i]);
259 #endif
260         } else if (!strcmp(argv[i], "-run")) {
261             for (j=i+1; j < argc; j++) {
262                 unsigned int testId;
263                 if (argv[j] && isdigit(*argv[j]) && (testId = atoi(argv[j]))) {
264                     if ((testId > 0) && (testId <= MAX_TEST)) {
265                         dprintf("selecting test %d\n", testId);
266                         runTest[testId] = TRUE;
267                     } else {
268                         printf("%s[%d]: invalid test %d requested\n", __FILE__, __LINE__, testId);
269                         exit(-1);
270                     }
271                 } else {
272                     /* end of test list */
273                     break;
274                 }
275             }
276             i = j-1;
277         } else {
278             printf("unexpected parameter '%s'\n", argv[i]);
279             fprintf(stderr, "%s\n", USAGE);
280             exit(-1);
281         }
282     }
283
284     if ((argc==1) || debugPrint)
285         printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
286                 mutateeCplusplus ? "C++" : "C", Builder_id);
287     if (argc==1) exit(0);
288
289     /* see if we should wait for the attach */
290     if (useAttach) {
291 #ifndef i386_unknown_nt4_0
292         char ch = 'T';
293         if (write(pfd, &ch, sizeof(char)) != sizeof(char)) {
294             fprintf(stderr, "*ERROR*: Writing to pipe\n");
295             exit(-1);
296         }
297         close(pfd);
298 #endif
299         printf("Waiting for mutator to attach...\n"); fflush(stdout);
300         while (!checkIfAttached()) ;
301         printf("Mutator attached.  Mutatee continuing.\n");
302     }
303
304
305     if (runTest[6] || runTest[7]) {
306         if (runTest[6]) func6_1();
307
308         /* Stop and wait for the mutator to check that we linked the library */
309         stop_process();
310     }
311
312     if (runTest[8]) func8_1();
313
314     while(1);
315
316     return(0);
317 }