1*12927SRod.Evans@Sun.COM /*
2*12927SRod.Evans@Sun.COM * CDDL HEADER START
3*12927SRod.Evans@Sun.COM *
4*12927SRod.Evans@Sun.COM * The contents of this file are subject to the terms of the
5*12927SRod.Evans@Sun.COM * Common Development and Distribution License (the "License").
6*12927SRod.Evans@Sun.COM * You may not use this file except in compliance with the License.
7*12927SRod.Evans@Sun.COM *
8*12927SRod.Evans@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12927SRod.Evans@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12927SRod.Evans@Sun.COM * See the License for the specific language governing permissions
11*12927SRod.Evans@Sun.COM * and limitations under the License.
12*12927SRod.Evans@Sun.COM *
13*12927SRod.Evans@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12927SRod.Evans@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12927SRod.Evans@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12927SRod.Evans@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12927SRod.Evans@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12927SRod.Evans@Sun.COM *
19*12927SRod.Evans@Sun.COM * CDDL HEADER END
20*12927SRod.Evans@Sun.COM */
21*12927SRod.Evans@Sun.COM
22*12927SRod.Evans@Sun.COM /*
23*12927SRod.Evans@Sun.COM * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
24*12927SRod.Evans@Sun.COM */
25*12927SRod.Evans@Sun.COM
26*12927SRod.Evans@Sun.COM #include <stdio.h>
27*12927SRod.Evans@Sun.COM #include <stdlib.h>
28*12927SRod.Evans@Sun.COM #include <unistd.h>
29*12927SRod.Evans@Sun.COM #include <sys/uio.h>
30*12927SRod.Evans@Sun.COM #include <fcntl.h>
31*12927SRod.Evans@Sun.COM #include <string.h>
32*12927SRod.Evans@Sun.COM #include <errno.h>
33*12927SRod.Evans@Sun.COM #include <sys/types.h>
34*12927SRod.Evans@Sun.COM #include <sys/signal.h>
35*12927SRod.Evans@Sun.COM #include <sys/fault.h>
36*12927SRod.Evans@Sun.COM #include <sys/syscall.h>
37*12927SRod.Evans@Sun.COM #include <procfs.h>
38*12927SRod.Evans@Sun.COM #include <sys/auxv.h>
39*12927SRod.Evans@Sun.COM #include <libelf.h>
40*12927SRod.Evans@Sun.COM #include <sys/param.h>
41*12927SRod.Evans@Sun.COM #include <sys/machelf.h>
42*12927SRod.Evans@Sun.COM #include <stdarg.h>
43*12927SRod.Evans@Sun.COM
44*12927SRod.Evans@Sun.COM #include <proc_service.h>
45*12927SRod.Evans@Sun.COM
46*12927SRod.Evans@Sun.COM #include "rdb.h"
47*12927SRod.Evans@Sun.COM #include "disasm.h"
48*12927SRod.Evans@Sun.COM #include "gram.h"
49*12927SRod.Evans@Sun.COM
50*12927SRod.Evans@Sun.COM #define PROCSIZE 20
51*12927SRod.Evans@Sun.COM
52*12927SRod.Evans@Sun.COM static void
init_proc()53*12927SRod.Evans@Sun.COM init_proc()
54*12927SRod.Evans@Sun.COM {
55*12927SRod.Evans@Sun.COM int pfd;
56*12927SRod.Evans@Sun.COM char procname[PROCSIZE];
57*12927SRod.Evans@Sun.COM sigset_t sigset;
58*12927SRod.Evans@Sun.COM fltset_t fltset;
59*12927SRod.Evans@Sun.COM sysset_t sysset;
60*12927SRod.Evans@Sun.COM long oper, pflags;
61*12927SRod.Evans@Sun.COM struct iovec piov[2];
62*12927SRod.Evans@Sun.COM
63*12927SRod.Evans@Sun.COM /*
64*12927SRod.Evans@Sun.COM * open our own /proc file and set tracing flags
65*12927SRod.Evans@Sun.COM */
66*12927SRod.Evans@Sun.COM (void) snprintf(procname, PROCSIZE, "/proc/%d/ctl", EC_SWORD(getpid()));
67*12927SRod.Evans@Sun.COM if ((pfd = open(procname, O_WRONLY)) < 0) {
68*12927SRod.Evans@Sun.COM (void) fprintf(stderr, "can't open %s\n", procname);
69*12927SRod.Evans@Sun.COM exit(1);
70*12927SRod.Evans@Sun.COM }
71*12927SRod.Evans@Sun.COM
72*12927SRod.Evans@Sun.COM /*
73*12927SRod.Evans@Sun.COM * inherit on fork, and kill-on-last-close
74*12927SRod.Evans@Sun.COM */
75*12927SRod.Evans@Sun.COM oper = PCSET;
76*12927SRod.Evans@Sun.COM piov[0].iov_base = (caddr_t)(&oper);
77*12927SRod.Evans@Sun.COM piov[0].iov_len = sizeof (oper);
78*12927SRod.Evans@Sun.COM pflags = PR_FORK;
79*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&pflags;
80*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (pflags);
81*12927SRod.Evans@Sun.COM
82*12927SRod.Evans@Sun.COM if (writev(pfd, piov, 2) == -1)
83*12927SRod.Evans@Sun.COM perr("init_proc: PCSET");
84*12927SRod.Evans@Sun.COM
85*12927SRod.Evans@Sun.COM /*
86*12927SRod.Evans@Sun.COM * no signal tracing
87*12927SRod.Evans@Sun.COM */
88*12927SRod.Evans@Sun.COM oper = PCSTRACE;
89*12927SRod.Evans@Sun.COM premptyset(&sigset);
90*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&sigset;
91*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (sigset);
92*12927SRod.Evans@Sun.COM if (writev(pfd, piov, 2) == -1)
93*12927SRod.Evans@Sun.COM perr("PCSTRACE");
94*12927SRod.Evans@Sun.COM
95*12927SRod.Evans@Sun.COM /*
96*12927SRod.Evans@Sun.COM * no fault tracing
97*12927SRod.Evans@Sun.COM */
98*12927SRod.Evans@Sun.COM oper = PCSFAULT;
99*12927SRod.Evans@Sun.COM premptyset(&fltset);
100*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&fltset;
101*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (fltset);
102*12927SRod.Evans@Sun.COM if (writev(pfd, piov, 2) == -1)
103*12927SRod.Evans@Sun.COM perr("PCSFAULT");
104*12927SRod.Evans@Sun.COM
105*12927SRod.Evans@Sun.COM /*
106*12927SRod.Evans@Sun.COM * no syscall tracing
107*12927SRod.Evans@Sun.COM */
108*12927SRod.Evans@Sun.COM oper = PCSENTRY;
109*12927SRod.Evans@Sun.COM premptyset(&sysset);
110*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&sysset;
111*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (sysset);
112*12927SRod.Evans@Sun.COM if (writev(pfd, piov, 2) == -1)
113*12927SRod.Evans@Sun.COM perr("PSENTRY");
114*12927SRod.Evans@Sun.COM
115*12927SRod.Evans@Sun.COM /*
116*12927SRod.Evans@Sun.COM * except exit from exec() or execve()
117*12927SRod.Evans@Sun.COM */
118*12927SRod.Evans@Sun.COM oper = PCSEXIT;
119*12927SRod.Evans@Sun.COM premptyset(&sysset);
120*12927SRod.Evans@Sun.COM praddset(&sysset, SYS_execve);
121*12927SRod.Evans@Sun.COM if (writev(pfd, piov, 2) == -1)
122*12927SRod.Evans@Sun.COM perr("PCSEXIT");
123*12927SRod.Evans@Sun.COM
124*12927SRod.Evans@Sun.COM (void) close(pfd);
125*12927SRod.Evans@Sun.COM }
126*12927SRod.Evans@Sun.COM
127*12927SRod.Evans@Sun.COM int
main(int argc,char * argv[])128*12927SRod.Evans@Sun.COM main(int argc, char *argv[])
129*12927SRod.Evans@Sun.COM {
130*12927SRod.Evans@Sun.COM int pctlfd;
131*12927SRod.Evans@Sun.COM int pstatusfd;
132*12927SRod.Evans@Sun.COM char procname[PROCSIZE];
133*12927SRod.Evans@Sun.COM char *command;
134*12927SRod.Evans@Sun.COM char *rdb_commands = NULL;
135*12927SRod.Evans@Sun.COM pid_t cpid;
136*12927SRod.Evans@Sun.COM pstatus_t pstatus;
137*12927SRod.Evans@Sun.COM sysset_t sysset;
138*12927SRod.Evans@Sun.COM int c;
139*12927SRod.Evans@Sun.COM int error = 0;
140*12927SRod.Evans@Sun.COM long oper;
141*12927SRod.Evans@Sun.COM struct iovec piov[2];
142*12927SRod.Evans@Sun.COM extern FILE *yyin;
143*12927SRod.Evans@Sun.COM
144*12927SRod.Evans@Sun.COM command = argv[0];
145*12927SRod.Evans@Sun.COM
146*12927SRod.Evans@Sun.COM while ((c = getopt(argc, argv, "f:")) != EOF)
147*12927SRod.Evans@Sun.COM switch (c) {
148*12927SRod.Evans@Sun.COM case 'f':
149*12927SRod.Evans@Sun.COM rdb_commands = optarg;
150*12927SRod.Evans@Sun.COM break;
151*12927SRod.Evans@Sun.COM case '?':
152*12927SRod.Evans@Sun.COM break;
153*12927SRod.Evans@Sun.COM }
154*12927SRod.Evans@Sun.COM
155*12927SRod.Evans@Sun.COM if (error || (optind == argc)) {
156*12927SRod.Evans@Sun.COM (void) printf("usage: %s [-f file] executable "
157*12927SRod.Evans@Sun.COM "[executable arguments ...]\n", command);
158*12927SRod.Evans@Sun.COM (void) printf("\t-f command file\n");
159*12927SRod.Evans@Sun.COM exit(1);
160*12927SRod.Evans@Sun.COM }
161*12927SRod.Evans@Sun.COM
162*12927SRod.Evans@Sun.COM /*
163*12927SRod.Evans@Sun.COM * set up for tracing the child.
164*12927SRod.Evans@Sun.COM */
165*12927SRod.Evans@Sun.COM init_proc();
166*12927SRod.Evans@Sun.COM
167*12927SRod.Evans@Sun.COM /*
168*12927SRod.Evans@Sun.COM * create a child to fork and exec from.
169*12927SRod.Evans@Sun.COM */
170*12927SRod.Evans@Sun.COM if ((cpid = fork()) == 0) {
171*12927SRod.Evans@Sun.COM (void) execv(argv[optind], &argv[optind]);
172*12927SRod.Evans@Sun.COM perr(argv[1]);
173*12927SRod.Evans@Sun.COM }
174*12927SRod.Evans@Sun.COM
175*12927SRod.Evans@Sun.COM if (cpid == -1) /* fork() failure */
176*12927SRod.Evans@Sun.COM perr(command);
177*12927SRod.Evans@Sun.COM
178*12927SRod.Evans@Sun.COM /*
179*12927SRod.Evans@Sun.COM * initialize libelf
180*12927SRod.Evans@Sun.COM */
181*12927SRod.Evans@Sun.COM if (elf_version(EV_CURRENT) == EV_NONE) {
182*12927SRod.Evans@Sun.COM (void) fprintf(stderr, "elf_version() failed: %s\n",
183*12927SRod.Evans@Sun.COM elf_errmsg(0));
184*12927SRod.Evans@Sun.COM exit(1);
185*12927SRod.Evans@Sun.COM }
186*12927SRod.Evans@Sun.COM
187*12927SRod.Evans@Sun.COM /*
188*12927SRod.Evans@Sun.COM * initialize librtld_db
189*12927SRod.Evans@Sun.COM */
190*12927SRod.Evans@Sun.COM if (rd_init(RD_VERSION) != RD_OK) {
191*12927SRod.Evans@Sun.COM (void) fprintf(stderr, "librtld_db::rd_init() failed: version "
192*12927SRod.Evans@Sun.COM "submitted: %d\n", RD_VERSION);
193*12927SRod.Evans@Sun.COM exit(1);
194*12927SRod.Evans@Sun.COM }
195*12927SRod.Evans@Sun.COM
196*12927SRod.Evans@Sun.COM /* rd_log(1); */
197*12927SRod.Evans@Sun.COM
198*12927SRod.Evans@Sun.COM /*
199*12927SRod.Evans@Sun.COM * Child should now be waiting after the successful
200*12927SRod.Evans@Sun.COM * exec.
201*12927SRod.Evans@Sun.COM */
202*12927SRod.Evans@Sun.COM (void) snprintf(procname, PROCSIZE, "/proc/%d/ctl", EC_SWORD(cpid));
203*12927SRod.Evans@Sun.COM (void) printf("parent: %d child: %d child procname: %s\n",
204*12927SRod.Evans@Sun.COM EC_SWORD(getpid()), EC_SWORD(cpid), procname);
205*12927SRod.Evans@Sun.COM if ((pctlfd = open(procname, O_WRONLY)) < 0) {
206*12927SRod.Evans@Sun.COM perror(procname);
207*12927SRod.Evans@Sun.COM (void) fprintf(stderr, "%s: can't open child %s\n",
208*12927SRod.Evans@Sun.COM command, procname);
209*12927SRod.Evans@Sun.COM exit(1);
210*12927SRod.Evans@Sun.COM }
211*12927SRod.Evans@Sun.COM
212*12927SRod.Evans@Sun.COM /*
213*12927SRod.Evans@Sun.COM * wait for child process.
214*12927SRod.Evans@Sun.COM */
215*12927SRod.Evans@Sun.COM oper = PCWSTOP;
216*12927SRod.Evans@Sun.COM piov[0].iov_base = (caddr_t)&oper;
217*12927SRod.Evans@Sun.COM piov[0].iov_len = sizeof (oper);
218*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 1) == -1)
219*12927SRod.Evans@Sun.COM perr("PCWSTOP");
220*12927SRod.Evans@Sun.COM
221*12927SRod.Evans@Sun.COM /*
222*12927SRod.Evans@Sun.COM * open /proc/<cpid>/status
223*12927SRod.Evans@Sun.COM */
224*12927SRod.Evans@Sun.COM (void) snprintf(procname, PROCSIZE, "/proc/%d/status", EC_SWORD(cpid));
225*12927SRod.Evans@Sun.COM if ((pstatusfd = open(procname, O_RDONLY)) == -1)
226*12927SRod.Evans@Sun.COM perr(procname);
227*12927SRod.Evans@Sun.COM
228*12927SRod.Evans@Sun.COM if (read(pstatusfd, &pstatus, sizeof (pstatus)) == -1)
229*12927SRod.Evans@Sun.COM perr("status read failed");
230*12927SRod.Evans@Sun.COM
231*12927SRod.Evans@Sun.COM /*
232*12927SRod.Evans@Sun.COM * Make sure that it stopped where we expected.
233*12927SRod.Evans@Sun.COM */
234*12927SRod.Evans@Sun.COM while ((pstatus.pr_lwp.pr_why == PR_SYSEXIT) &&
235*12927SRod.Evans@Sun.COM (pstatus.pr_lwp.pr_what == SYS_execve)) {
236*12927SRod.Evans@Sun.COM long pflags = 0;
237*12927SRod.Evans@Sun.COM if (!(pstatus.pr_lwp.pr_reg[R_PS] & ERRBIT)) {
238*12927SRod.Evans@Sun.COM /* successfull exec(2) */
239*12927SRod.Evans@Sun.COM break;
240*12927SRod.Evans@Sun.COM }
241*12927SRod.Evans@Sun.COM
242*12927SRod.Evans@Sun.COM oper = PCRUN;
243*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&pflags;
244*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (pflags);
245*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 2) == -1)
246*12927SRod.Evans@Sun.COM perr("PCRUN1");
247*12927SRod.Evans@Sun.COM
248*12927SRod.Evans@Sun.COM oper = PCWSTOP;
249*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 1) == -1)
250*12927SRod.Evans@Sun.COM perr("PCWSTOP");
251*12927SRod.Evans@Sun.COM
252*12927SRod.Evans@Sun.COM if (read(pstatusfd, &pstatus, sizeof (pstatus)) == -1)
253*12927SRod.Evans@Sun.COM perr("status read failed");
254*12927SRod.Evans@Sun.COM }
255*12927SRod.Evans@Sun.COM
256*12927SRod.Evans@Sun.COM premptyset(&sysset);
257*12927SRod.Evans@Sun.COM oper = PCSEXIT;
258*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&sysset;
259*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (sysset);
260*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 2) == -1)
261*12927SRod.Evans@Sun.COM perr("PIOCSEXIT");
262*12927SRod.Evans@Sun.COM
263*12927SRod.Evans@Sun.COM /*
264*12927SRod.Evans@Sun.COM * Did we stop where we expected ?
265*12927SRod.Evans@Sun.COM */
266*12927SRod.Evans@Sun.COM if ((pstatus.pr_lwp.pr_why != PR_SYSEXIT) ||
267*12927SRod.Evans@Sun.COM (pstatus.pr_lwp.pr_what != SYS_execve)) {
268*12927SRod.Evans@Sun.COM long pflags = 0;
269*12927SRod.Evans@Sun.COM
270*12927SRod.Evans@Sun.COM (void) fprintf(stderr, "Didn't catch the exec, why: %d "
271*12927SRod.Evans@Sun.COM "what: %d\n", pstatus.pr_lwp.pr_why,
272*12927SRod.Evans@Sun.COM pstatus.pr_lwp.pr_what);
273*12927SRod.Evans@Sun.COM
274*12927SRod.Evans@Sun.COM oper = PCRUN;
275*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&pflags;
276*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (pflags);
277*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 2) == -1)
278*12927SRod.Evans@Sun.COM perr("PCRUN2");
279*12927SRod.Evans@Sun.COM exit(1);
280*12927SRod.Evans@Sun.COM }
281*12927SRod.Evans@Sun.COM
282*12927SRod.Evans@Sun.COM (void) ps_init(pctlfd, pstatusfd, cpid, &proch);
283*12927SRod.Evans@Sun.COM
284*12927SRod.Evans@Sun.COM if (rdb_commands) {
285*12927SRod.Evans@Sun.COM if ((yyin = fopen(rdb_commands, "r")) == NULL) {
286*12927SRod.Evans@Sun.COM (void) printf("unable to open %s for input\n",
287*12927SRod.Evans@Sun.COM rdb_commands);
288*12927SRod.Evans@Sun.COM perr("fopen");
289*12927SRod.Evans@Sun.COM }
290*12927SRod.Evans@Sun.COM } else {
291*12927SRod.Evans@Sun.COM proch.pp_flags |= FLG_PP_PROMPT;
292*12927SRod.Evans@Sun.COM rdb_prompt();
293*12927SRod.Evans@Sun.COM }
294*12927SRod.Evans@Sun.COM (void) yyparse();
295*12927SRod.Evans@Sun.COM
296*12927SRod.Evans@Sun.COM if (proch.pp_flags & FLG_PP_PACT) {
297*12927SRod.Evans@Sun.COM long pflags = PRCFAULT;
298*12927SRod.Evans@Sun.COM
299*12927SRod.Evans@Sun.COM (void) printf("\ncontinuing the hung process...\n");
300*12927SRod.Evans@Sun.COM
301*12927SRod.Evans@Sun.COM pctlfd = proch.pp_ctlfd;
302*12927SRod.Evans@Sun.COM (void) ps_close(&proch);
303*12927SRod.Evans@Sun.COM
304*12927SRod.Evans@Sun.COM oper = PCRUN;
305*12927SRod.Evans@Sun.COM piov[1].iov_base = (caddr_t)&pflags;
306*12927SRod.Evans@Sun.COM piov[1].iov_len = sizeof (pflags);
307*12927SRod.Evans@Sun.COM if (writev(pctlfd, piov, 2) == -1)
308*12927SRod.Evans@Sun.COM perr("PCRUN2");
309*12927SRod.Evans@Sun.COM (void) close(pctlfd);
310*12927SRod.Evans@Sun.COM }
311*12927SRod.Evans@Sun.COM
312*12927SRod.Evans@Sun.COM return (0);
313*12927SRod.Evans@Sun.COM }
314