xref: /illumos-gate/usr/src/cmd/sgs/liblddbg/common/util.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 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	"msg.h"
29 #include	"_debug.h"
30 #include	"libld.h"
31 
32 /*
33  * If any run-time linker debugging is being carried out always indicate the
34  * fact and specify the point at which we transfer control to the main program.
35  */
36 void
37 Dbg_util_call_main(Rt_map *lmp)
38 {
39 	Lm_list	*lml = LIST(lmp);
40 
41 	Dbg_util_nl(lml, DBG_NL_FRC);
42 	dbg_print(lml, MSG_INTL(MSG_UTL_TRANS), NAME(lmp));
43 	Dbg_util_nl(lml, DBG_NL_FRC);
44 }
45 
46 void
47 Dbg_util_call_init(Rt_map *lmp, int flag)
48 {
49 	Lm_list		*lml = LIST(lmp);
50 	const char	*str;
51 
52 	if (DBG_NOTCLASS(DBG_C_INIT))
53 		return;
54 
55 	if (flag == DBG_INIT_SORT)
56 		str = MSG_INTL(MSG_UTL_SORT);
57 	else if (flag == DBG_INIT_PEND)
58 		str = MSG_INTL(MSG_UTL_PEND);
59 	else if (flag == DBG_INIT_DYN)
60 		str = MSG_INTL(MSG_UTL_DYN);
61 	else
62 		str = MSG_INTL(MSG_UTL_DONE);
63 
64 	Dbg_util_nl(lml, DBG_NL_STD);
65 	dbg_print(lml, MSG_INTL(MSG_UTL_INIT), str, NAME(lmp));
66 	Dbg_util_nl(lml, DBG_NL_STD);
67 }
68 
69 void
70 Dbg_util_no_init(Rt_map *lmp)
71 {
72 	Lm_list	*lml = LIST(lmp);
73 
74 	if (DBG_NOTCLASS(DBG_C_INIT))
75 		return;
76 
77 	Dbg_util_nl(lml, DBG_NL_STD);
78 	dbg_print(lml, MSG_INTL(MSG_UTL_NOINIT), NAME(lmp));
79 	Dbg_util_nl(lml, DBG_NL_STD);
80 }
81 
82 void
83 Dbg_util_intoolate(Rt_map *lmp)
84 {
85 	Lm_list	*lml = LIST(lmp);
86 
87 	Dbg_util_nl(lml, DBG_NL_STD);
88 	dbg_print(lml, MSG_INTL(MSG_UTL_INTOOLATE), NAME(lmp));
89 	Dbg_util_nl(lml, DBG_NL_STD);
90 }
91 
92 void
93 Dbg_util_dbnotify(Lm_list *lml, rd_event_e event, r_state_e state)
94 {
95 	const char	*estr;
96 	const char	*sstr;
97 
98 	if (DBG_NOTCLASS(DBG_C_FILES))
99 		return;
100 	if (DBG_NOTDETAIL())
101 		return;
102 
103 	switch (event) {
104 	case RD_PREINIT:
105 		estr = MSG_ORIG(MSG_UTL_EVNT_PREINIT);
106 		sstr = MSG_INTL(MSG_STR_NULL);
107 		break;
108 	case RD_POSTINIT:
109 		estr = MSG_ORIG(MSG_UTL_EVNT_POSTINIT);
110 		sstr = MSG_INTL(MSG_STR_NULL);
111 		break;
112 	case RD_DLACTIVITY:
113 		estr = MSG_ORIG(MSG_UTL_EVNT_DLACT);
114 		switch (state) {
115 		case RT_CONSISTENT:
116 			sstr = MSG_ORIG(MSG_UTL_STA_CONSIST);
117 			break;
118 		case RT_ADD:
119 			sstr = MSG_ORIG(MSG_UTL_STA_ADD);
120 			break;
121 		case RT_DELETE:
122 			sstr = MSG_ORIG(MSG_UTL_STA_DELETE);
123 			break;
124 		default:
125 			sstr = MSG_INTL(MSG_STR_NULL);
126 			break;
127 		}
128 		break;
129 	default:
130 		sstr = MSG_INTL(MSG_STR_NULL);
131 		estr = MSG_INTL(MSG_STR_UNKNOWN);
132 		break;
133 	}
134 
135 	Dbg_util_nl(lml, DBG_NL_STD);
136 	dbg_print(lml, MSG_INTL(MSG_UTL_DBNOTIFY), estr, sstr);
137 	Dbg_util_nl(lml, DBG_NL_STD);
138 }
139 
140 void
141 Dbg_util_call_array(Rt_map *lmp, void *addr, int ndx, Word shtype)
142 {
143 	Lm_list		*lml = LIST(lmp);
144 	const char	*str;
145 
146 	if (DBG_NOTCLASS(DBG_C_INIT))
147 		return;
148 
149 	if (shtype == SHT_INIT_ARRAY)
150 		str = MSG_ORIG(MSG_SCN_INITARRAY);
151 	else if (shtype == SHT_FINI_ARRAY)
152 		str = MSG_ORIG(MSG_SCN_FINIARRAY);
153 	else
154 		str = MSG_ORIG(MSG_SCN_PREINITARRAY);
155 
156 	dbg_print(lml, MSG_INTL(MSG_UTL_ARRAY), str, ndx, EC_NATPTR(addr),
157 	    NAME(lmp));
158 }
159 
160 void
161 Dbg_util_call_fini(Rt_map *lmp)
162 {
163 	Lm_list	*lml = LIST(lmp);
164 
165 	if (DBG_NOTCLASS(DBG_C_INIT))
166 		return;
167 
168 	Dbg_util_nl(lml, DBG_NL_STD);
169 	dbg_print(lml, MSG_INTL(MSG_UTL_FINI), NAME(lmp));
170 	Dbg_util_nl(lml, DBG_NL_STD);
171 }
172 
173 void
174 Dbg_util_str(Lm_list *lml, const char *str)
175 {
176 	Dbg_util_nl(lml, DBG_NL_STD);
177 	Dbg_util_nl(lml, DBG_NL_FRC);
178 	dbg_print(lml, MSG_ORIG(MSG_FMT_STR), str);
179 	Dbg_util_nl(lml, DBG_NL_FRC);
180 	Dbg_util_nl(lml, DBG_NL_STD);
181 }
182 
183 void
184 Dbg_util_scc_title(Lm_list *lml, int sec)
185 {
186 	const char	*_sec;
187 
188 	if (DBG_NOTCLASS(DBG_C_INIT))
189 		return;
190 	if (DBG_NOTDETAIL())
191 		return;
192 
193 	if (sec)
194 		_sec = MSG_INTL(MSG_UTL_SCC_SUBI);
195 	else
196 		_sec = MSG_INTL(MSG_UTL_SCC_SUBF);
197 
198 	Dbg_util_nl(lml, DBG_NL_STD);
199 	dbg_print(lml, MSG_INTL(MSG_UTL_SCC_TITLE), _sec);
200 }
201 
202 void
203 Dbg_util_scc_entry(Rt_map *lmp, uint_t idx)
204 {
205 	if (DBG_NOTCLASS(DBG_C_INIT))
206 		return;
207 	if (DBG_NOTDETAIL())
208 		return;
209 
210 	dbg_print(LIST(lmp), MSG_ORIG(MSG_UTL_SCC_ENTRY), idx, NAME(lmp));
211 }
212 
213 void
214 Dbg_util_broadcast(Rt_map *lmp)
215 {
216 	Lm_list	*lml = LIST(lmp);
217 
218 	if (DBG_NOTCLASS(DBG_C_INIT))
219 		return;
220 	if (DBG_NOTDETAIL())
221 		return;
222 
223 	Dbg_util_nl(lml, DBG_NL_STD);
224 	dbg_print(lml, MSG_INTL(MSG_UTL_BROAD), NAME(lmp));
225 	Dbg_util_nl(lml, DBG_NL_STD);
226 }
227 
228 void
229 Dbg_util_wait(Rt_map *clmp, Rt_map *dlmp, int what)
230 {
231 	Lm_list		*lml = LIST(clmp);
232 	const char	*str;
233 
234 	if (DBG_NOTCLASS(DBG_C_INIT))
235 		return;
236 	if (DBG_NOTDETAIL())
237 		return;
238 
239 	if (what == DBG_WAIT_INIT)
240 		str = MSG_ORIG(MSG_SCN_INIT);
241 	else if (what == DBG_WAIT_FINI)
242 		str = MSG_ORIG(MSG_SCN_FINI);
243 	else
244 		str = MSG_INTL(MSG_STR_SYMBOL);
245 
246 	Dbg_util_nl(lml, DBG_NL_STD);
247 	dbg_print(lml, MSG_INTL(MSG_UTL_WAIT), str, NAME(clmp), NAME(dlmp));
248 	Dbg_util_nl(lml, DBG_NL_STD);
249 }
250 
251 static	int ectoggle = 0;
252 
253 void
254 Dbg_util_edge_in(Lm_list *lml, Rt_map *clmp, uint_t flags, Rt_map *dlmp,
255     int ndx, int flag)
256 {
257 	Conv_bnd_type_buf_t	bnd_type_buf;
258 	const char		*str;
259 
260 	if (DBG_NOTCLASS(DBG_C_INIT))
261 		return;
262 	if (DBG_NOTDETAIL())
263 		return;
264 
265 	if (flag & RT_SORT_REV)
266 		str = MSG_ORIG(MSG_SCN_INIT);
267 	else
268 		str = MSG_ORIG(MSG_SCN_FINI);
269 
270 	if ((clmp == 0) || (ectoggle == 0))
271 		Dbg_util_nl(lml, DBG_NL_STD);
272 	if (clmp == 0) {
273 		if (flag & RT_SORT_INTPOSE)
274 			dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_I), str);
275 		else
276 			dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE_S), str);
277 
278 		dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_START), ndx, NAME(dlmp));
279 	} else
280 		dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_IN), ndx, NAME(dlmp),
281 		    NAME(clmp), conv_bnd_type(flags, &bnd_type_buf));
282 
283 	ectoggle = 1;
284 }
285 
286 void
287 Dbg_util_edge_out(Rt_map *clmp, Rt_map *dlmp)
288 {
289 	if (DBG_NOTCLASS(DBG_C_INIT))
290 		return;
291 	if (DBG_NOTDETAIL())
292 		return;
293 
294 	dbg_print(LIST(clmp), MSG_INTL(MSG_UTL_EDGE_OUT), SORTVAL(clmp),
295 	    NAME(clmp), NAME(dlmp));
296 }
297 
298 void
299 Dbg_util_collect(Rt_map *lmp, int ndx, int flag)
300 {
301 	Lm_list		*lml = LIST(lmp);
302 	const char	*str;
303 
304 	if (DBG_NOTCLASS(DBG_C_INIT))
305 		return;
306 	if (DBG_NOTDETAIL())
307 		return;
308 
309 	if (flag & RT_SORT_REV)
310 		str = MSG_ORIG(MSG_SCN_INIT);
311 	else
312 		str = MSG_ORIG(MSG_SCN_FINI);
313 
314 	if (ectoggle == 1) {
315 		Dbg_util_nl(lml, DBG_NL_STD);
316 		ectoggle = 0;
317 	}
318 	dbg_print(lml, MSG_INTL(MSG_UTL_COLLECT), ndx, NAME(lmp), str);
319 }
320 
321 static const Msg	tags[] = {
322 	MSG_CI_NULL,		/* MSG_ORIG(MSG_CI_NULL) */
323 	MSG_CI_VERSION,		/* MSG_ORIG(MSG_CI_VERSION) */
324 	MSG_CI_ATEXIT,		/* MSG_ORIG(MSG_CI_ATEXIT) */
325 	MSG_CI_LCMESSAGES,	/* MSG_ORIG(MSG_CI_LCMESSAGES) */
326 	MSG_CI_BIND_GUARD,	/* MSG_ORIG(MSG_CI_BIND_GUARD) */
327 	MSG_CI_BIND_CLEAR,	/* MSG_ORIG(MSG_CI_BIND_CLEAR) */
328 	MSG_CI_THR_SELF,	/* MSG_ORIG(MSG_CI_THR_SELF) */
329 	MSG_CI_TLS_MODADD,	/* MSG_ORIG(MSG_CI_TLS_MODADD) */
330 	MSG_CI_TLS_MODREM,	/* MSG_ORIG(MSG_CI_TLS_MODREM) */
331 	MSG_CI_TLS_STATMOD,	/* MSG_ORIG(MSG_CI_TLS_STATMOD) */
332 	MSG_CI_THRINIT		/* MSG_ORIG(MSG_CI_THRINIT) */
333 };
334 
335 void
336 Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val)
337 {
338 	const char	*str;
339 	Conv_inv_buf_t	inv_buf;
340 
341 	if (DBG_NOTDETAIL())
342 		return;
343 
344 	if (tag < CI_MAX)
345 		str = MSG_ORIG(tags[tag]);
346 	else
347 		str = conv_invalid_val(&inv_buf, tag, 0);
348 
349 	dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str,
350 	    EC_NATPTR(val));
351 }
352 
353 void
354 Dbg_unused_lcinterface(Rt_map *nlmp, Rt_map *olmp, int tag)
355 {
356 	const char	*str;
357 	Conv_inv_buf_t	inv_buf;
358 
359 	if (DBG_NOTCLASS(DBG_C_UNUSED))
360 		return;
361 
362 	if (tag < CI_MAX)
363 		str = MSG_ORIG(tags[tag]);
364 	else
365 		str = conv_invalid_val(&inv_buf, tag, 0);
366 
367 	dbg_print(LIST(nlmp), MSG_INTL(MSG_USD_LCINTERFACE), NAME(nlmp), str,
368 	    NAME(olmp));
369 }
370 
371 /*
372  * Generic new line generator.  To prevent multiple newlines from being
373  * generated, a flag is maintained in the global debug descriptor.  This flag
374  * is cleared by the callers dbg_print() function to indicate that a newline
375  * (actually, any line) has been printed.  Multiple newlines can be generated
376  * using the DBG_NL_FRC flag.
377  */
378 void
379 Dbg_util_nl(Lm_list *lml, int flag)
380 {
381 	if ((flag == DBG_NL_STD) && (dbg_desc->d_extra & DBG_E_STDNL))
382 		return;
383 
384 	dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
385 
386 	if (flag == DBG_NL_STD)
387 		dbg_desc->d_extra |= DBG_E_STDNL;
388 }
389 
390 /*
391  * Define name demanglers.
392  */
393 const char *
394 Dbg_demangle_name(const char *name)
395 {
396 	if (DBG_NOTCLASS(DBG_C_DEMANGLE))
397 		return (name);
398 
399 	return (conv_demangle_name(name));
400 }
401 
402 const char *
403 Elf_demangle_name(const char *name)
404 {
405 	if (DBG_ISDEMANGLE())
406 		return (conv_demangle_name(name));
407 	return (name);
408 }
409