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