Minor fix to cleanup_drn. We should only use it when computingCost is
[dyninst.git] / dyninstAPI / src / process2.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41 /*
42  * This file contains special versions of some of the functions in process.C
43  * that have been modified for the dyninstAPI library.
44  */
45 /*
46  * $Log: process2.C,v $
47  * Revision 1.2  1997/05/07 19:03:20  naim
48  * Getting rid of old support for threads and turning it off until the new
49  * version is finished. Additionally, new superTable, baseTable and superVector
50  * classes for future support of multiple threads. The fastInferiorHeap class has
51  * also changed - naim
52  *
53  * Revision 1.1  1997/03/18 19:44:23  buck
54  * first commit of dyninst library.  Also includes:
55  *      moving templates from paradynd to dyninstAPI
56  *      converting showError into a function (in showerror.C)
57  *      many ifdefs for BPATCH_LIBRARY in dyinstAPI/src.
58  *
59  *
60  */
61
62 extern "C" {
63 #ifdef PARADYND_PVM
64 int pvmputenv (const char *);
65 int pvmendtask();
66 #endif
67 }
68
69 #include "util/h/headers.h"
70 #include "dyninstAPI/src/symtab.h"
71 #include "dyninstAPI/src/pdThread.h"
72 #include "dyninstAPI/src/process.h"
73 #include "dyninstAPI/src/util.h"
74 #include "dyninstAPI/src/inst.h"
75 #include "dyninstAPI/src/instP.h"
76 #include "dyninstAPI/src/dyninstP.h"
77 #include "dyninstAPI/src/os.h"
78 #include "paradynd/src/showerror.h"
79 #include "paradynd/src/perfStream.h"
80 #include "dyninstAPI/src/dynamiclinking.h"
81
82 #include "util/h/debugOstream.h"
83
84 #ifdef ATTACH_DETACH_DEBUG
85 extern debug_ostream attach_cerr;
86 #else
87 extern debug_ostream attach_cerr;
88 #endif
89
90 extern unsigned activeProcesses; // number of active processes
91 extern vector<process*> processVec;
92
93 extern bool dyninstAPI_forkNewProcess(string file, string dir,
94     vector<string> argv, vector<string>envp, string inputFile,
95     string outputFile, int &traceLink, int &ioLink, int &pid, int &tid,
96     int &procHandle, int &thrHandle);
97
98 /*
99  * Create a new instance of the named process.  Read the symbols and start
100  *   the program
101  */
102 process *dyninstAPI_createProcess(const string File, vector<string> argv,
103         vector<string> envp, const string dir = "")
104 {
105     // prepend the directory (if any) to the file, unless the filename
106     // starts with a /
107     string file = File;
108     if (!file.prefixed_by("/") && dir.length() > 0)
109       file = dir + "/" + file;
110
111     int traceLink;
112     int ioLink;
113     int pid;
114     int tid;
115     int procHandle;
116     int thrHandle;
117
118     string inputFile;
119     string outputFile;
120
121     ioLink = traceLink = -1;
122     if (!dyninstAPI_forkNewProcess(file, dir, argv, envp, inputFile, outputFile,
123                    traceLink, ioLink, pid, tid, procHandle, thrHandle)) {
124       // forkNewProcess is resposible for displaying error messages
125       return NULL;
126     }
127
128
129 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
130         extern bool establishBaseAddrs(int pid, int &status, bool waitForTrap);
131         int status;
132
133         if (!establishBaseAddrs(pid, status, true)) {
134             return(NULL);
135         }
136 #endif
137
138         image *img = image::parseImage(file);
139         if (!img) {
140             // For better error reporting, two failure return values would be useful
141             // One for simple error like because-file-not-because
142             // Another for serious errors like found-but-parsing-failed (internal error;
143             //    please report to paradyn@cs.wisc.edu)
144
145             string msg = string("Unable to parse image: ") + file;
146             showErrorCallback(68, msg.string_of());
147             // destroy child process
148             P_kill(pid, 9);
149
150             return(NULL);
151         }
152
153         /* parent */
154         statusLine("initializing process data structures");
155
156 #ifdef SHM_SAMPLING
157         vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
158         theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
159         theShmHeapStats[0].maxNumElems  = numIntCounters;
160
161         theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
162         theShmHeapStats[1].maxNumElems  = numWallTimers;
163
164         theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
165         theShmHeapStats[2].maxNumElems  = numProcTimers;
166 #endif
167
168         process *ret = new process(pid, img, traceLink, ioLink
169 #ifdef SHM_SAMPLING
170                                    , 7000, // shm seg key to try first
171                                    theShmHeapStats
172 #endif
173                                    );
174            // change this to a ctor that takes in more args
175
176         assert(ret);
177
178         processVec += ret;
179         activeProcesses++;
180
181         // find the signal handler function
182         ret->findSignalHandler(); // should this be in the ctor?
183
184         // initializing vector of threads - thread[0] is really the 
185         // same process
186         ret->threads += new pdThread(ret);
187
188         // we use this flag to solve race condition between inferiorRPC and 
189         // continueProc message from paradyn - naim
190         ret->deferredContinueProc = false;
191
192         ret->numOfActCounters_is=0;
193         ret->numOfActProcTimers_is=0;
194         ret->numOfActWallTimers_is=0;
195
196     return ret;
197
198 }
199
200
201 process *dyninstAPI_attachProcess(const string &progpath, int pid,
202         int afterAttach)
203 {
204    // implementation of dynRPC::attach() (the igen call)
205    // This is meant to be "the other way" to start a process (competes w/ createProcess)
206
207    // progpath gives the full path name of the executable, which we use ONLY to
208    // read the symbol table.
209
210    // We try to make progpath optional, since given pid, we should be able to
211    // calculate it with a clever enough search of the process' PATH, examining
212    // its argv[0], examining its current directory, etc.  /proc gives us this
213    // information on solaris...not sure about other platforms...
214
215    // possible values for afterAttach: 1 --> pause, 2 --> run, 0 --> leave as is
216
217    attach_cerr << "welcome to attachProcess for pid " << pid << endl;
218
219    // QUESTION: When we attach to a process, do we want to redirect its stdout/stderr
220    //           (like we do when we fork off a new process the 'usual' way)?
221    //           My first guess would be no.  -ari
222    //           But although we may ignore the io, we still need the trace stream.
223
224    // When we attach to a process, we don't fork...so this routine is much simpler
225    // than its "competitor", createProcess() (above).
226
227    // TODO: What about AIX establishBaseAddrs???  Do that now?
228
229    string fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
230    if (!fullPathToExecutable.length())
231       return NULL;
232
233    image *theImage = image::parseImage(fullPathToExecutable);
234    if (theImage == NULL) {
235       // two failure return values would be useful here, to differentiate
236       // file-not-found vs. catastrophic-parse-error.
237       string msg = string("Unable to parse image: ") + fullPathToExecutable;
238       showErrorCallback(68, msg.string_of());
239       return NULL; // failure
240    }
241
242 #ifdef SHM_SAMPLING
243    vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
244    theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
245    theShmHeapStats[0].maxNumElems  = numIntCounters;
246
247    theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
248    theShmHeapStats[1].maxNumElems  = numWallTimers;
249
250    theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
251    theShmHeapStats[2].maxNumElems  = numProcTimers;
252 #endif
253
254    // NOTE: the actual attach happens in the process "attach" constructor:
255    process *theProc = new process(pid, theImage, afterAttach
256 #ifdef SHM_SAMPLING
257                                   ,7000, // shm seg key to try first
258                                   theShmHeapStats
259 #endif                            
260                                   );
261    assert(theProc);
262
263    // the attach ctor always leaves us stopped...we may get continued once
264    // DYNINSTinit has finished running...
265    assert(theProc->status() == stopped);
266
267    processVec += theProc;
268    activeProcesses++;
269
270    // find the signal handler function
271    theProc->findSignalHandler(); // shouldn't this be in the ctor?
272
273    return theProc; // successful
274 }