Added several calls to API (waitForStatusChange, BPatch_variableExpr
[dyninst.git] / dyninstAPI / tests / src / test_util.C
1
2 //
3 // Utility functions for use by the dyninst API test programs.
4 //
5
6 #include <stdio.h>
7 #include <signal.h>
8 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
9 #include <unistd.h>
10 #endif
11 #ifdef i386_unknown_nt4_0
12 #define WIN32_LEAN_AND_MEAN
13 #include <Windows.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_thread *appThread, int testnum, char *testname)
25 {
26     while (!appThread->isStopped() && !appThread->isTerminated())
27         waitForStatusChange();
28
29     if (!appThread->isStopped()) {
30         printf("**Failed test #%d (%s)\n", testnum, testname);
31         printf("    process did not signal mutator via stop\n");
32         exit(-1);
33     }
34 #ifdef i386_unknown_nt4_0
35     else if (appThread->stopSignal() != SIGTRAP) {
36         printf("**Failed test #%d (%s)\n", testnum, testname);
37         printf("    process stopped on signal %d, not SIGTRAP\n", 
38                 appThread->stopSignal());
39         exit(-1);
40     }
41 #else
42     else if (appThread->stopSignal() != SIGSTOP) {
43         printf("**Failed test #%d (%s)\n", testnum, testname);
44         printf("    process stopped on signal %d, not SIGSTOP\n", 
45                 appThread->stopSignal());
46         exit(-1);
47     }
48 #endif
49 }
50
51
52 //
53 // Signal the child that we've attached.  The child contains a function
54 // "checkIfAttached" which simply returns the value of the global variable
55 // "isAttached."  We add instrumentation to "checkIfAttached" to set
56 // "isAttached" to 1.
57 //
58 void signalAttached(BPatch_thread *appThread, BPatch_image *appImage)
59 {
60     BPatch_variableExpr *isAttached = appImage->findVariable("isAttached");
61     if (isAttached == NULL) {
62         printf("*ERROR*: unable to start tests because variable \"isAttached\" could not be found in the child process\n");
63         exit(-1);
64     }
65
66     BPatch_arithExpr setAttached(BPatch_assign, *isAttached,
67                                  BPatch_constExpr(1));
68     
69     // Find the point(s) we'll be instrumenting
70     BPatch_Vector<BPatch_point *> *points =
71         appImage->findProcedurePoint("checkIfAttached", BPatch_entry);
72     if (!points) {
73         fprintf(stderr, "*ERROR*: unable to start tests because the entry point to the function \"checkIfAttached\" could not be located\n");
74         exit(-1);
75     }
76
77     if (appThread->insertSnippet(setAttached, *points) == NULL) {
78         fprintf(stderr, "*ERROR*: unable to start tests because the entry point to the function \"checkIfAttached\" could not be instrumented\n");
79         exit(-1);
80     }
81 }
82
83
84 //
85 // Create a new process and return its process id.  If process creation 
86 // fails, this function returns -1.
87 //
88 int startNewProcess(char *pathname, char *argv[])
89 {
90 #ifdef i386_unknown_nt4_0
91     char child_args[1024];
92     strcpy(child_args, "");
93     if (argv[0] != NULL) {
94         strcpy(child_args, pathname);
95         for (int i = 1; argv[i] != NULL; i++) {
96             strcat(child_args, " ");
97             strcat(child_args, argv[i]);
98         }           
99     }
100
101     STARTUPINFO si;
102     memset(&si, 0, sizeof(STARTUPINFO));
103     si.cb = sizeof(STARTUPINFO);
104     PROCESS_INFORMATION pi;
105     if (!CreateProcess(pathname,        // application name
106                        child_args,      // command line
107                        NULL,            // security attributes
108                        NULL,            // thread security attributes
109                        FALSE,           // inherit handles
110                        0,               // creation flags
111                        NULL,            // environment,
112                        NULL,            // current directory
113                        &si,
114                        &pi)) {
115         return -1;
116     }
117
118     return pi.dwProcessId;
119 #else
120     int pid = fork();
121     if (pid == 0) {
122         // child - so exec 
123         execv(pathname, argv);
124         _exit(-1);
125     } else if (pid < 0) {
126         return -1;
127     }
128     return pid;
129 #endif
130 }