xref: /titanic_44/usr/src/cmd/sgs/liblddbg/common/debug.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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