cleanup
[dyninst.git] / dyninstAPI / tests / src / test_util.C
1 //
2 // $Id: test_util.C,v 1.9 1999/06/08 06:01:26 csserra Exp $
3 // Utility functions for use by the dyninst API test programs.
4 //
5
6 #include <stdio.h>
7 #include <signal.h>
8
9 #if defined(i386_unknown_nt4_0)
10 #define WIN32_LEAN_AND_MEAN
11 #include <Windows.h>
12 #else
13 #include <unistd.h>
14 #endif
15
16 #include "BPatch.h"
17 #include "BPatch_Vector.h"
18 #include "BPatch_thread.h"
19
20
21 //
22 // Wait for the mutatee to stop.
23 //
24 void waitUntilStopped(BPatch *bpatch,
25         BPatch_thread *appThread, int testnum, char *testname)
26 {
27     while (!appThread->isStopped() && !appThread->isTerminated())
28         bpatch->waitForStatusChange();
29
30     if (!appThread->isStopped()) {
31         printf("**Failed test #%d (%s)\n", testnum, testname);
32         printf("    process did not signal mutator via stop\n");
33         exit(-1);
34     }
35 #ifdef i386_unknown_nt4_0
36     else if (appThread->stopSignal() != SIGTRAP && appThread->stopSignal() != -1) {
37         printf("**Failed test #%d (%s)\n", testnum, testname);
38         printf("    process stopped on signal %d, not SIGTRAP\n", 
39                 appThread->stopSignal());
40         exit(-1);
41     }
42 #else
43     else if ((appThread->stopSignal() != SIGSTOP) &&
44             (appThread->stopSignal() != SIGHUP)) {
45         printf("**Failed test #%d (%s)\n", testnum, testname);
46         printf("    process stopped on signal %d, not SIGSTOP\n", 
47                 appThread->stopSignal());
48         exit(-1);
49     }
50 #endif
51 }
52
53
54 //
55 // Signal the child that we've attached.  The child contains a function
56 // "checkIfAttached" which simply returns the value of the global variable
57 // "isAttached."  We add instrumentation to "checkIfAttached" to set
58 // "isAttached" to 1.
59 //
60 void signalAttached(BPatch_thread *appThread, BPatch_image *appImage)
61 {
62     BPatch_variableExpr *isAttached = appImage->findVariable("isAttached");
63     if (isAttached == NULL) {
64         printf("*ERROR*: unable to start tests because variable \"isAttached\" could not be found in the child process\n");
65         exit(-1);
66     }
67
68     int yes = 1;
69     isAttached->writeValue(&yes);
70 }
71
72
73 //
74 // Create a new process and return its process id.  If process creation 
75 // fails, this function returns -1.
76 //
77 int startNewProcessForAttach(char *pathname, char *argv[])
78 {
79 #ifdef i386_unknown_nt4_0
80     char child_args[1024];
81     strcpy(child_args, "");
82     if (argv[0] != NULL) {
83         strcpy(child_args, pathname);
84         for (int i = 1; argv[i] != NULL; i++) {
85             strcat(child_args, " ");
86             strcat(child_args, argv[i]);
87         }           
88         strcat(child_args, " -attach");
89     }
90
91     STARTUPINFO si;
92     memset(&si, 0, sizeof(STARTUPINFO));
93     si.cb = sizeof(STARTUPINFO);
94     PROCESS_INFORMATION pi;
95     if (!CreateProcess(pathname,        // application name
96                        child_args,      // command line
97                        NULL,            // security attributes
98                        NULL,            // thread security attributes
99                        FALSE,           // inherit handles
100                        0,               // creation flags
101                        NULL,            // environment,
102                        NULL,            // current directory
103                        &si,
104                        &pi)) {
105         return -1;
106     }
107
108     return pi.dwProcessId;
109 #else
110     /* Make a pipe that we will use to signal that the mutatee has started. */
111     int fds[2];
112     if (pipe(fds) != 0) {
113         fprintf(stderr, "*ERROR*: Unable to create pipe.\n");
114         exit(-1);
115     }
116
117     /* Create the argv string for the child process. */
118     char fdstr[32];
119     sprintf(fdstr, "%d", fds[1]);
120
121     int i;
122     for (i = 0; argv[i] != NULL; i++) ;
123     char **attach_argv = (char**)malloc(sizeof(char *) * (i + 3));
124
125     for (i = 0; argv[i] != NULL; i++)
126         attach_argv[i] = argv[i];
127     attach_argv[i++] = "-attach";
128     attach_argv[i++] = fdstr;
129     attach_argv[i++] = NULL;
130
131     int pid = fork();
132     if (pid == 0) {
133         // child
134         close(fds[0]); // We don't need the read side
135         execv(pathname, attach_argv);
136         exit(-1);
137     } else if (pid < 0) {
138         return -1;
139     }
140
141     // parent
142     close(fds[1]);  // We don't need the write side
143
144     // Wait for the child to write to the pipe
145     char ch;
146     if (read(fds[0], &ch, sizeof(char)) != sizeof(char)) {
147         fprintf(stderr, "*ERROR*: Error reading from pipe\n");
148         exit(-1);
149     }
150
151     if (ch != 'T') {
152         fprintf(stderr, "*ERROR*: Child didn't write expected value to pipe.\n");
153         exit(-1);
154     }
155
156     close(fds[0]);  // We're done with the pipe
157
158     return pid;
159 #endif
160 }