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 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 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