C/C++ determination/reporting.
[dyninst.git] / dyninstAPI / tests / src / test2.mutatee.c
1
2 /* Test application (Mutatee) */
3
4 /* $Id: test2.mutatee.c,v 1.23 2000/06/20 21:45:58 wylie Exp $ */
5
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <signal.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <ctype.h>
12
13 #if defined(i386_unknown_nt4_0)
14 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
16 #else
17 #include <unistd.h>
18 #endif
19
20 #if defined(sparc_sun_solaris2_4)  || defined(i386_unknown_solaris2_5) || \
21     defined(i386_unknown_linux2_0) || defined(mips_sgi_irix6_4) || \
22     defined(alpha_dec_osf4_0)
23 #include <dlfcn.h>
24 #endif
25
26 #ifdef __cplusplus
27 int mutateeCplusplus = 1;
28 #else
29 int mutateeCplusplus = 0;
30 #endif
31
32 #include "test2.h"
33
34 /* Empty functions are sometimes compiled too tight for entry and exit
35    points.  The following macro is used to flesh out these
36    functions. (expanded to use on all platforms for non-gcc compilers jkh 10/99) */
37 #define DUMMY_FN_BODY \
38   int dummy1__ = 1; \
39   int dummy2__ = 2; \
40   int dummy3__ = dummy1__ + dummy2__
41
42 /* XXX Currently, there's a bug in the library that prevents a subroutine call
43  * instrumentation point from being recognized if it is the first instruction
44  * in a function.  The following variable is used in this program in a number
45  * of kludges to get around this.  */
46 int kludge;
47
48 /* control debug printf statements */
49 #define dprintf if (debugPrint) printf
50 int debugPrint = 0;
51
52 #define TRUE    1
53 #define FALSE   0
54
55 #define MAX_TEST 14
56 int runTest[MAX_TEST+1];
57 int passedTest[MAX_TEST+1];
58
59 int isAttached = 0;
60
61 void doFork();
62
63 /*
64  * Check to see if the mutator has attached to us.
65  */
66 int checkIfAttached()
67 {
68     return isAttached;
69 }
70
71 /*
72  * Stop the process (in order to wait for the mutator to finish what it's
73  * doing and restart us).
74  */
75 void stop_process()
76 {
77 #ifdef i386_unknown_nt4_0
78     DebugBreak();
79 #else
80 #ifdef DETACH_ON_THE_FLY
81     kill(getpid(), SIGILL);
82 #else
83     kill(getpid(), SIGSTOP);
84 #endif
85 #endif
86 }
87
88
89 void func6_1()
90 {
91 #if defined(sparc_sun_solaris2_4)  || defined(i386_unknown_solaris2_5) || \
92     defined(i386_unknown_linux2_0) || defined(mips_sgi_irix6_4) || \
93     defined(alpha_dec_osf4_0)
94
95     void *ref;
96
97     /* now use the dlopen interface to force an object to load. */
98 #if defined(alpha_dec_osf4_0)
99     ref = dlopen(TEST_DYNAMIC_LIB, RTLD_NOW);
100 #else
101     ref = dlopen(TEST_DYNAMIC_LIB, RTLD_NOW | RTLD_GLOBAL);
102 #endif
103
104     if (!ref) {
105         fprintf(stderr, "%s\n", dlerror());
106         fflush(stderr);
107     }
108
109 #endif
110 }
111
112 void func8_1()
113 {
114     /* Does nothing.  Will be instrumented with a BPatch_breakPointExpr */
115     DUMMY_FN_BODY;
116 }
117
118 void func11_1()
119 {
120     /* Does nothing. */
121     DUMMY_FN_BODY;
122 }
123
124 void func12_1()
125 {
126     /* Does nothing. */
127     DUMMY_FN_BODY;
128 }
129
130 #ifdef i386_unknown_nt4_0
131 #define USAGE "Usage: test2.mutatee [-attach] [-verbose]"
132 #else
133 #define USAGE "Usage: test2.mutatee [-attach <fd>] [-verbose]"
134 #endif
135
136 int main(int iargc, char *argv[])
137 {                                       /* despite different conventions */
138     unsigned argc=(unsigned)iargc;      /* make argc consistently unsigned */
139     unsigned int i, j;
140 #if !defined(i386_unknown_nt4_0)
141     int pfd;
142 #endif
143     int useAttach = FALSE;
144  
145     for (j=1; j <= MAX_TEST; j++) {
146         runTest[j] = TRUE;
147     }
148
149     for (i=1; i < argc; i++) {
150         if (!strcmp(argv[i], "-verbose")) {
151             debugPrint = 1;
152         } else if (!strcmp(argv[i], "-attach")) {
153             useAttach = TRUE;
154 #ifndef i386_unknown_nt4_0
155             if (++i >= argc) {
156                 printf("attach usage\n");
157                 fprintf(stderr, "%s\n", USAGE);
158                 exit(-1);
159             }
160             pfd = atoi(argv[i]);
161 #endif
162         } else if (!strcmp(argv[i], "-fork")) {
163             doFork();
164         } else if (!strcmp(argv[i], "-run")) {
165             for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
166             for (j=i+1; j < argc; j++) {
167                 unsigned int testId;
168                 if (argv[j] && isdigit(*argv[j]) && (testId = atoi(argv[j]))) {
169                     if ((testId > 0) && (testId <= MAX_TEST)) {
170                         runTest[testId] = 1;
171                     } else {
172                         printf("invalid test %d requested\n", testId);
173                         exit(-1);
174                     }
175                 } else {
176                     /* end of test list */
177                     break;
178                 }
179             }
180             i = j-1;
181         } else {
182             printf("unexpected parameter '%s'\n", argv[i]);
183             fprintf(stderr, "%s\n", USAGE);
184             exit(-1);
185         }
186     }
187
188     dprintf("Mutatee %s running (%s).\n", argv[0], 
189                 mutateeCplusplus ? "C++" : "C");
190
191     /* see if we should wait for the attach */
192     if (useAttach) {
193 #ifndef i386_unknown_nt4_0
194         char ch = 'T';
195         if (write(pfd, &ch, sizeof(char)) != sizeof(char)) {
196             fprintf(stderr, "*ERROR*: Writing to pipe\n");
197             exit(-1);
198         }
199         close(pfd);
200 #endif
201         printf("Waiting for mutator to attach...\n"); fflush(stdout);
202         while (!checkIfAttached()) ;
203         printf("Mutator attached.  Mutatee continuing.\n");
204     }
205
206
207     if (runTest[6] || runTest[7]) {
208         if (runTest[6]) func6_1();
209
210         /* Stop and wait for the mutator to check that we linked the library */
211         stop_process();
212     }
213
214     if (runTest[8]) func8_1();
215
216     while(1);
217
218     dprintf("Mutatee %s terminating.\n", argv[0]);
219     return(0);
220 }
221
222
223 void doFork() { 
224     /* XXX To be completed... */
225     while(1);
226 }