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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "_synonyms.h" 30 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <sys/param.h> 34 #include <stdio.h> 35 #include <fcntl.h> 36 #include <stdarg.h> 37 #include <dlfcn.h> 38 #include <unistd.h> 39 #include <string.h> 40 #include <thread.h> 41 #include <debug.h> 42 #include "_rtld.h" 43 #include "_elf.h" 44 #include "msg.h" 45 46 47 static int dbg_fd; /* debugging output file descriptor */ 48 static dev_t dbg_dev; 49 static ino_t dbg_ino; 50 static pid_t pid; 51 52 /* 53 * Enable diagnostic output. All debugging functions reside in the linker 54 * debugging library liblddbg.so which is lazy loaded when required. 55 */ 56 uintptr_t 57 dbg_setup(const char *options, Dbg_desc *dbp) 58 { 59 uintptr_t ret; 60 struct stat status; 61 62 /* 63 * If we're running secure, only allow debugging if ld.so.1 itself is 64 * owned by root and has its mode setuid. Fail silently. 65 */ 66 if (rtld_flags & RT_FL_SECURE) { 67 struct stat status; 68 69 if (stat(NAME(lml_rtld.lm_head), &status) == 0) { 70 if ((status.st_uid != 0) || 71 (!(status.st_mode & S_ISUID))) 72 return (0); 73 } else 74 return (0); 75 } 76 77 /* 78 * As Dbg_setup() will effectively lazy load the necessary support 79 * libraries, make sure ld.so.1 is initialized for plt relocations. 80 */ 81 if (elf_rtld_load() == 0) 82 return (0); 83 84 /* 85 * Call the debugging setup routine. This function verifies the 86 * debugging tokens provided and returns a mask indicating the debugging 87 * categories selected. The mask effectively enables calls to the 88 * debugging library. 89 */ 90 if ((ret = Dbg_setup(options, dbp)) != (uintptr_t)1) 91 return (ret); 92 93 /* 94 * If an LD_DEBUG_OUTPUT file was specified then we need to direct all 95 * diagnostics to the specified file. Add the process id as a file 96 * suffix so that multiple processes that inherit the same debugging 97 * environment variable don't fight over the same file. 98 */ 99 if (dbg_file) { 100 char file[MAXPATHLEN]; 101 102 (void) snprintf(file, MAXPATHLEN, MSG_ORIG(MSG_DBG_FILE), 103 dbg_file, getpid()); 104 if ((dbg_fd = open(file, (O_RDWR | O_CREAT), 0666)) == -1) { 105 int err = errno; 106 107 eprintf(&lml_rtld, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 108 file, strerror(err)); 109 dbp->d_class = 0; 110 return (0); 111 } 112 } else { 113 /* 114 * The default is to direct debugging to the stderr. 115 */ 116 dbg_fd = 2; 117 } 118 119 /* 120 * Initialize the dev/inode pair to enable us to determine if 121 * the debugging file descriptor is still available once the 122 * application has been entered. 123 */ 124 (void) fstat(dbg_fd, &status); 125 dbg_dev = status.st_dev; 126 dbg_ino = status.st_ino; 127 pid = getpid(); 128 129 return (ret); 130 } 131 132 static int 133 dbg_lmid(Lm_list *lml) 134 { 135 const char *str; 136 Aliste idx; 137 138 for (APLIST_TRAVERSE(dbg_desc->d_list, idx, str)) { 139 if (strcmp(lml->lm_lmidstr, str) == 0) 140 return (1); 141 } 142 return (0); 143 } 144 145 /* 146 * All diagnostic requests are funneled to this routine. 147 */ 148 /* PRINTFLIKE2 */ 149 void 150 dbg_print(Lm_list *lml, const char *format, ...) 151 { 152 va_list args; 153 char buffer[ERRSIZE + 1]; 154 pid_t _pid; 155 struct stat status; 156 Prfbuf prf; 157 158 /* 159 * Knock off any newline indicator to signify that a diagnostic has 160 * been processed. 161 */ 162 dbg_desc->d_extra &= ~DBG_E_STDNL; 163 164 /* 165 * If debugging has been isolated to individual link-map lists, 166 * determine whether this request originates from a link-map list that 167 * is being monitored. Otherwise, process all link-map list diagnostics 168 * except those that originate from ld.so.1 processing its own 169 * dependencies. 170 */ 171 if (dbg_desc->d_list && lml && lml->lm_lmidstr) { 172 if (dbg_lmid(lml) == 0) 173 return; 174 } else if (lml && (lml->lm_flags & LML_FLG_RTLDLM)) 175 return; 176 177 /* 178 * If we're in the application make sure the debugging file descriptor 179 * is still available (ie, the user hasn't closed and/or reused the 180 * same descriptor). 181 */ 182 if (rtld_flags & RT_FL_APPLIC) { 183 if ((fstat(dbg_fd, &status) == -1) || 184 (status.st_dev != dbg_dev) || 185 (status.st_ino != dbg_ino)) { 186 if (dbg_file) { 187 /* 188 * If the user specified output file has been 189 * disconnected try and reconnect to it. 190 */ 191 char file[MAXPATHLEN]; 192 193 (void) snprintf(file, MAXPATHLEN, 194 MSG_ORIG(MSG_DBG_FILE), dbg_file, pid); 195 if ((dbg_fd = open(file, (O_RDWR | O_APPEND), 196 0)) == -1) { 197 dbg_desc->d_class = 0; 198 return; 199 } 200 (void) fstat(dbg_fd, &status); 201 dbg_dev = status.st_dev; 202 dbg_ino = status.st_ino; 203 } else { 204 /* 205 * If stderr has been stolen from us simply 206 * turn debugging off. 207 */ 208 dbg_desc->d_class = 0; 209 return; 210 } 211 } 212 } 213 214 prf.pr_buf = prf.pr_cur = buffer; 215 prf.pr_len = ERRSIZE; 216 prf.pr_fd = dbg_fd; 217 218 /* 219 * The getpid() call is a 'special' interface between ld.so.1 and dbx, 220 * because of this getpid() can't be called freely until after control 221 * has been given to the user program. Once the control has been given 222 * to the user program we know that the r_debug structure has been 223 * properly initialized for the debugger. 224 */ 225 if (rtld_flags & RT_FL_APPLIC) 226 _pid = getpid(); 227 else 228 _pid = pid; 229 230 if (lml) 231 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_PID), _pid); 232 else 233 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_UNDEF)); 234 prf.pr_cur--; 235 236 if (DBG_ISLMID() && lml && lml->lm_lmidstr) { 237 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_LMID), lml->lm_lmidstr); 238 prf.pr_cur--; 239 } 240 if (rtld_flags & RT_FL_THREADS) { 241 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_THREAD), rt_thr_self()); 242 prf.pr_cur--; 243 } 244 245 /* 246 * Format the message and print it. 247 */ 248 va_start(args, format); 249 (void) doprf(format, args, &prf); 250 *(prf.pr_cur - 1) = '\n'; 251 (void) dowrite(&prf); 252 va_end(args); 253 } 254