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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <string.h> 30 #include <stdlib.h> 31 #include "_debug.h" 32 #include "msg.h" 33 34 uint_t _Dbg_mask; 35 static int _Dbg_count = 0; 36 37 38 /* 39 * Debugging initialization and processing. The options structure defines 40 * a set of option strings that can be specified using the -D flag or from an 41 * environment variable. For each option, a class is enabled in the _Dbg_mask 42 * bit mask. 43 */ 44 static DBG_options _Dbg_options[] = { 45 {MSG_ORIG(MSG_TOK_NAME), DBG_G_SNAME}, 46 {MSG_ORIG(MSG_TOK_FULLNAME), DBG_G_SNAME | DBG_G_FNAME}, 47 {MSG_ORIG(MSG_TOK_CLASS), DBG_G_SNAME | DBG_G_CLASS}, 48 49 {MSG_ORIG(MSG_TOK_ALL), DBG_LOCAL}, 50 {MSG_ORIG(MSG_TOK_ARGS), DBG_ARGS}, 51 {MSG_ORIG(MSG_TOK_BASIC), DBG_BASIC}, 52 {MSG_ORIG(MSG_TOK_BINDINGS), DBG_BINDINGS}, 53 {MSG_ORIG(MSG_TOK_DETAIL), DBG_DETAIL}, 54 {MSG_ORIG(MSG_TOK_ENTRY), DBG_ENTRY}, 55 {MSG_ORIG(MSG_TOK_FILES), DBG_FILES}, 56 {MSG_ORIG(MSG_TOK_HELP), DBG_HELP}, 57 {MSG_ORIG(MSG_TOK_LIBS), DBG_LIBS}, 58 {MSG_ORIG(MSG_TOK_LONG), DBG_LONG}, 59 {MSG_ORIG(MSG_TOK_MAP), DBG_MAP}, 60 {MSG_ORIG(MSG_TOK_RELOC), DBG_RELOC}, 61 {MSG_ORIG(MSG_TOK_SECTIONS), DBG_SECTIONS}, 62 {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_SEGMENTS}, 63 {MSG_ORIG(MSG_TOK_SUPPORT), DBG_SUPPORT}, 64 {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_SYMBOLS}, 65 {MSG_ORIG(MSG_TOK_TLS), DBG_TLS}, 66 {MSG_ORIG(MSG_TOK_AUDIT), DBG_AUDITING}, 67 {MSG_ORIG(MSG_TOK_VERSIONS), DBG_VERSIONS}, 68 {MSG_ORIG(MSG_TOK_GOT), DBG_GOT}, 69 {MSG_ORIG(MSG_TOK_MOVE), DBG_MOVE}, 70 {MSG_ORIG(MSG_TOK_STRTAB), DBG_STRTAB}, 71 {MSG_ORIG(MSG_TOK_STATISTICS), DBG_STATISTICS}, 72 {MSG_ORIG(MSG_TOK_UNUSED), DBG_UNUSED}, 73 #ifdef DEMANGLE 74 {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_DEMANGLE}, 75 #endif 76 {MSG_ORIG(MSG_TOK_CAP), DBG_CAP}, 77 {MSG_ORIG(MSG_TOK_INIT), DBG_INIT}, 78 {NULL, NULL}, 79 }; 80 81 /* 82 * Provide a debugging usage message 83 */ 84 static void 85 _Dbg_usage() 86 { 87 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 88 dbg_print(MSG_INTL(MSG_USE_RTLD_A)); 89 dbg_print(MSG_INTL(MSG_USE_RTLD_B)); 90 dbg_print(MSG_INTL(MSG_USE_RTLD_C)); 91 dbg_print(MSG_INTL(MSG_USE_RTLD_D)); 92 dbg_print(MSG_INTL(MSG_USE_RTLD_E)); 93 dbg_print(MSG_INTL(MSG_USE_RTLD_F)); 94 dbg_print(MSG_INTL(MSG_USE_RTLD_G)); 95 96 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 97 dbg_print(MSG_INTL(MSG_USE_LD_A)); 98 dbg_print(MSG_INTL(MSG_USE_LD_B)); 99 dbg_print(MSG_INTL(MSG_USE_LD_C)); 100 dbg_print(MSG_INTL(MSG_USE_LD_D)); 101 dbg_print(MSG_INTL(MSG_USE_LD_E)); 102 dbg_print(MSG_INTL(MSG_USE_LD_F)); 103 dbg_print(MSG_INTL(MSG_USE_LD_G)); 104 dbg_print(MSG_INTL(MSG_USE_LD_H)); 105 dbg_print(MSG_INTL(MSG_USE_LD_I)); 106 dbg_print(MSG_INTL(MSG_USE_LD_J)); 107 108 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 109 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 110 dbg_print(MSG_INTL(MSG_USE_ARGS)); 111 dbg_print(MSG_INTL(MSG_USE_AUDIT)); 112 dbg_print(MSG_INTL(MSG_USE_BASIC)); 113 dbg_print(MSG_INTL(MSG_USE_BINDINGS)); 114 dbg_print(MSG_INTL(MSG_USE_BINDINGS_2)); 115 dbg_print(MSG_INTL(MSG_USE_CAP)); 116 dbg_print(MSG_INTL(MSG_USE_DETAIL)); 117 #ifdef DEMANGLE 118 dbg_print(MSG_INTL(MSG_USE_DEMANGLE)); 119 #endif 120 dbg_print(MSG_INTL(MSG_USE_ENTRY)); 121 dbg_print(MSG_INTL(MSG_USE_FILES)); 122 dbg_print(MSG_INTL(MSG_USE_GOT)); 123 dbg_print(MSG_INTL(MSG_USE_HELP)); 124 dbg_print(MSG_INTL(MSG_USE_INIT)); 125 dbg_print(MSG_INTL(MSG_USE_LIBS)); 126 dbg_print(MSG_INTL(MSG_USE_LIBS_2)); 127 dbg_print(MSG_INTL(MSG_USE_LONG)); 128 dbg_print(MSG_INTL(MSG_USE_MAP)); 129 dbg_print(MSG_INTL(MSG_USE_MOVE)); 130 dbg_print(MSG_INTL(MSG_USE_RELOC)); 131 dbg_print(MSG_INTL(MSG_USE_SECTIONS)); 132 dbg_print(MSG_INTL(MSG_USE_SEGMENTS)); 133 dbg_print(MSG_INTL(MSG_USE_SEGMENTS_2)); 134 dbg_print(MSG_INTL(MSG_USE_STATISTICS)); 135 dbg_print(MSG_INTL(MSG_USE_STRTAB)); 136 dbg_print(MSG_INTL(MSG_USE_STRTAB_2)); 137 dbg_print(MSG_INTL(MSG_USE_SUPPORT)); 138 dbg_print(MSG_INTL(MSG_USE_SYMBOLS)); 139 dbg_print(MSG_INTL(MSG_USE_SYMBOLS_2)); 140 dbg_print(MSG_INTL(MSG_USE_TLS)); 141 dbg_print(MSG_INTL(MSG_USE_UNUSED)); 142 dbg_print(MSG_INTL(MSG_USE_UNUSED_2)); 143 dbg_print(MSG_INTL(MSG_USE_VERSIONS)); 144 } 145 146 /* 147 * Validate and enable the appropriate debugging classes. 148 */ 149 uint_t 150 Dbg_setup(const char *string) 151 { 152 char *name, *_name; /* Temporary buffer in which to */ 153 /* perform strtok_r() operations. */ 154 char *lasts; 155 DBG_opts opts; /* Ptr to cycle thru _Dbg_options[]. */ 156 const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 157 158 if ((_name = (char *)malloc(strlen(string) + 1)) == 0) 159 return (0); 160 (void) strcpy(_name, string); 161 162 /* 163 * The token should be of the form "-Dtok,tok,tok,...". Separate the 164 * pieces and build up the appropriate mask, unrecognized options are 165 * flagged. 166 */ 167 if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 168 Boolean found, set; 169 do { 170 found = FALSE; 171 set = TRUE; 172 if (name[0] == '!') { 173 set = FALSE; 174 name++; 175 } 176 for (opts = _Dbg_options; opts->o_name != NULL; 177 opts++) { 178 if (strcmp(name, opts->o_name) == 0) { 179 if (set == TRUE) 180 _Dbg_mask |= opts->o_mask; 181 else 182 _Dbg_mask &= ~(opts->o_mask); 183 found = TRUE; 184 break; 185 } 186 } 187 if (found == FALSE) 188 dbg_print(MSG_INTL(MSG_USE_UNRECOG), name); 189 } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 190 } 191 (void) free(_name); 192 193 /* 194 * If the debug help option was specified dump a usage message. If 195 * this is the only debug option return an indication that the user 196 * should exit. 197 */ 198 if ((_Dbg_mask & DBG_HELP) && !_Dbg_count) { 199 _Dbg_usage(); 200 if (_Dbg_mask == DBG_HELP) 201 /* LINTED */ 202 return ((uint_t)S_ERROR); 203 } 204 205 _Dbg_count++; 206 207 return (_Dbg_mask); 208 } 209 210 /* 211 * Set the specified flags to _Dbg_mask. 212 */ 213 void 214 Dbg_set(uint_t flags) 215 { 216 _Dbg_mask = flags; 217 } 218 219 220 /* 221 * Messaging support - funnel everything through _dgettext() as this provides 222 * a stub binding to libc, or a real binding to libintl. 223 */ 224 extern char *_dgettext(const char *, const char *); 225 226 const char * 227 _liblddbg_msg(Msg mid) 228 { 229 return (_dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 230 } 231