xref: /illumos-gate/usr/src/cmd/sgs/liblddbg/common/util.c (revision 0173c38a73f34277e0c97a19fedfd25d81ba8380)
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 2006 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 	const char	*str;
258 
259 	if (DBG_NOTCLASS(DBG_C_INIT))
260 		return;
261 	if (DBG_NOTDETAIL())
262 		return;
263 
264 	if (flag & RT_SORT_REV)
265 		str = MSG_ORIG(MSG_SCN_INIT);
266 	else
267 		str = MSG_ORIG(MSG_SCN_FINI);
268 
269 	if ((clmp == 0) || (ectoggle == 0))
270 		Dbg_util_nl(lml, DBG_NL_STD);
271 	if (clmp == 0) {
272 		dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_TITLE), str);
273 		dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_START), ndx, NAME(dlmp));
274 	} else
275 		dbg_print(lml, MSG_INTL(MSG_UTL_EDGE_IN), ndx, NAME(dlmp),
276 		    NAME(clmp), conv_bnd_type(flags));
277 
278 	ectoggle = 1;
279 }
280 
281 void
282 Dbg_util_edge_out(Rt_map *clmp, Rt_map *dlmp)
283 {
284 	if (DBG_NOTCLASS(DBG_C_INIT))
285 		return;
286 	if (DBG_NOTDETAIL())
287 		return;
288 
289 	dbg_print(LIST(clmp), MSG_INTL(MSG_UTL_EDGE_OUT), SORTVAL(clmp),
290 	    NAME(clmp), NAME(dlmp));
291 }
292 
293 void
294 Dbg_util_collect(Rt_map *lmp, int ndx, int flag)
295 {
296 	Lm_list		*lml = LIST(lmp);
297 	const char	*str;
298 
299 	if (DBG_NOTCLASS(DBG_C_INIT))
300 		return;
301 	if (DBG_NOTDETAIL())
302 		return;
303 
304 	if (flag & RT_SORT_REV)
305 		str = MSG_ORIG(MSG_SCN_INIT);
306 	else
307 		str = MSG_ORIG(MSG_SCN_FINI);
308 
309 	if (ectoggle == 1) {
310 		Dbg_util_nl(lml, DBG_NL_STD);
311 		ectoggle = 0;
312 	}
313 	dbg_print(lml, MSG_INTL(MSG_UTL_COLLECT), ndx, NAME(lmp), str);
314 }
315 
316 static const Msg	tags[] = {
317 	MSG_CI_NULL,		/* MSG_ORIG(MSG_CI_NULL) */
318 	MSG_CI_VERSION,		/* MSG_ORIG(MSG_CI_VERSION) */
319 	MSG_CI_ATEXIT,		/* MSG_ORIG(MSG_CI_ATEXIT) */
320 	MSG_CI_LCMESSAGES,	/* MSG_ORIG(MSG_CI_LCMESSAGES) */
321 	MSG_CI_BIND_GUARD,	/* MSG_ORIG(MSG_CI_BIND_GUARD) */
322 	MSG_CI_BIND_CLEAR,	/* MSG_ORIG(MSG_CI_BIND_CLEAR) */
323 	MSG_CI_THR_SELF,	/* MSG_ORIG(MSG_CI_THR_SELF) */
324 	MSG_CI_TLS_MODADD,	/* MSG_ORIG(MSG_CI_TLS_MODADD) */
325 	MSG_CI_TLS_MODREM,	/* MSG_ORIG(MSG_CI_TLS_MODREM) */
326 	MSG_CI_TLS_STATMOD,	/* MSG_ORIG(MSG_CI_TLS_STATMOD) */
327 	MSG_CI_THRINIT		/* MSG_ORIG(MSG_CI_THRINIT) */
328 };
329 
330 void
331 Dbg_util_lcinterface(Rt_map *lmp, int tag, char *val)
332 {
333 	const char	*str;
334 	static char	string[CONV_INV_STRSIZE];
335 
336 	if (DBG_NOTDETAIL())
337 		return;
338 
339 	if (tag < CI_MAX)
340 		str = MSG_ORIG(tags[tag]);
341 	else
342 		str = conv_invalid_val(string, CONV_INV_STRSIZE, tag, 0);
343 
344 	dbg_print(LIST(lmp), MSG_INTL(MSG_UTL_LCINTERFACE), NAME(lmp), str,
345 	    EC_NATPTR(val));
346 }
347 
348 void
349 Dbg_unused_lcinterface(Rt_map *nlmp, Rt_map *olmp, int tag)
350 {
351 	const char	*str;
352 	static char	string[CONV_INV_STRSIZE];
353 
354 	if (DBG_NOTCLASS(DBG_C_UNUSED))
355 		return;
356 
357 	if (tag < CI_MAX)
358 		str = MSG_ORIG(tags[tag]);
359 	else
360 		str = conv_invalid_val(string, CONV_INV_STRSIZE, tag, 0);
361 
362 	dbg_print(LIST(nlmp), MSG_INTL(MSG_USD_LCINTERFACE), NAME(nlmp), str,
363 	    NAME(olmp));
364 }
365 
366 /*
367  * Generic new line generator.  To prevent multiple newlines from being
368  * generated, a flag is maintained in the global debug descriptor.  This flag
369  * is cleared by the callers dbg_print() function to indicate that a newline
370  * (actually, any line) has been printed.  Multiple newlines can be generated
371  * using the DBG_NL_FRC flag.
372  */
373 void
374 Dbg_util_nl(Lm_list *lml, int flag)
375 {
376 	if ((flag == DBG_NL_STD) && (dbg_desc->d_extra & DBG_E_STDNL))
377 		return;
378 
379 	dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
380 
381 	if (flag == DBG_NL_STD)
382 		dbg_desc->d_extra |= DBG_E_STDNL;
383 }
384 
385 /*
386  * Define name demanglers.
387  */
388 const char *
389 Dbg_demangle_name(const char *name)
390 {
391 	if (DBG_NOTCLASS(DBG_C_DEMANGLE))
392 		return (name);
393 
394 	return (conv_demangle_name(name));
395 }
396 
397 const char *
398 Elf_demangle_name(const char *name)
399 {
400 	if (DBG_ISDEMANGLE())
401 		return (conv_demangle_name(name));
402 	return (name);
403 }
404