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