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 #include <libintl.h> 28 #include <sys/varargs.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <alist.h> 33 #include <debug.h> 34 #include <_debug.h> 35 #include <msg.h> 36 37 /* 38 * Define a debug descriptor. Note, although this provides the default 39 * definition to which most users bind, ld.so.1 must provide its own definition, 40 * and thus interposition is expected. This item should be defined NODIRECT. 41 */ 42 static Dbg_desc _dbg_desc = { 0, 0, 0 }; 43 Dbg_desc *dbg_desc = &_dbg_desc; 44 45 int _Dbg_cnt = 0; 46 47 /* 48 * Debugging initialization and processing. The dbg_options[] array defines 49 * a set of option strings that can be specified using the -D flag or from an 50 * environment variable. For each option, a class is enabled in the d_class 51 * bit mask, or an extra flag is enabled in the d_extra bit mask. 52 */ 53 DBG_options _Dbg_options[] = { 54 {MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL}, 55 {MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG}, 56 {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, 57 {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, 58 {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, 59 {MSG_ORIG(MSG_TOK_LMID), 0, DBG_E_LMID}, 60 61 {MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL, 0}, 62 {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, 63 {MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0}, 64 {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, 65 {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, 66 {MSG_ORIG(MSG_TOK_FILES), DBG_C_FILES, 0}, 67 {MSG_ORIG(MSG_TOK_HELP), DBG_C_HELP, 0}, 68 {MSG_ORIG(MSG_TOK_LIBS), DBG_C_LIBS, 0}, 69 {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, 70 {MSG_ORIG(MSG_TOK_RELOC), DBG_C_RELOC, 0}, 71 {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, 72 {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, 73 {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, 74 {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_C_SYMBOLS, 0}, 75 {MSG_ORIG(MSG_TOK_TLS), DBG_C_TLS, 0}, 76 {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, 77 {MSG_ORIG(MSG_TOK_VERSIONS), DBG_C_VERSIONS, 0}, 78 {MSG_ORIG(MSG_TOK_GOT), DBG_C_GOT, 0}, 79 {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, 80 {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, 81 {MSG_ORIG(MSG_TOK_STATS), DBG_C_STATS, 0}, 82 {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, 83 #ifdef DEMANGLE 84 {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, 85 #endif 86 {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, 87 {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, 88 {NULL, NULL}, 89 }; 90 91 /* 92 * Tokens may also define identifiers for diagnostics. Presently, only ld.so.1 93 * uses these strings to identify, or isolate its output to selected link-map 94 * lists. See ld.so.1:dbg_print(). 95 */ 96 const char *_Dbg_strs[] = { 97 MSG_ORIG(MSG_TOK_BASE), MSG_ORIG(MSG_TOK_LDSO), 98 MSG_ORIG(MSG_TOK_NEWLM), NULL 99 }; 100 101 /* 102 * Provide a debugging usage message 103 */ 104 void 105 Dbg_usage() 106 { 107 Dbg_util_nl(0, DBG_NL_FRC); 108 dbg_print(0, MSG_INTL(MSG_USE_RTLD_A)); 109 dbg_print(0, MSG_INTL(MSG_USE_RTLD_B)); 110 dbg_print(0, MSG_INTL(MSG_USE_RTLD_C)); 111 dbg_print(0, MSG_INTL(MSG_USE_RTLD_D)); 112 dbg_print(0, MSG_INTL(MSG_USE_RTLD_E)); 113 dbg_print(0, MSG_INTL(MSG_USE_RTLD_F)); 114 dbg_print(0, MSG_INTL(MSG_USE_RTLD_G)); 115 dbg_print(0, MSG_INTL(MSG_USE_RTLD_H)); 116 dbg_print(0, MSG_INTL(MSG_USE_RTLD_I)); 117 Dbg_util_nl(0, DBG_NL_FRC); 118 dbg_print(0, MSG_INTL(MSG_USE_RTLD_J)); 119 dbg_print(0, MSG_INTL(MSG_USE_RTLD_K)); 120 dbg_print(0, MSG_INTL(MSG_USE_RTLD_L)); 121 dbg_print(0, MSG_INTL(MSG_USE_RTLD_M)); 122 Dbg_util_nl(0, DBG_NL_FRC); 123 dbg_print(0, MSG_INTL(MSG_USE_RTLD_N)); 124 dbg_print(0, MSG_INTL(MSG_USE_RTLD_O)); 125 Dbg_util_nl(0, DBG_NL_FRC); 126 dbg_print(0, MSG_INTL(MSG_USE_RTLD_P)); 127 dbg_print(0, MSG_INTL(MSG_USE_RTLD_Q)); 128 dbg_print(0, MSG_INTL(MSG_USE_RTLD_R)); 129 dbg_print(0, MSG_INTL(MSG_USE_RTLD_S)); 130 131 Dbg_util_nl(0, DBG_NL_FRC); 132 dbg_print(0, MSG_INTL(MSG_USE_LD_A)); 133 dbg_print(0, MSG_INTL(MSG_USE_LD_B)); 134 dbg_print(0, MSG_INTL(MSG_USE_LD_C)); 135 dbg_print(0, MSG_INTL(MSG_USE_LD_D)); 136 dbg_print(0, MSG_INTL(MSG_USE_LD_E)); 137 dbg_print(0, MSG_INTL(MSG_USE_LD_F)); 138 dbg_print(0, MSG_INTL(MSG_USE_LD_G)); 139 dbg_print(0, MSG_INTL(MSG_USE_LD_H)); 140 Dbg_util_nl(0, DBG_NL_FRC); 141 dbg_print(0, MSG_INTL(MSG_USE_LD_I)); 142 Dbg_util_nl(0, DBG_NL_FRC); 143 dbg_print(0, MSG_INTL(MSG_USE_LD_J)); 144 dbg_print(0, MSG_INTL(MSG_USE_LD_K)); 145 Dbg_util_nl(0, DBG_NL_FRC); 146 dbg_print(0, MSG_INTL(MSG_USE_LD_L)); 147 Dbg_util_nl(0, DBG_NL_FRC); 148 dbg_print(0, MSG_INTL(MSG_USE_LD_M)); 149 dbg_print(0, MSG_INTL(MSG_USE_LD_N)); 150 dbg_print(0, MSG_INTL(MSG_USE_LD_O)); 151 152 Dbg_util_nl(0, DBG_NL_FRC); 153 Dbg_util_nl(0, DBG_NL_FRC); 154 dbg_print(0, MSG_INTL(MSG_USE_ARGS)); 155 dbg_print(0, MSG_INTL(MSG_USE_AUDIT)); 156 dbg_print(0, MSG_INTL(MSG_USE_BASIC)); 157 dbg_print(0, MSG_INTL(MSG_USE_BINDINGS)); 158 dbg_print(0, MSG_INTL(MSG_USE_BINDINGS_2)); 159 dbg_print(0, MSG_INTL(MSG_USE_CAP)); 160 dbg_print(0, MSG_INTL(MSG_USE_DETAIL)); 161 #ifdef DEMANGLE 162 dbg_print(0, MSG_INTL(MSG_USE_DEMANGLE)); 163 #endif 164 dbg_print(0, MSG_INTL(MSG_USE_ENTRY)); 165 dbg_print(0, MSG_INTL(MSG_USE_FILES)); 166 dbg_print(0, MSG_INTL(MSG_USE_GOT)); 167 dbg_print(0, MSG_INTL(MSG_USE_HELP)); 168 dbg_print(0, MSG_INTL(MSG_USE_INIT)); 169 dbg_print(0, MSG_INTL(MSG_USE_LIBS)); 170 dbg_print(0, MSG_INTL(MSG_USE_LIBS_2)); 171 dbg_print(0, MSG_INTL(MSG_USE_LMID)); 172 dbg_print(0, MSG_INTL(MSG_USE_LONG)); 173 dbg_print(0, MSG_INTL(MSG_USE_MAP)); 174 dbg_print(0, MSG_INTL(MSG_USE_MOVE)); 175 dbg_print(0, MSG_INTL(MSG_USE_RELOC)); 176 dbg_print(0, MSG_INTL(MSG_USE_SECTIONS)); 177 dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS)); 178 dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS_2)); 179 dbg_print(0, MSG_INTL(MSG_USE_STATS)); 180 dbg_print(0, MSG_INTL(MSG_USE_STRTAB)); 181 dbg_print(0, MSG_INTL(MSG_USE_STRTAB_2)); 182 dbg_print(0, MSG_INTL(MSG_USE_SUPPORT)); 183 dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS)); 184 dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS_2)); 185 dbg_print(0, MSG_INTL(MSG_USE_TLS)); 186 dbg_print(0, MSG_INTL(MSG_USE_UNUSED)); 187 dbg_print(0, MSG_INTL(MSG_USE_UNUSED_2)); 188 dbg_print(0, MSG_INTL(MSG_USE_VERSIONS)); 189 Dbg_util_nl(0, DBG_NL_FRC); 190 } 191 192 /* 193 * Messaging support - funnel everything through dgettext() as this provides 194 * the real binding to libc. 195 */ 196 const char * 197 _liblddbg_msg(Msg mid) 198 { 199 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 200 } 201 202 /* 203 * Validate and enable the appropriate debugging classes. 204 */ 205 uintptr_t 206 Dbg_setup(const char *string, Dbg_desc *dbp) 207 { 208 char *name, *_name; /* buffer in which to perform */ 209 /* strtok_r() operations. */ 210 char *lasts; 211 const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 212 213 if ((_name = (char *)malloc(strlen(string) + 1)) == 0) 214 return (S_ERROR); 215 (void) strcpy(_name, string); 216 217 /* 218 * The token should be of the form "-Dtok,tok,tok,...". Separate the 219 * pieces and build up the appropriate mask, unrecognized options are 220 * flagged. 221 */ 222 if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 223 do { 224 DBG_options *opt; 225 const char *str; 226 Boolean set, found = FALSE; 227 int ndx = 0; 228 229 if (name[0] == '!') { 230 set = FALSE; 231 name++; 232 } else 233 set = TRUE; 234 235 /* 236 * First, determine if the token represents a class or 237 * extra. 238 */ 239 for (opt = _Dbg_options; opt->o_name != NULL; opt++) { 240 if (strcmp(name, opt->o_name) != 0) 241 continue; 242 243 if (set == TRUE) { 244 if (opt->o_class) 245 dbp->d_class |= opt->o_class; 246 if (opt->o_extra) 247 dbp->d_extra |= opt->o_extra; 248 } else { 249 if (opt->o_class) 250 dbp->d_class &= ~(opt->o_class); 251 if (opt->o_extra) 252 dbp->d_extra &= ~(opt->o_extra); 253 } 254 found = TRUE; 255 break; 256 } 257 if (found == TRUE) 258 continue; 259 260 /* 261 * Second, determine if the token represents a known 262 * diagnostic identifier. Note, newlm identifiers are 263 * typically followed by a numeric id, for example 264 * newlm1, newlm2 ... Thus we only compare the 265 * initial text of the string. 266 */ 267 while ((str = _Dbg_strs[ndx++]) != NULL) { 268 char *tup; 269 270 if (strncmp(name, str, strlen(str)) != 0) 271 continue; 272 273 /* 274 * Translate lmid identifier to uppercase. 275 */ 276 for (tup = name; *tup; tup++) { 277 if ((*tup >= 'a') && (*tup <= 'z')) 278 *tup = *tup - ('a' - 'A'); 279 } 280 281 /* 282 * Save this lmid. The whole token buffer has 283 * been reallocated, so these names will remain 284 * once this routine returns. 285 */ 286 if (aplist_append(&dbp->d_list, name, 287 AL_CNT_DEBUG) == 0) 288 return (S_ERROR); 289 290 found = TRUE; 291 break; 292 } 293 294 if (found == FALSE) 295 dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); 296 297 } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 298 } 299 300 /* 301 * If the debug help option was specified dump a usage message. If 302 * this is the only debug class, return an indication that the user 303 * should exit. 304 */ 305 if ((_Dbg_cnt++ == 0) && (dbp->d_class & DBG_C_HELP)) { 306 Dbg_usage(); 307 if (dbp->d_class == DBG_C_HELP) 308 return (0); 309 } 310 return (1); 311 } 312 313 /* 314 * Define our own printing routine. This provides a basic fallback, as ld(1) 315 * and ld.so.1(1) provide their own routines that augment their diagnostic 316 * output, and direct the output to stderr. This item should be defined 317 * NODIRECT. 318 */ 319 /* PRINTFLIKE2 */ 320 void 321 dbg_print(Lm_list *lml, const char *format, ...) 322 { 323 va_list ap; 324 325 #if defined(lint) 326 /* 327 * The lml argument is only meaningful for diagnostics sent to ld.so.1. 328 * Supress the lint error by making a dummy assignment. 329 */ 330 lml = 0; 331 #endif 332 va_start(ap, format); 333 (void) vprintf(format, ap); 334 (void) printf(MSG_ORIG(MSG_STR_NL)); 335 va_end(ap); 336 } 337