1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <stdio.h>
27 #include <stdio_ext.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <limits.h>
33 #include <libproc.h>
34 #include <proc_service.h>
35
36 static int show_map(void *, const prmap_t *, const char *);
37
38 static char *command;
39
40 int
main(int argc,char ** argv)41 main(int argc, char **argv)
42 {
43 int rc = 0;
44 int opt;
45 int errflg = 0;
46 int Fflag = 0;
47 int lflag = 0;
48 core_content_t content = CC_CONTENT_DATA | CC_CONTENT_ANON;
49 struct rlimit rlim;
50
51 if ((command = strrchr(argv[0], '/')) != NULL)
52 command++;
53 else
54 command = argv[0];
55
56 /* options */
57 while ((opt = getopt(argc, argv, "Fl")) != EOF) {
58 switch (opt) {
59 case 'F': /* force grabbing (no O_EXCL) */
60 Fflag = PGRAB_FORCE;
61 break;
62 case 'l': /* show unresolved link map names */
63 lflag = 1;
64 break;
65 default:
66 errflg = 1;
67 break;
68 }
69 }
70
71 argc -= optind;
72 argv += optind;
73
74 if (errflg || argc <= 0) {
75 (void) fprintf(stderr,
76 "usage:\t%s [-Fl] { pid | core } ...\n", command);
77 (void) fprintf(stderr,
78 " (report process dynamic libraries)\n");
79 (void) fprintf(stderr,
80 " -F: force grabbing of the target process\n"
81 " -l: show unresolved dynamic linker map names\n");
82 return (2);
83 }
84
85 /*
86 * Make sure we'll have enough file descriptors to handle a target
87 * that has many many mappings.
88 */
89 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
90 rlim.rlim_cur = rlim.rlim_max;
91 (void) setrlimit(RLIMIT_NOFILE, &rlim);
92 (void) enable_extended_FILE_stdio(-1, -1);
93 }
94
95 (void) proc_initstdio();
96
97 while (argc-- > 0) {
98 char *arg;
99 int gcode;
100 psinfo_t psinfo;
101 struct ps_prochandle *Pr;
102
103 (void) proc_flushstdio();
104
105 if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
106 PGRAB_RETAIN | Fflag, &gcode)) == NULL) {
107
108 (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
109 command, arg, Pgrab_error(gcode));
110 rc++;
111 continue;
112 }
113
114 (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
115 proc_unctrl_psinfo(&psinfo);
116
117 if (Pstate(Pr) == PS_DEAD) {
118 if ((Pcontent(Pr) & content) != content) {
119 (void) fprintf(stderr, "%s: core '%s' has "
120 "insufficient content\n", command, arg);
121 rc++;
122 continue;
123 }
124 (void) printf("core '%s' of %d:\t%.70s\n",
125 arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
126 } else {
127 (void) printf("%d:\t%.70s\n",
128 (int)psinfo.pr_pid, psinfo.pr_psargs);
129 }
130
131 if (Pgetauxval(Pr, AT_BASE) != -1L && Prd_agent(Pr) == NULL) {
132 (void) fprintf(stderr, "%s: warning: librtld_db failed "
133 "to initialize; shared library information will "
134 "not be available\n", command);
135 }
136
137 if (lflag)
138 rc += Pobject_iter(Pr, show_map, Pr);
139 else
140 rc += Pobject_iter_resolved(Pr, show_map, Pr);
141 Prelease(Pr, 0);
142 }
143 (void) proc_finistdio();
144
145 return (rc);
146 }
147
148 static int
show_map(void * cd,const prmap_t * pmap,const char * object_name)149 show_map(void *cd, const prmap_t *pmap, const char *object_name)
150 {
151 char pathname[PATH_MAX];
152 struct ps_prochandle *Pr = cd;
153 const auxv_t *auxv;
154 int len;
155
156 /* omit the executable file */
157 if (strcmp(pmap->pr_mapname, "a.out") == 0)
158 return (0);
159
160 /* also omit the dynamic linker */
161 if (ps_pauxv(Pr, &auxv) == PS_OK) {
162 while (auxv->a_type != AT_NULL) {
163 if (auxv->a_type == AT_BASE) {
164 if (pmap->pr_vaddr == auxv->a_un.a_val)
165 return (0);
166 break;
167 }
168 auxv++;
169 }
170 }
171
172 /* freedom from symlinks; canonical form */
173 if ((len = resolvepath(object_name, pathname, sizeof (pathname))) > 0)
174 pathname[len] = '\0';
175 else
176 (void) strncpy(pathname, object_name, sizeof (pathname));
177
178 (void) printf("%s\n", pathname);
179 return (0);
180 }
181