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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 uint_t 57 dbg_setup(const char *options) 58 { 59 uint_t _dbg_mask; 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 ((_dbg_mask = Dbg_setup(options)) == (uint_t)S_ERROR) 91 return (0); 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_FMT_FILE), 103 dbg_file, (int)getpid()); 104 if ((dbg_fd = open(file, (O_RDWR | O_CREAT), 0666)) == -1) { 105 int err = errno; 106 107 eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), file, 108 strerror(err)); 109 dbg_mask = 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 (_dbg_mask); 130 } 131 132 /* 133 * All diagnostic requests are funneled to this routine. 134 */ 135 /*PRINTFLIKE1*/ 136 void 137 dbg_print(const char *format, ...) 138 { 139 va_list args; 140 char buffer[ERRSIZE + 1]; 141 pid_t _pid; 142 struct stat status; 143 Prfbuf prf; 144 145 /* 146 * If we're in the application make sure the debugging file descriptor 147 * is still available (ie, the user hasn't closed and/or reused the 148 * same descriptor). 149 */ 150 if (rtld_flags & RT_FL_APPLIC) { 151 if ((fstat(dbg_fd, &status) == -1) || 152 (status.st_dev != dbg_dev) || 153 (status.st_ino != dbg_ino)) { 154 if (dbg_file) { 155 /* 156 * If the user specified output file has been 157 * disconnected try and reconnect to it. 158 */ 159 char file[MAXPATHLEN]; 160 161 (void) snprintf(file, MAXPATHLEN, 162 MSG_ORIG(MSG_DBG_FMT_FILE), dbg_file, 163 (int)pid); 164 if ((dbg_fd = open(file, (O_RDWR | O_APPEND), 165 0)) == -1) { 166 dbg_mask = 0; 167 return; 168 } 169 (void) fstat(dbg_fd, &status); 170 dbg_dev = status.st_dev; 171 dbg_ino = status.st_ino; 172 } else { 173 /* 174 * If stderr has been stolen from us simply 175 * turn debugging off. 176 */ 177 dbg_mask = 0; 178 return; 179 } 180 } 181 } 182 183 /* 184 * The getpid() call is a 'special' interface between ld.so.1 185 * and dbx, because of this getpid() can't be called freely 186 * until after control has been given to the user program. 187 * Once the control has been given to the user program 188 * we know that the r_debug structure has been properly 189 * initialized for the debugger. 190 */ 191 if (rtld_flags & RT_FL_APPLIC) 192 _pid = getpid(); 193 else 194 _pid = pid; 195 196 prf.pr_buf = prf.pr_cur = buffer; 197 prf.pr_len = ERRSIZE; 198 prf.pr_fd = dbg_fd; 199 200 if (rtld_flags & RT_FL_THREADS) 201 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_FMT_THREAD), _pid, 202 rt_thr_self()); 203 else 204 (void) bufprint(&prf, MSG_ORIG(MSG_DBG_FMT_DIAG), _pid); 205 206 /* 207 * Format the message and print it. 208 */ 209 va_start(args, format); 210 prf.pr_cur--; 211 (void) doprf(format, args, &prf); 212 *(prf.pr_cur - 1) = '\n'; 213 (void) dowrite(&prf); 214 va_end(args); 215 } 216