*** empty log message ***
[dyninst.git] / dyninstAPI / src / linux.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 #include "dyninstAPI/src/symtab.h"
43 #include "util/h/headers.h"
44 #include "dyninstAPI/src/os.h"
45 #include "dyninstAPI/src/process.h"
46 #include "dyninstAPI/src/stats.h"
47 #include "util/h/Types.h"
48 #include <sys/ioctl.h>
49 #include <fcntl.h>
50 #include <sys/termios.h>
51 #include <unistd.h>
52 #include "paradynd/src/showerror.h"
53 #include "util/h/pathName.h" // concat_pathname_components()
54 #include "util/h/debugOstream.h"
55 #include "util/h/solarisKludges.h"
56
57 #if defined (sparc_sun_solaris2_4)
58 #include "dyninstAPI/src/inst-sparc.h"
59 #else
60 #include "dyninstAPI/src/inst-x86.h"
61 #endif
62
63 #include "instPoint.h"
64
65 #include <sys/procfs.h>
66 //#include <poll.h>
67 #include <limits.h>
68 #include <link.h>
69 #include <dlfcn.h>
70
71 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
72
73 extern "C" {
74 extern int ioctl(int, int, ...);
75 extern long sysconf(int);
76 };
77
78 // The following were defined in process.C
79 extern debug_ostream attach_cerr;
80 extern debug_ostream inferiorrpc_cerr;
81 extern debug_ostream shmsample_cerr;
82 extern debug_ostream forkexec_cerr;
83 extern debug_ostream metric_cerr;
84 extern debug_ostream signal_cerr;
85
86 /*
87    Define the indices of some registers to be used with pr_reg.
88    These values are different on sparc and x86 platforms.
89    RETVAL_REG: the registers that holds the return value of calls ($o0 on sparc,
90                %eax on x86).
91    PC_REG: program counter
92    FP_REG: frame pointer (%i7 on sparc, %ebp on x86) 
93 */
94 #ifdef sparc_sun_solaris2_4
95 #define RETVAL_REG (R_O0)
96 #define PC_REG (R_PC)
97 #define FP_REG (R_O6)
98 #endif
99 #ifdef i386_unknown_solaris2_5
100 #define RETVAL_REG (EAX)
101 #define PC_REG (EIP)
102 #define FP_REG (EBP)
103 #endif
104
105
106 extern bool isValidAddress(process *proc, Address where);
107 extern void generateBreakPoint(instruction &insn);
108
109 /*
110    osTraceMe is called after we fork a child process to set
111    a breakpoint on the exit of the exec system call.
112    When /proc is used, this breakpoint **will not** cause a SIGTRAP to 
113    be sent to the process. The parent should use PIOCWSTOP to wait for 
114    the child.
115 */
116 void OS::osTraceMe(void) {
117
118   return;
119 }
120
121
122 // already setup on this FD.
123 // disconnect from controlling terminal 
124 void OS::osDisconnect(void) {
125
126 }
127
128 bool process::continueWithForwardSignal(int) {
129    return true;
130 }
131
132 bool process::dumpImage() {return false;}
133
134
135 /* 
136    execResult: return the result of an exec system call - true if succesful.
137    The traced processes will stop on exit of an exec system call, just before
138    returning to user code. At this point the return value (errno) is already
139    written to a register, and we need to check if the return value is zero.
140  */
141 static inline bool execResult(prstatus_t stat) {
142   return 0;
143 }
144
145 /*
146    wait for inferior processes to terminate or stop.
147 */
148 int process::waitProcs(int *status) {
149    return 0;
150 }
151
152
153 static char *extract_string_ptr(int procfd, char **ptr) {
154    // we want to return *ptr.
155    return 0;
156
157 }
158
159 string extract_string(int procfd, const char *inferiorptr) {
160    // assuming inferiorptr points to a null-terminated string in the inferior
161    // process, extract it and return it.
162    return 0;
163 }
164
165 bool get_ps_stuff(int proc_fd, string &argv0, string &pathenv, string &cwdenv) {
166    // Use ps info to obtain argv[0], PATH, and curr working directory of the
167    // inferior process designated by proc_fd.  Writes to argv0, pathenv, cwdenv.
168    return true;
169 }
170
171 /*
172    Open the /proc file correspoding to process pid, 
173    set the signals to be caught to be only SIGSTOP and SIGTRAP,
174    and set the kill-on-last-close and inherit-on-fork flags.
175 */
176 extern string pd_flavor ;
177 bool process::attach() {
178   return true;
179 }
180
181 #if defined(USES_LIBDYNINSTRT_SO)
182 bool process::trapAtEntryPointOfMain()
183 {
184
185   return(false);
186 }
187
188 bool process::trapDueToDyninstLib()
189 {
190   return(false);
191 }
192
193 void process::handleIfDueToDyninstLib() 
194 {
195
196 }
197
198 void process::handleTrapAtEntryPointOfMain()
199 {
200
201 }
202
203 void process::insertTrapAtEntryPointOfMain()
204 {
205
206 }
207
208 bool process::dlopenDYNINSTlib() {
209   // we will write the following into a buffer and copy it into the
210   // application process's address space
211   // [....LIBRARY's NAME...|code for DLOPEN]
212
213   // write to the application at codeOffset. This won't work if we
214   // attach to a running process.
215   //Address codeBase = this->getImage()->codeOffset();
216   // ...let's try "_start" instead
217   return true;
218 }
219
220 unsigned process::get_dlopen_addr() const {
221     return(0);
222 }
223 #endif
224
225 bool process::isRunning_() const {
226    // determine if a process is running by doing low-level system checks, as
227    // opposed to checking the 'status_' member vrble.  May assume that attach()
228    // has run, but can't assume anything else.
229       return true;
230 }
231
232 bool process::attach_() {assert(false);}
233 bool process::stop_() {assert(false);}
234
235 /* 
236    continue a process that is stopped 
237 */
238 bool process::continueProc_() {
239   return true;
240 }
241
242 #ifdef BPATCH_LIBRARY
243 /*
244    terminate execution of a process
245  */
246 bool process::terminateProc_()
247 {
248         return true;
249 }
250 #endif
251
252 /*
253    pause a process that is running
254 */
255 bool process::pause_() {
256  return 0;
257 }
258
259 /*
260    close the file descriptor for the file associated with a process
261 */
262 bool process::detach_() {
263
264   return true;
265 }
266
267 #ifdef BPATCH_LIBRARY
268 /*
269    detach from thr process, continuing its execution if the parameter "cont"
270    is true.
271  */
272 bool process::API_detach_(const bool cont)
273 {
274
275   return true;
276 }
277 #endif
278
279 bool process::dumpCore_(const string) {
280   return false;
281 }
282
283 bool process::writeTextWord_(caddr_t inTraced, int data) {
284   return false;
285 }
286
287 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
288 //  cerr << "writeTextSpace pid=" << getPid() << ", @ " << (void *)inTraced << " len=" << amount << endl; cerr.flush();
289   return false;
290 }
291
292 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
293 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
294   return false;
295 }
296 #endif
297
298 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
299   return 0;
300 }
301
302 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
303   return 0;
304 }
305
306 bool process::loopUntilStopped() {
307   assert(0);
308 }
309
310 #ifdef notdef
311 // TODO -- only call getrusage once per round
312 static struct rusage *get_usage_data() {
313   return NULL;
314 }
315 #endif
316
317 float OS::compute_rusage_cpu() {
318   return 0;
319 }
320
321 float OS::compute_rusage_sys() {
322   return 0;
323 }
324
325 float OS::compute_rusage_min() {
326   return 0;
327 }
328 float OS::compute_rusage_maj() {
329   return 0;
330 }
331
332 float OS::compute_rusage_swap() {
333   return 0;
334 }
335 float OS::compute_rusage_io_in() {
336   return 0;
337 }
338 float OS::compute_rusage_io_out() {
339   return 0;
340 }
341 float OS::compute_rusage_msg_send() {
342   return 0;
343 }
344 float OS::compute_rusage_msg_recv() {
345   return 0;
346 }
347 float OS::compute_rusage_sigs() {
348   return 0;
349 }
350 float OS::compute_rusage_vol_cs() {
351   return 0;
352 }
353 float OS::compute_rusage_inv_cs() {
354   return 0;
355 }
356
357 int getNumberOfCPUs()
358 {
359     return(1);
360 }  
361
362
363 bool process::getActiveFrame(int *fp, int *pc)
364 {
365   return 0;
366 }
367
368
369 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool uppermost)
370 {
371  
372
373
374   return false;
375 }
376
377
378
379 #ifdef SHM_SAMPLING
380 time64 process::getInferiorProcessCPUtime() {
381    // returns user+sys time from the u or proc area of the inferior process, which in
382    // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
383    // to obtain it (solaris).  It must not stop the inferior process in order
384    // to obtain the result, nor can it assue that the inferior has been stopped.
385    // The result MUST be "in sync" with rtinst's DYNINSTgetCPUtime().
386
387    // We use the PIOCUSAGE /proc ioctl
388
389    // Other /proc ioctls that should work too: PIOCPSINFO
390    // and the lower-level PIOCGETPR and PIOCGETU which return copies of the proc
391    // and u areas, respectively.
392    // PIOCSTATUS does _not_ work because its results are not in sync
393    // with DYNINSTgetCPUtime
394
395    time64 result;
396    return result;
397 }
398 #endif
399
400 void *process::getRegisters() {
401    // Astonishingly, this routine can be shared between solaris/sparc and
402    // solaris/x86.  All hail /proc!!!
403    // assumes the process is stopped (/proc requires it)
404
405    return 0;
406 }
407
408 bool process::executingSystemCall() {
409    return(false);
410 }
411
412 bool process::changePC(unsigned addr, const void *savedRegs) {
413    return true;
414 }
415
416 bool process::changePC(unsigned addr) {
417    return true;
418 }
419
420 bool process::restoreRegisters(void *buffer) {
421    // The fact that this routine can be shared between solaris/sparc and
422    // solaris/x86 is just really, really cool.  /proc rules!
423
424    return true;
425 }
426
427 #ifdef i386_unknown_solaris2_5
428
429 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool )
430 {
431   return(readOK);
432 }
433
434 #endif
435
436 #ifdef i386_unknown_solaris2_5
437 // ******** TODO **********
438 bool process::needToAddALeafFrame(Frame , Address &) {
439   return false;
440 }
441
442 #else
443
444 // needToAddALeafFrame: returns true if the between the current frame 
445 // and the next frame there is a leaf function (this occurs when the 
446 // current frame is the signal handler and the function that was executing
447 // when the sighandler was called is a leaf function)
448 bool process::needToAddALeafFrame(Frame current_frame, Address &leaf_pc){
449
450
451    return false;
452 }
453 #endif
454
455 string process::tryToFindExecutable(const string &iprogpath, int pid) {
456    // returns empty string on failure.
457    // Otherwise, returns a full-path-name for the file.  Tries every
458    // trick to determine the full-path-name, even though "progpath" may be
459    // unspecified (empty string).
460    
461    // Remember, we can always return the empty string...no need to
462    // go nuts writing the world's most complex algorithm.
463    return "";
464 }
465
466 bool process::set_breakpoint_for_syscall_completion() {
467    /* Can assume: (1) process is paused and (2) in a system call.
468       We want to set a TRAP for the syscall exit, and do the
469       inferiorRPC at that time.  We'll use /proc PIOCSEXIT.
470       Returns true iff breakpoint was successfully set. */
471    return true;
472 }
473
474 unsigned process::read_inferiorRPC_result_register(reg) {
475       return 0; // assert(false)?
476 }
477
478
479 // hasBeenBound: returns true if the runtime linker has bound the
480 // function symbol corresponding to the relocation entry in at the address
481 // specified by entry and base_addr.  If it has been bound, then the callee 
482 // function is returned in "target_pdf", else it returns false.
483 bool process::hasBeenBound(const relocationEntry entry, 
484                            pd_Function *&target_pdf, Address base_addr) {
485
486   return false;
487
488 }
489
490
491
492 // findCallee: finds the function called by the instruction corresponding
493 // to the instPoint "instr". If the function call has been bound to an
494 // address, then the callee function is returned in "target" and the 
495 // instPoint "callee" data member is set to pt to callee's function_base.  
496 // If the function has not yet been bound, then "target" is set to the 
497 // function_base associated with the name of the target function (this is 
498 // obtained by the PLT and relocation entries in the image), and the instPoint
499 // callee is not set.  If the callee function cannot be found, (ex. function
500 // pointers, or other indirect calls), it returns false.
501 // Returns false on error (ex. process doesn't contain this instPoint).
502 //
503 // The assumption here is that for all processes sharing the image containing
504 // this instPoint they are going to bind the call target to the same function. 
505 // For shared objects this is always true, however this may not be true for
506 // dynamic executables.  Two a.outs can be identical except for how they are
507 // linked, so a call to fuction foo in one version of the a.out may be bound
508 // to function foo in libfoo.so.1, and in the other version it may be bound to 
509 // function foo in libfoo.so.2.  We are currently not handling this case, since
510 // it is unlikely to happen in practice.
511 bool process::findCallee(instPoint &instr, function_base *&target){
512
513     return false;  
514 }
515
516
517
518
519
520
521
522
523
524
525