4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <sys/fault.h>
36 #include <sys/syscall.h>
40 #include <sys/param.h>
41 #include <sys/machelf.h>
44 #include <proc_service.h>
56 char procname
[PROCSIZE
];
64 * open our own /proc file and set tracing flags
66 (void) snprintf(procname
, PROCSIZE
, "/proc/%d/ctl", EC_SWORD(getpid()));
67 if ((pfd
= open(procname
, O_WRONLY
)) < 0) {
68 (void) fprintf(stderr
, "can't open %s\n", procname
);
73 * inherit on fork, and kill-on-last-close
76 piov
[0].iov_base
= (caddr_t
)(&oper
);
77 piov
[0].iov_len
= sizeof (oper
);
79 piov
[1].iov_base
= (caddr_t
)&pflags
;
80 piov
[1].iov_len
= sizeof (pflags
);
82 if (writev(pfd
, piov
, 2) == -1)
83 perr("init_proc: PCSET");
90 piov
[1].iov_base
= (caddr_t
)&sigset
;
91 piov
[1].iov_len
= sizeof (sigset
);
92 if (writev(pfd
, piov
, 2) == -1)
100 piov
[1].iov_base
= (caddr_t
)&fltset
;
101 piov
[1].iov_len
= sizeof (fltset
);
102 if (writev(pfd
, piov
, 2) == -1)
110 piov
[1].iov_base
= (caddr_t
)&sysset
;
111 piov
[1].iov_len
= sizeof (sysset
);
112 if (writev(pfd
, piov
, 2) == -1)
116 * except exit from exec() or execve()
120 praddset(&sysset
, SYS_execve
);
121 if (writev(pfd
, piov
, 2) == -1)
128 main(int argc
, char *argv
[])
132 char procname
[PROCSIZE
];
134 char *rdb_commands
= NULL
;
141 struct iovec piov
[2];
146 while ((c
= getopt(argc
, argv
, "f:")) != EOF
)
149 rdb_commands
= optarg
;
155 if (error
|| (optind
== argc
)) {
156 (void) printf("usage: %s [-f file] executable "
157 "[executable arguments ...]\n", command
);
158 (void) printf("\t-f command file\n");
163 * set up for tracing the child.
168 * create a child to fork and exec from.
170 if ((cpid
= fork()) == 0) {
171 (void) execv(argv
[optind
], &argv
[optind
]);
175 if (cpid
== -1) /* fork() failure */
181 if (elf_version(EV_CURRENT
) == EV_NONE
) {
182 (void) fprintf(stderr
, "elf_version() failed: %s\n",
188 * initialize librtld_db
190 if (rd_init(RD_VERSION
) != RD_OK
) {
191 (void) fprintf(stderr
, "librtld_db::rd_init() failed: version "
192 "submitted: %d\n", RD_VERSION
);
199 * Child should now be waiting after the successful
202 (void) snprintf(procname
, PROCSIZE
, "/proc/%d/ctl", EC_SWORD(cpid
));
203 (void) printf("parent: %d child: %d child procname: %s\n",
204 EC_SWORD(getpid()), EC_SWORD(cpid
), procname
);
205 if ((pctlfd
= open(procname
, O_WRONLY
)) < 0) {
207 (void) fprintf(stderr
, "%s: can't open child %s\n",
213 * wait for child process.
216 piov
[0].iov_base
= (caddr_t
)&oper
;
217 piov
[0].iov_len
= sizeof (oper
);
218 if (writev(pctlfd
, piov
, 1) == -1)
222 * open /proc/<cpid>/status
224 (void) snprintf(procname
, PROCSIZE
, "/proc/%d/status", EC_SWORD(cpid
));
225 if ((pstatusfd
= open(procname
, O_RDONLY
)) == -1)
228 if (read(pstatusfd
, &pstatus
, sizeof (pstatus
)) == -1)
229 perr("status read failed");
232 * Make sure that it stopped where we expected.
234 while ((pstatus
.pr_lwp
.pr_why
== PR_SYSEXIT
) &&
235 (pstatus
.pr_lwp
.pr_what
== SYS_execve
)) {
237 if (!(pstatus
.pr_lwp
.pr_reg
[R_PS
] & ERRBIT
)) {
238 /* successfull exec(2) */
243 piov
[1].iov_base
= (caddr_t
)&pflags
;
244 piov
[1].iov_len
= sizeof (pflags
);
245 if (writev(pctlfd
, piov
, 2) == -1)
249 if (writev(pctlfd
, piov
, 1) == -1)
252 if (read(pstatusfd
, &pstatus
, sizeof (pstatus
)) == -1)
253 perr("status read failed");
258 piov
[1].iov_base
= (caddr_t
)&sysset
;
259 piov
[1].iov_len
= sizeof (sysset
);
260 if (writev(pctlfd
, piov
, 2) == -1)
264 * Did we stop where we expected ?
266 if ((pstatus
.pr_lwp
.pr_why
!= PR_SYSEXIT
) ||
267 (pstatus
.pr_lwp
.pr_what
!= SYS_execve
)) {
270 (void) fprintf(stderr
, "Didn't catch the exec, why: %d "
271 "what: %d\n", pstatus
.pr_lwp
.pr_why
,
272 pstatus
.pr_lwp
.pr_what
);
275 piov
[1].iov_base
= (caddr_t
)&pflags
;
276 piov
[1].iov_len
= sizeof (pflags
);
277 if (writev(pctlfd
, piov
, 2) == -1)
282 (void) ps_init(pctlfd
, pstatusfd
, cpid
, &proch
);
285 if ((yyin
= fopen(rdb_commands
, "r")) == NULL
) {
286 (void) printf("unable to open %s for input\n",
291 proch
.pp_flags
|= FLG_PP_PROMPT
;
296 if (proch
.pp_flags
& FLG_PP_PACT
) {
297 long pflags
= PRCFAULT
;
299 (void) printf("\ncontinuing the hung process...\n");
301 pctlfd
= proch
.pp_ctlfd
;
302 (void) ps_close(&proch
);
305 piov
[1].iov_base
= (caddr_t
)&pflags
;
306 piov
[1].iov_len
= sizeof (pflags
);
307 if (writev(pctlfd
, piov
, 2) == -1)
309 (void) close(pctlfd
);