2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
43 #include "util/h/headers.h"
44 #include "util/h/String.h"
45 #include "util/h/Vector.h"
46 #include "paradynd/src/showerror.h"
47 #include "dyninstAPI/src/os.h"
48 #include "dyninstAPI/src/util.h"
50 #ifndef BPATCH_LIBRARY
51 #include "paradynd/src/perfStream.h"
52 #include "paradynd/src/main.h"
55 // the following are needed for handleSigChild
56 #include "dyninstAPI/src/process.h"
57 #include "dyninstAPI/src/instP.h"
58 #include "dyninstAPI/src/stats.h"
59 extern process *findProcess(int);
61 // The following were all defined in process.C (for no particular reason)
62 extern debug_ostream attach_cerr;
63 extern debug_ostream inferiorrpc_cerr;
64 extern debug_ostream shmsample_cerr;
65 extern debug_ostream forkexec_cerr;
66 extern debug_ostream metric_cerr;
67 extern debug_ostream signal_cerr;
68 extern debug_ostream sharedobj_cerr;
73 int pvmputenv (const char *);
78 /*****************************************************************************
79 * forkNewProcess: starts a new process, setting up trace and io links between
80 * the new process and the daemon
81 * Returns true if succesfull.
84 * file: file to execute
85 * dir: working directory for the new process
86 * argv: arguments to new process
87 * envp: environment **** not in use
88 * inputFile: where to redirect standard input
89 * outputFile: where to redirect standard output
90 * traceLink: handle or file descriptor of trace link (read only)
91 * ioLink: handle or file descriptor of io link (read only)
92 * pid: process id of new process
93 * tid: thread id for main thread (needed by WindowsNT)
94 * procHandle: handle for new process (needed by WindowsNT)
95 * thrHandle: handle for main thread (needed by WindowsNT)
96 ****************************************************************************/
97 bool forkNewProcess(string file, string dir, vector<string> argv,
98 vector<string>envp, string inputFile, string outputFile,
99 int &traceLink, int &ioLink,
100 int &pid, int & /*tid*/,
101 int & /*procHandle*/, int & /*thrHandle*/) {
103 #ifndef BPATCH_LIBRARY
104 // Strange, but using socketpair here doesn't seem to work OK on SunOS.
106 // r = P_socketpair(AF_UNIX, SOCK_STREAM, (int) NULL, tracePipe);
108 int r = P_pipe(tracePipe);
110 // P_perror("socketpair");
111 string msg = string("Unable to create trace pipe for program '") + file +
112 string("': ") + string(sys_errlist[errno]);
113 showErrorCallback(68, msg);
117 // ioPipe is used to redirect the child's stdout & stderr to a pipe which is in
118 // turn read by the parent via the process->ioLink socket.
121 // r = P_socketpair(AF_UNIX, SOCK_STREAM, (int) NULL, ioPipe);
124 // P_perror("socketpair");
125 string msg = string("Unable to create IO pipe for program '") + file +
126 string("': ") + string(sys_errlist[errno]);
127 showErrorCallback(68, msg);
133 // WARNING This code assumes that vfork is used, and a failed exec will
134 // corectly change failed in the parent process.
139 // must use fork, since pvmendtask will do some writing in the address space
141 // fprintf(stderr, "FORK: pid=%d\n", pid);
151 sprintf(errorLine, "Unable to start %s: %s\n", file.string_of(),
154 showErrorCallback(68, (const char *) errorLine);
158 #ifndef BPATCH_LIBRARY
160 // parent never writes trace records; it only receives them.
163 // parent closes write end of io pipe; child closes its read end.
164 // pipe output goes to the parent's read fd (ret->ioLink); pipe input
165 // comes from the child's write fd. In short, when the child writes to
166 // its stdout/stderr, it gets sent to the pipe which in turn sends it to
167 // the parent's ret->ioLink fd for reading.
169 traceLink = tracePipe[0];
174 } else if (pid == 0) {
182 #ifndef BPATCH_LIBRARY
185 // We only write to ioPipe. Hence we close ioPipe[0], the read end. Then we
186 // call dup2() twice to assign our stdout and stderr to the write end of the
190 // assigns fd 1 (stdout) to be a copy of ioPipe[1]. (Since stdout is already
191 // in use, dup2 will first close it then reopen it with the characteristics
193 // In short, stdout gets redirected towards the write end of the pipe.
194 // The read end of the pipe is read by the parent (paradynd), not by us.
196 dup2(ioPipe[1], 2); // redirect fd 2 (stderr) to the pipe, like above.
198 // We're not using ioPipe[1] anymore; close it.
199 if (ioPipe[1] > 2) close (ioPipe[1]);
201 // Now that stdout is going to a pipe, it'll (unfortunately) be block buffered
202 // instead of the usual line buffered (when it goes to a tty). In effect the
203 // stdio library is being a little too clever for our purposes. We don't want
204 // the "bufferedness" to change. So we set it back to line-buffered.
205 // The command to do this is setlinebuf(stdout) [stdio.h call] But we don't
206 // do it here, since the upcoming execve() would undo our work [execve keeps
207 // fd's but resets higher-level stdio information, which is recreated before
208 // execution of main()] So when do we do it? In rtinst's DYNINSTinit
209 // (RTposix.c et al.)
211 // setup stderr for rest of exec try.
212 FILE *childError = P_fdopen(2, "w");
214 P_close(tracePipe[0]);
216 if (P_dup2(tracePipe[1], 3) != 3) {
217 fprintf(childError, "dup2 failed\n");
222 /* close if higher */
223 if (tracePipe[1] > 3) close(tracePipe[1]);
225 if ((dir.length() > 0) && (P_chdir(dir.string_of()) < 0)) {
226 sprintf(errorLine, "cannot chdir to '%s': %s\n", dir.string_of(),
232 /* see if I/O needs to be redirected */
233 if (inputFile.length()) {
234 int fd = P_open(inputFile.string_of(), O_RDONLY, 0);
236 fprintf(childError, "stdin open of %s failed\n", inputFile.string_of());
245 if (outputFile.length()) {
246 int fd = P_open(outputFile.string_of(), O_WRONLY|O_CREAT, 0444);
248 fprintf(childError, "stdout open of %s failed\n", outputFile.string_of());
252 dup2(fd, 1); // redirect fd 1 (stdout) to a copy of descriptor "fd"
253 P_close(fd); // not using descriptor fd any more; close it.
258 /* indicate our desire to be traced */
262 sprintf(errorLine, "ptrace error, exiting, errno=%d\n", errno);
264 logLine(sys_errlist[errno]);
265 showErrorCallback(69, string("Internal error: ") +
266 string((const char *) errorLine));
267 P__exit(-1); // double underscores are correct
270 if (pvm_running && envp.size())
271 for (int ep=envp.size()-1; ep>=0; ep--) {
272 pvmputenv(envp[ep].string_of());
275 #ifndef BPATCH_LIBRARY
276 // hand off info about how to start a paradynd to the application.
277 // used to catch rexec calls, and poe events.
279 char paradynInfo[1024];
280 sprintf(paradynInfo, "PARADYN_MASTER_INFO= ");
281 for (unsigned i=0; i < process::arg_list.size(); i++) {
284 str = P_strdup(process::arg_list[i].string_of());
285 if (!strcmp(str, "-l1")) {
286 strcat(paradynInfo, "-l0");
288 strcat(paradynInfo, str);
290 strcat(paradynInfo, " ");
292 P_putenv(paradynInfo);
296 args = new char*[argv.size()+1];
297 for (unsigned ai=0; ai<argv.size(); ai++)
298 args[ai] = P_strdup(argv[ai].string_of());
299 args[argv.size()] = NULL;
300 P_execvp(file.string_of(), args);
302 sprintf(errorLine, "paradynd: execv failed, errno=%d\n", errno);
305 logLine(sys_errlist[errno]);
309 sprintf(errorLine, "argv %d = %s\n", i, args[i]);
319 } else { // pid == 0 --- error
320 sprintf(errorLine, "vfork failed, errno=%d\n", errno);
322 showErrorCallback(71, (const char *) errorLine);
331 TODO: cleanup handleSigChild. This function has a lot of code that
332 should be moved to a machine independent place (a lot of what is
333 going on here will probably have to be moved anyway once we move to
336 There is a different version of this function for WindowsNT. If any changes
337 are made here, they will probably also be needed in the NT version.
342 // TODO -- make this a process method
343 int handleSigChild(int pid, int status)
346 #ifdef rs6000_ibm_aix4_1
347 // On AIX, we get sigtraps on fork and load, and must handle
348 // these cases specially
349 extern bool handleAIXsigTraps(int, int);
350 if (handleAIXsigTraps(pid, status)) {
353 /* else check for regular traps and signals */
356 // ignore signals from unknown processes
357 process *curr = findProcess(pid);
359 forkexec_cerr << "handleSigChild pid " << pid << " is an unknown process." << endl;
360 forkexec_cerr << "WIFSTOPPED=" << (WIFSTOPPED(status) ? "true" : "false");
361 if (WIFSTOPPED(status)) {
362 forkexec_cerr << "WSTOPSIG=" << WSTOPSIG(status);
364 forkexec_cerr << endl << flush;
368 if (WIFSTOPPED(status)) {
369 int sig = WSTOPSIG(status);
373 sprintf(errorLine, "process %d got SIGTSTP", pid);
374 statusLine(errorLine);
379 // Note that there are now several uses for SIGTRAPs in paradynd.
380 // The original use was to detect when a ptraced process had
381 // started up. Several have been added. We must be careful
382 // to make sure that uses of SIGTRAPs do not conflict.
384 signal_cerr << "welcome to SIGTRAP for pid " << curr->getPid() << " status=" << curr->getStatusAsString() << endl;
385 const bool wasRunning = (curr->status() == running);
386 curr->status_ = stopped;
388 // Check to see if the TRAP is due to a system call exit which
389 // we were waiting for, in order to launch an inferior rpc safely.
390 if (curr->isRPCwaitingForSysCallToComplete()) {
391 inferiorrpc_cerr << "got SIGTRAP indicating syscall completion!"
393 curr->setRPCwaitingForSysCallToComplete(false);
395 if (curr->launchRPCifAppropriate(false, // not running
396 true // finishing a syscall
398 inferiorrpc_cerr << "syscall completion: rpc launched ok, as expected " << endl;
401 inferiorrpc_cerr << "syscall completion: failed to launch rpc" << endl;
405 // check to see if trap is due to dlopen or dlcose event
406 if(curr->isDynamicallyLinked()){
407 if(curr->handleIfDueToSharedObjectMapping()){
409 if(wasRunning) curr->continueProc();
414 //If the list is not empty, it means some previous
415 //instrumentation has yet need to be finished.
416 if (instWList.size() != 0) {
417 // cerr << "instWList is full" << endl;
418 if(curr -> cleanUpInstrumentation(wasRunning)){
419 break; // successfully processed the SIGTRAP
423 if (curr->handleTrapIfDueToRPC()) {
424 inferiorrpc_cerr << "processed RPC response in SIGTRAP" << endl;
429 // the process has executed a succesful exec, and is now
430 // stopped at the exit of the exec call.
432 forkexec_cerr << "SIGTRAP: inExec is true, so doing process::handleExec()!" << endl;
433 string buffer = string("process ") + string(curr->getPid()) +
434 " has performed exec() syscall";
435 statusLine(buffer.string_of());
437 // call handleExec to clean our internal data structures, reparse
438 // symbol table. handleExec does not insert instrumentation or do
439 // any propagation. Why not? Because it wouldn't be safe -- the
440 // process hasn't yet been bootstrapped (run DYNINST, etc.) Only
441 // when we get the breakpoint at the end of DYNINSTinit() is it safe
442 // to insert instrumentation and allocate timers & counters...
445 #ifndef BPATCH_LIBRARY
446 // need to start resourceBatchMode here because we will call
447 // tryToReadAndProcessBootstrapInfo which
448 // calls tp->resourceBatchMode(false)
449 tp->resourceBatchMode(true);
452 // set reachedFirstBreak to false here, so we execute
453 // the code below, and insert the initial instrumentation
454 // in the new image. (Actually, this is already done by handleExec())
455 curr->reachedFirstBreak = false;
460 // Now we expect that this TRAP is the initial trap sent when a ptrace'd
461 // process completes startup via exec (or when an exec syscall was
462 // executed in an already-running process).
463 // But we must query 'reachedFirstBreak' because on machines where we
464 // attach/detach on pause/continue, a TRAP is generated on each pause!
466 if (!curr->reachedFirstBreak) { // vrble should be renamed 'reachedFirstTrap'
467 // cerr << "!reachedFirstBreak" << endl;
468 string buffer = string("PID=") + string(pid);
469 buffer += string(", passed trap at start of program");
470 statusLine(buffer.string_of());
472 // check for DYNINST symbols and initializes the inferiorHeap
473 // If libdyninst is dynamically linked, this can only be
474 // called after libdyninst is loaded
475 curr->initDyninstLib();
477 curr->reachedFirstBreak = true;
479 buffer=string("PID=") + string(pid) + ", installing call to DYNINSTinit()";
480 statusLine(buffer.string_of());
482 curr->installBootstrapInst();
484 // now, let main() and then DYNINSTinit() get invoked. As it
485 // completes, DYNINSTinit() does a DYNINSTbreakPoint, at which time
486 // we read bootstrap information "sent back" (in a global vrble),
487 // propagate metric instances, do tp->newProgramCallbackFunc(), etc.
488 if (!curr->continueProc()) {
489 cerr << "continueProc after installBootstrapInst() failed, so DYNINSTinit() isn't being invoked yet, which it should!" << endl;
492 buffer=string("PID=") + string(pid) + ", running DYNINSTinit()...";
493 statusLine(buffer.string_of());
497 signal_cerr << "SIGTRAP not handled for pid " << pid << " so just leaving process in stopped state" << endl << flush;
505 signal_cerr << "welcome to SIGSTOP/SIGINT for proc pid " << curr->getPid() << endl;
507 const processState prevStatus = curr->status_;
508 // assert(prevStatus != stopped); (bombs on sunos and AIX, when lots of spurious sigstops are delivered)
510 curr->status_ = stopped;
511 // the following routines expect (and assert) this status.
513 int result = curr->procStopFromDYNINSTinit();
514 assert(result >=0 && result <= 2);
516 forkexec_cerr << "processed SIGSTOP from DYNINSTinit for pid " << curr->getPid() << endl << flush;
519 assert(curr->status_ == stopped);
520 // DYNINSTinit() after normal startup, after fork, or after exec
521 // syscall was made by a running program; leave paused
522 // (tp->newProgramCallback() to paradyn will result in the process
523 // being continued soon enough, assuming the applic was running,
524 // which is true in all cases except when an applic is just being
525 // started up). Fall through (we want the status line to change)
528 break; // don't fall through...prog is finishing the inferiorRPC
531 else if (curr->handleTrapIfDueToRPC()) {
532 inferiorrpc_cerr << "processed RPC response in SIGSTOP" << endl;
533 break; // don't want to execute ->Stopped() which changes status line
535 #ifndef BPATCH_LIBRARY
536 else if (curr->handleStopDueToExecEntry()) {
537 // grabs data from DYNINST_bootstrap_info
538 forkexec_cerr << "fork/exec -- handled stop before exec" << endl;
539 string buffer = string("process ") + string(curr->getPid()) +
540 " performing exec() syscall...";
541 statusLine(buffer.string_of());
543 // note: status will now be 'running', since handleStopDueToExec()
544 // did a continueProc() to let the exec() syscall go forward.
545 assert(curr->status_ == running);
546 // would neonatal be better? or exited?
548 break; // don't want to change status line in conventional way
550 #endif /* BPATCH_LIBRARY */
552 forkexec_cerr << "unhandled SIGSTOP for pid " << curr->getPid() << " so just leaving process in paused state." << endl << flush;
554 curr->status_ = prevStatus; // so Stopped() below won't be a nop
561 signal_cerr << "welcome to SIGILL" << endl << flush;
562 curr->status_ = stopped;
564 if (curr->handleTrapIfDueToRPC()) {
565 inferiorrpc_cerr << "processed RPC response in SIGILL" << endl; cerr.flush();
567 break; // we don't forward the signal -- on purpose
570 // fall through, on purpose
575 #if (defined(POWER_DEBUG) || defined(HP_DEBUG)) && (defined(rs6000_ibm_aix4_1) || defined(hppa1_1_hp_hpux))
576 // In this way, we will detach from the application and we
577 // will be able to attach again using gdb. We need to send
578 // a kill -ILL pid signal to the application in order to
580 #if defined(rs6000_ibm_aix4_1)
581 if (ptrace(PT_DETACH,pid,(int *) 1, SIGSTOP, NULL) == -1) {
583 if (ptrace(PT_DETACH, pid, 1, SIGSTOP, NULL) == -1) {
585 logLine("ptrace error\n");
588 signal_cerr << "caught signal, dying... (sig="
589 << WSTOPSIG(status) << ")" << endl << flush;
591 curr->status_ = stopped;
593 curr->continueWithForwardSignal(WSTOPSIG(status));
599 // Due to the DYNINSTin_sample variable, it's safest to launch
600 // inferior-RPCs only when we know that the inferior is not in the
601 // middle of processing an alarm-expire. Otherwise, code that does
602 // stuff like call DYNINSTstartWallTimer will appear to do nothing
603 // (DYNINSTstartWallTimer will be invoked but will see that
604 // DYNINSTin_sample is set and so bails out!!!)
606 if (curr->existsRPCreadyToLaunch()) {
607 curr -> status_ = stopped;
608 (void)curr->launchRPCifAppropriate(true, false);
609 break; // sure, we lose the SIGALARM, but so what.
612 ; // no break, on purpose
620 case SIGSEGV: // treadmarks needs this signal
621 #if (defined(POWER_DEBUG) || defined(HP_DEBUG)) && (defined(rs6000_ibm_aix4_1) || defined(hppa1_1_hp_hpux))
622 // In this way, we will detach from the application and we
623 // will be able to attach again using gdb - naim
626 logLine("==> Detaching paradynd from the application...\n");
627 #if defined(rs6000_ibm_aix4_1)
628 if (ptrace(PT_DETACH,pid,(int *) 1, SIGSTOP, NULL) == -1)
630 if (ptrace(PT_DETACH,pid, 1, SIGSTOP, NULL) == -1)
632 logLine("ptrace error\n");
636 if (!curr->continueWithForwardSignal(WSTOPSIG(status))) {
637 logLine("error in forwarding signal\n");
638 showErrorCallback(38, "Error in forwarding signal");
645 // XXXX for debugging
646 case SIGSEGV: // treadmarks needs this signal
647 sprintf(errorLine, "DEBUG: forwarding signal (sig=%d, pid=%d)\n"
648 , WSTOPSIG(status), pid);
652 if (!curr->continueWithForwardSignal(WSTOPSIG(status))) {
653 logLine("error in forwarding signal\n");
659 } else if (WIFEXITED(status)) {
660 #if defined(PARADYND_PVM)
661 // if (pvm_running) {
662 // PDYN_reportSIGCHLD (pid, WEXITSTATUS(status));
665 sprintf(errorLine, "Process %d has terminated\n", curr->getPid());
666 statusLine(errorLine);
670 handleProcessExit(curr, WEXITSTATUS(status));
671 } else if (WIFSIGNALED(status)) {
672 sprintf(errorLine, "process %d has terminated on signal %d\n", curr->getPid(), WTERMSIG(status));
674 statusLine(errorLine);
675 handleProcessExit(curr, WTERMSIG(status));
677 sprintf(errorLine, "Unknown state %d from process %d\n", status, curr->getPid());
679 showErrorCallback(39,(const char *) errorLine);
685 void checkProcStatus() {
686 /* check for status change on inferior processes, or the arrival of
690 int wait_pid = process::waitProcs(&wait_status);
692 if (handleSigChild(wait_pid, wait_status) < 0) {
693 cerr << "handleSigChild failed for pid " << wait_pid << endl;
699 bool OS::osKill(int pid) {
700 return (P_kill(pid,9)==0);