debug.c revision 5892:b863dde33f1b
1107120Sjulian/* 2107120Sjulian * CDDL HEADER START 3139823Simp * 4139823Simp * The contents of this file are subject to the terms of the 5139823Simp * Common Development and Distribution License (the "License"). 6107120Sjulian * You may not use this file except in compliance with the License. 7107120Sjulian * 8107120Sjulian * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9107120Sjulian * or http://www.opensolaris.org/os/licensing. 10107120Sjulian * See the License for the specific language governing permissions 11107120Sjulian * and limitations under the License. 12107120Sjulian * 13107120Sjulian * When distributing Covered Code, include this CDDL HEADER in each 14107120Sjulian * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15107120Sjulian * If applicable, add the following below this CDDL HEADER, with the 16107120Sjulian * fields enclosed by brackets "[]" replaced with your own identifying 17107120Sjulian * information: Portions Copyright [yyyy] [name of copyright owner] 18107120Sjulian * 19107120Sjulian * CDDL HEADER END 20107120Sjulian */ 21107120Sjulian 22107120Sjulian/* 23107120Sjulian * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24107120Sjulian * Use is subject to license terms. 25107120Sjulian */ 26107120Sjulian#pragma ident "%Z%%M% %I% %E% SMI" 27107120Sjulian 28107120Sjulian#define dgettext _dgettext 29107120Sjulian 30114878Sjulian#include <libintl.h> 31107120Sjulian#include <sys/varargs.h> 32107120Sjulian#include <stdio.h> 33107120Sjulian#include <string.h> 34107120Sjulian#include <stdlib.h> 35122634Semax#include <alist.h> 36107120Sjulian#include <debug.h> 37107120Sjulian#include <_debug.h> 38107120Sjulian#include <msg.h> 39107120Sjulian 40107120Sjulian/* 41107120Sjulian * Define a debug descriptor. Note, although this provides the default 42107120Sjulian * definition to which most users bind, ld.so.1 must provide its own definition, 43107120Sjulian * and thus interposition is expected. This item should be defined NODIRECT. 44107120Sjulian */ 45107120Sjulianstatic Dbg_desc _dbg_desc = { 0, 0, 0 }; 46107120SjulianDbg_desc *dbg_desc = &_dbg_desc; 47107120Sjulian 48int _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 */ 56DBG_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 */ 99const 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 */ 107void 108Dbg_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 */ 199const 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 */ 208uintptr_t 209Dbg_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 */ 323void 324dbg_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