Update copyright to LGPL on all files
[dyninst.git] / codeCoverage / src / CCPreInstrument.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 #include <stdio.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <iostream>
37 #include <fstream>
38 #include <limits.h>
39 #include <pthread.h>
40 #include <tcl.h>
41 #include <tk.h>
42
43 #include <CCcommon.h>
44 #include <FCAllBlocks.h>
45 #include <FCUseDominator.h>
46 #include <CCPreInstrument.h>
47
48 using namespace std;
49 /** constructor */
50 CCPreInstrument::CCPreInstrument() : CodeCoverage() {}
51
52 /** destructor */
53 CCPreInstrument::~CCPreInstrument() {}
54
55 /** For pre instrumenting code coverage, control flow graph is
56   * created for each function that is to be instrumented and then
57   * instrumented prior to the execution.
58   */
59 int CCPreInstrument::instrumentInitial(){
60
61         cout << "information: Beginning initial instrumentation..." << endl;
62
63         if(globalInterp && statusBarName){
64                 pthread_mutex_lock(&statusUpdateLock);
65                 tclStatusChanged = true;
66                 sprintf(tclStatusBuffer,"%s configure -text \
67                         \"Initial instrumentation is being done...\"",
68                         statusBarName);
69                 pthread_mutex_unlock(&statusUpdateLock);
70         }
71
72         for(int i=0;i<instrumentedFunctionCount;i++){
73                 FunctionCoverage* fc = instrumentedFunctions[i];
74
75                 /** an id is given to the function */
76                 fc->setId(i);
77
78                 int errorCode = Error_OK;
79
80                 /** instrumentation points are chosen */
81                 errorCode = fc->selectInstrumentationPoints();
82                 if(errorCode < Error_OK)
83                         return errorCode;
84
85                 /** necessary code is inserted */
86                 errorCode = fc->instrumentPoints();
87                 if(errorCode < Error_OK)
88                         return errorCode;
89         }
90         return Error_OK;
91 }
92
93 /** the mutatee is executed while mutator waits for fixed time intervals.
94   * when the necessary time passes the mutator stops the mutatee and
95   * calls the deletion interval callback to collect/update 
96   * information and to delete the already executed instrumentation
97   * code.
98   */
99 int CCPreInstrument::run(){
100         
101         cout << endl
102              << "information: The execution of the mutatee starts..."
103              << endl << endl;
104
105         if(globalInterp && statusBarName){
106                 pthread_mutex_lock(&statusUpdateLock);
107                 tclStatusChanged = true;
108                 sprintf(tclStatusBuffer,"%s configure -text \
109                         \"Execution of mutatee started...\"",
110                         statusBarName);
111                 pthread_mutex_unlock(&statusUpdateLock);
112         }
113
114         globalObject = this;
115
116         int errorCode = Error_OK;
117
118         appThread->continueExecution();
119
120         /** if instrumentation code deletion is activated */
121         if(deletionInterval > 0)
122                 while(true){
123                         if(appThread->isTerminated()){
124                                 cerr << "Mutatee unexpectedly terminated....." << endl;
125                                 exit(-1);
126                         }
127
128                         /** if already stooped, it reached the end of mutatee */
129                         if(appThread->isStopped())
130                                 break;
131
132                         /** wait some time (in seconds) */
133                         sleep(deletionInterval);
134
135                         /** call the deletion interval callback */
136                         deletionIntervalCallback();
137
138                 }
139
140         /** wait untill the breakpoint at exithandle is reached */
141         bPatch.waitUntilStopped(appThread);
142
143         whichInterval++;
144         totalDeletions = 0;
145
146         /** coverage results are printed into a binary file */
147         errorCode = printCoverageInformation();
148         if(errorCode < Error_OK)
149                 return errorPrint(Error_PrintResult);
150         
151         addTclTkFrequency();
152
153         /** the mutatee is let to run to terminate */
154         appThread->continueExecution();
155
156         bPatch.waitForStatusChange();
157
158         cout << endl 
159              << "information: the execution of mutatee terminates..."
160              << endl << endl;
161
162         if(globalInterp && statusBarName){
163                 pthread_mutex_lock(&statusUpdateLock);
164                 tclStatusChanged = true;
165                 sprintf(tclStatusBuffer,"%s configure -text \
166                         \"Execution of mutatee ended...\"",
167                         statusBarName);
168                 pthread_mutex_unlock(&statusUpdateLock);
169         }
170
171         return Error_OK;
172 }
173
174 /** for pre instrumentating code coverage since every function
175   * whose source code is available will be instrumented 
176   * this method always returns true.
177   */
178 bool CCPreInstrument::isInstrumented(int){
179         return true;
180 }
181
182 /** deletion interval callback is called at fixed
183   * time intervals and the mutatee is stopped and
184   * necessary execution counts are updated and 
185   * already executed instrumentation code is deleted 
186   */
187 int CCPreInstrument::deletionIntervalCallback(){
188
189         /** stop the process if not stopped yet */
190         bool already = false;
191         if(!appThread->isStopped())
192                 appThread->stopExecution();
193         else already = true;
194
195         whichInterval++;
196         totalDeletions = 0;
197
198         if(globalInterp && statusBarName){
199                 pthread_mutex_lock(&statusUpdateLock);
200                 tclStatusChanged = true;
201                 sprintf(tclStatusBuffer,"%s configure -text \
202                 \"Interval %d has started...\"",statusBarName,whichInterval);
203                 pthread_mutex_unlock(&statusUpdateLock);
204         }
205
206         cout << endl 
207              << "information: mutatee stopped and deletion occurs..."
208              << endl << endl;
209
210         /** update the execution counts of the basic blocks */
211         updateFCObjectInfo();
212
213         addTclTkFrequency();
214
215         if(globalInterp && statusBarName){
216                 pthread_mutex_lock(&statusUpdateLock);
217                 tclStatusChanged = true;
218                 sprintf(tclStatusBuffer,"%s configure -text \
219                         \"Interval %d has ended...\"",statusBarName,whichInterval);
220                 pthread_mutex_unlock(&statusUpdateLock);
221         }
222
223         /** assign the alarm interval call back and continue exec */
224         /** continue execution */
225         if(!already)
226                 appThread->continueExecution();
227
228         return Error_OK;
229 }