xref: /onnv-gate/usr/src/cmd/sgs/librtld_db/demo/common/main.c (revision 12927:a27c46eb192b)
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