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 2004 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 {NULL, NULL}, 78 }; 79 80 /* 81 * Provide a debugging usage message 82 */ 83 static void 84 _Dbg_usage() 85 { 86 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 87 dbg_print(MSG_INTL(MSG_USE_RTLD_A)); 88 dbg_print(MSG_INTL(MSG_USE_RTLD_B)); 89 dbg_print(MSG_INTL(MSG_USE_RTLD_C)); 90 dbg_print(MSG_INTL(MSG_USE_RTLD_D)); 91 dbg_print(MSG_INTL(MSG_USE_RTLD_E)); 92 dbg_print(MSG_INTL(MSG_USE_RTLD_F)); 93 dbg_print(MSG_INTL(MSG_USE_RTLD_G)); 94 95 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 96 dbg_print(MSG_INTL(MSG_USE_LD_A)); 97 dbg_print(MSG_INTL(MSG_USE_LD_B)); 98 dbg_print(MSG_INTL(MSG_USE_LD_C)); 99 dbg_print(MSG_INTL(MSG_USE_LD_D)); 100 dbg_print(MSG_INTL(MSG_USE_LD_E)); 101 dbg_print(MSG_INTL(MSG_USE_LD_F)); 102 dbg_print(MSG_INTL(MSG_USE_LD_G)); 103 dbg_print(MSG_INTL(MSG_USE_LD_H)); 104 dbg_print(MSG_INTL(MSG_USE_LD_I)); 105 dbg_print(MSG_INTL(MSG_USE_LD_J)); 106 107 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 108 dbg_print(MSG_ORIG(MSG_STR_EMPTY)); 109 dbg_print(MSG_INTL(MSG_USE_ARGS)); 110 dbg_print(MSG_INTL(MSG_USE_AUDIT)); 111 dbg_print(MSG_INTL(MSG_USE_BASIC)); 112 dbg_print(MSG_INTL(MSG_USE_BINDINGS)); 113 dbg_print(MSG_INTL(MSG_USE_BINDINGS_2)); 114 dbg_print(MSG_INTL(MSG_USE_CAP)); 115 dbg_print(MSG_INTL(MSG_USE_DETAIL)); 116 #ifdef DEMANGLE 117 dbg_print(MSG_INTL(MSG_USE_DEMANGLE)); 118 #endif 119 dbg_print(MSG_INTL(MSG_USE_ENTRY)); 120 dbg_print(MSG_INTL(MSG_USE_FILES)); 121 dbg_print(MSG_INTL(MSG_USE_GOT)); 122 dbg_print(MSG_INTL(MSG_USE_HELP)); 123 dbg_print(MSG_INTL(MSG_USE_LIBS)); 124 dbg_print(MSG_INTL(MSG_USE_LIBS_2)); 125 dbg_print(MSG_INTL(MSG_USE_LONG)); 126 dbg_print(MSG_INTL(MSG_USE_MAP)); 127 dbg_print(MSG_INTL(MSG_USE_MOVE)); 128 dbg_print(MSG_INTL(MSG_USE_RELOC)); 129 dbg_print(MSG_INTL(MSG_USE_SECTIONS)); 130 dbg_print(MSG_INTL(MSG_USE_SEGMENTS)); 131 dbg_print(MSG_INTL(MSG_USE_SEGMENTS_2)); 132 dbg_print(MSG_INTL(MSG_USE_STATISTICS)); 133 dbg_print(MSG_INTL(MSG_USE_STRTAB)); 134 dbg_print(MSG_INTL(MSG_USE_STRTAB_2)); 135 dbg_print(MSG_INTL(MSG_USE_SUPPORT)); 136 dbg_print(MSG_INTL(MSG_USE_SYMBOLS)); 137 dbg_print(MSG_INTL(MSG_USE_SYMBOLS_2)); 138 dbg_print(MSG_INTL(MSG_USE_TLS)); 139 dbg_print(MSG_INTL(MSG_USE_UNUSED)); 140 dbg_print(MSG_INTL(MSG_USE_UNUSED_2)); 141 dbg_print(MSG_INTL(MSG_USE_VERSIONS)); 142 } 143 144 /* 145 * Validate and enable the appropriate debugging classes. 146 */ 147 uint_t 148 Dbg_setup(const char *string) 149 { 150 char *name, *_name; /* Temporary buffer in which to */ 151 /* perform strtok_r() operations. */ 152 char *lasts; 153 DBG_opts opts; /* Ptr to cycle thru _Dbg_options[]. */ 154 const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 155 156 if ((_name = (char *)malloc(strlen(string) + 1)) == 0) 157 return (0); 158 (void) strcpy(_name, string); 159 160 /* 161 * The token should be of the form "-Dtok,tok,tok,...". Separate the 162 * pieces and build up the appropriate mask, unrecognized options are 163 * flagged. 164 */ 165 if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 166 Boolean found, set; 167 do { 168 found = FALSE; 169 set = TRUE; 170 if (name[0] == '!') { 171 set = FALSE; 172 name++; 173 } 174 for (opts = _Dbg_options; opts->o_name != NULL; 175 opts++) { 176 if (strcmp(name, opts->o_name) == 0) { 177 if (set == TRUE) 178 _Dbg_mask |= opts->o_mask; 179 else 180 _Dbg_mask &= ~(opts->o_mask); 181 found = TRUE; 182 break; 183 } 184 } 185 if (found == FALSE) 186 dbg_print(MSG_INTL(MSG_USE_UNRECOG), name); 187 } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 188 } 189 (void) free(_name); 190 191 /* 192 * If the debug help option was specified dump a usage message. If 193 * this is the only debug option return an indication that the user 194 * should exit. 195 */ 196 if ((_Dbg_mask & DBG_HELP) && !_Dbg_count) { 197 _Dbg_usage(); 198 if (_Dbg_mask == DBG_HELP) 199 /* LINTED */ 200 return ((uint_t)S_ERROR); 201 } 202 203 _Dbg_count++; 204 205 return (_Dbg_mask); 206 } 207 208 /* 209 * Set the specified flags to _Dbg_mask. 210 */ 211 void 212 Dbg_set(uint_t flags) 213 { 214 _Dbg_mask = flags; 215 } 216 217 218 /* 219 * Messaging support - funnel everything through _dgettext() as this provides 220 * a stub binding to libc, or a real binding to libintl. 221 */ 222 extern char *_dgettext(const char *, const char *); 223 224 const char * 225 _liblddbg_msg(Msg mid) 226 { 227 return (_dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 228 } 229