xref: /illumos-gate/usr/src/cmd/sgs/liblddbg/common/files.c (revision 45526e9775395f5d44bad3f5430041f32c84ce1e)
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	"_synonyms.h"
29 
30 #include	<sys/auxv.h>
31 #include	<string.h>
32 #include	<unistd.h>
33 #include	<fcntl.h>
34 #include	<limits.h>
35 #include	<stdio.h>
36 #include	"msg.h"
37 #include	"_debug.h"
38 #include	"libld.h"
39 
40 
41 void
42 Dbg_file_generic(Ifl_desc *ifl)
43 {
44 	if (DBG_NOTCLASS(DBG_FILES))
45 		return;
46 
47 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
48 	dbg_print(MSG_INTL(MSG_FIL_BASIC), ifl->ifl_name,
49 		conv_etype_str(ifl->ifl_ehdr->e_type));
50 }
51 
52 void
53 Dbg_file_skip(const char *nname, const char *oname)
54 {
55 	if (DBG_NOTCLASS(DBG_FILES))
56 		return;
57 
58 	if (oname && strcmp(nname, oname))
59 		dbg_print(MSG_INTL(MSG_FIL_SKIP_1), nname, oname);
60 	else
61 		dbg_print(MSG_INTL(MSG_FIL_SKIP_2), nname);
62 }
63 
64 void
65 Dbg_file_reuse(const char *nname, const char *oname)
66 {
67 	if (DBG_NOTCLASS(DBG_FILES))
68 		return;
69 
70 	dbg_print(MSG_INTL(MSG_FIL_REUSE), nname, oname);
71 }
72 
73 void
74 Dbg_file_archive(const char *name, int again)
75 {
76 	const char	*str;
77 
78 	if (DBG_NOTCLASS(DBG_FILES))
79 		return;
80 
81 	if (again)
82 		str = MSG_INTL(MSG_STR_AGAIN);
83 	else
84 		str = MSG_ORIG(MSG_STR_EMPTY);
85 
86 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
87 	dbg_print(MSG_INTL(MSG_FIL_ARCHIVE), name, str);
88 }
89 
90 void
91 Dbg_file_analyze(Rt_map * lmp)
92 {
93 	if (DBG_NOTCLASS(DBG_FILES))
94 		return;
95 
96 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
97 	dbg_print(MSG_INTL(MSG_FIL_ANALYZE), NAME(lmp),
98 	    conv_dlmode_str(MODE(lmp), 1));
99 }
100 
101 void
102 Dbg_file_aout(const char *name, ulong_t dynamic, ulong_t base, ulong_t size)
103 {
104 	if (DBG_NOTCLASS(DBG_FILES))
105 		return;
106 
107 	dbg_print(MSG_INTL(MSG_FIL_AOUT), name);
108 	dbg_print(MSG_INTL(MSG_FIL_DATA_1), EC_XWORD(dynamic),
109 	    EC_ADDR(base), EC_XWORD(size));
110 }
111 
112 void
113 Dbg_file_elf(const char *name, ulong_t dynamic, ulong_t base,
114     ulong_t size, ulong_t entry, Lmid_t lmid, Aliste lmco)
115 {
116 	const char	*str;
117 
118 	if (DBG_NOTCLASS(DBG_FILES))
119 		return;
120 
121 	if (base == 0)
122 		str = MSG_INTL(MSG_STR_TEMPORARY);
123 	else
124 		str = MSG_ORIG(MSG_STR_EMPTY);
125 
126 	dbg_print(MSG_INTL(MSG_FIL_ELF), name, str);
127 	dbg_print(MSG_INTL(MSG_FIL_DATA_1), EC_XWORD(dynamic),
128 	    EC_ADDR(base), EC_XWORD(size));
129 	dbg_print(MSG_INTL(MSG_FIL_DATA_2), EC_XWORD(entry),
130 	    EC_XWORD(lmid), EC_XWORD(lmco));
131 }
132 
133 void
134 Dbg_file_ldso(const char *name, ulong_t dynamic, ulong_t base, char **envp,
135     auxv_t *auxv)
136 {
137 	if (DBG_NOTCLASS(DBG_FILES))
138 		return;
139 
140 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
141 	dbg_print(MSG_INTL(MSG_FIL_LDSO), name);
142 	dbg_print(MSG_INTL(MSG_FIL_DATA_3), EC_XWORD(dynamic),
143 	    EC_ADDR(base));
144 	dbg_print(MSG_INTL(MSG_FIL_DATA_4), EC_ADDR(envp), EC_ADDR(auxv));
145 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
146 }
147 
148 void
149 Dbg_file_prot(const char *name, int prot)
150 {
151 	if (DBG_NOTCLASS(DBG_FILES))
152 		return;
153 
154 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
155 	dbg_print(MSG_INTL(MSG_FIL_PROT), name, (prot ? '+' : '-'));
156 }
157 
158 void
159 Dbg_file_delete(const char *name)
160 {
161 	if (DBG_NOTCLASS(DBG_FILES))
162 		return;
163 
164 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
165 	dbg_print(MSG_INTL(MSG_FIL_DELETE), name);
166 }
167 
168 static int	hdl_title = 0;
169 static Msg	hdl_str = 0;
170 
171 void
172 Dbg_file_hdl_title(int type)
173 {
174 	if (DBG_NOTCLASS(DBG_FILES))
175 		return;
176 	if (DBG_NOTDETAIL())
177 		return;
178 
179 	hdl_title = 1;
180 
181 	/*
182 	 * Establish a binding title for later use in Dbg_file_bind_entry.
183 	 */
184 	if (type == DBG_DEP_CREATE)
185 	    hdl_str = MSG_FIL_HDL_CREATE;  /* MSG_INTL(MSG_FIL_HDL_CREATE) */
186 	else if (type == DBG_DEP_ADD)
187 	    hdl_str = MSG_FIL_HDL_ADD;	   /* MSG_INTL(MSG_FIL_HDL_ADD) */
188 	else if (type == DBG_DEP_DELETE)
189 	    hdl_str = MSG_FIL_HDL_DELETE;  /* MSG_INTL(MSG_FIL_HDL_DELETE) */
190 	else if (type == DBG_DEP_ORPHAN)
191 	    hdl_str = MSG_FIL_HDL_ORPHAN;  /* MSG_INTL(MSG_FIL_HDL_ORPHAN) */
192 	else if (type == DBG_DEP_REINST)
193 	    hdl_str = MSG_FIL_HDL_REINST;  /* MSG_INTL(MSG_FIL_HDL_REINST) */
194 	else
195 	    hdl_str = 0;
196 }
197 
198 void
199 Dbg_file_hdl_collect(Grp_hdl * ghp, const char *name)
200 {
201 	const char *str;
202 
203 	if (DBG_NOTCLASS(DBG_FILES))
204 		return;
205 	if (DBG_NOTDETAIL())
206 		return;
207 
208 	if (ghp->gh_owner)
209 		str = NAME(ghp->gh_owner);
210 	else
211 		str = MSG_INTL(MSG_STR_ORPHAN);
212 
213 	if (hdl_title) {
214 		hdl_title = 0;
215 		dbg_print(MSG_ORIG(MSG_STR_EMPTY));
216 	}
217 	if (name)
218 		dbg_print(MSG_INTL(MSG_FIL_HDL_RETAIN), str, name);
219 	else
220 		dbg_print(MSG_INTL(MSG_FIL_HDL_COLLECT), str,
221 		    conv_grphdrflags_str(ghp->gh_flags));
222 }
223 
224 void
225 Dbg_file_hdl_action(Grp_hdl * ghp, Rt_map * lmp, int type)
226 {
227 	Msg	str;
228 
229 	if (DBG_NOTCLASS(DBG_FILES))
230 		return;
231 	if (DBG_NOTDETAIL())
232 		return;
233 
234 	if (hdl_title) {
235 		dbg_print(MSG_ORIG(MSG_STR_EMPTY));
236 		if (hdl_str) {
237 			const char	*name;
238 
239 			/*
240 			 * Protect ourselves in case this handle has no
241 			 * originating owner.
242 			 */
243 			if (ghp->gh_owner)
244 				name = NAME(ghp->gh_owner);
245 			else
246 				name = MSG_INTL(MSG_STR_UNKNOWN);
247 
248 			dbg_print(MSG_INTL(hdl_str), name);
249 		}
250 		hdl_title = 0;
251 	}
252 
253 	if (type == DBG_DEP_ADD)
254 	    str = MSG_FIL_DEP_ADD;	/* MSG_INTL(MSG_FIL_DEP_ADD) */
255 	else if (type == DBG_DEP_DELETE)
256 	    str = MSG_FIL_DEP_DELETE;	/* MSG_INTL(MSG_FIL_DEP_DELETE) */
257 	else if (type == DBG_DEP_REMOVE)
258 	    str = MSG_FIL_DEP_REMOVE;	/* MSG_INTL(MSG_FIL_DEP_REMOVE) */
259 	else if (type == DBG_DEP_REMAIN)
260 	    str = MSG_FIL_DEP_REMAIN;	/* MSG_INTL(MSG_FIL_DEP_REMAIN) */
261 	else
262 	    str = 0;
263 
264 	if (str) {
265 		const char *mode;
266 
267 		if ((MODE(lmp) & (RTLD_GLOBAL | RTLD_NODELETE)) ==
268 		    (RTLD_GLOBAL | RTLD_NODELETE))
269 			mode = MSG_ORIG(MSG_MODE_GLOBNODEL);
270 		else if (MODE(lmp) & RTLD_GLOBAL)
271 			mode = MSG_ORIG(MSG_MODE_GLOB);
272 
273 		else if (MODE(lmp) & RTLD_NODELETE)
274 			mode = MSG_ORIG(MSG_MODE_NODEL);
275 		else
276 			mode = MSG_ORIG(MSG_STR_EMPTY);
277 
278 		dbg_print(MSG_INTL(str), NAME(lmp), mode);
279 	}
280 }
281 
282 #define	BINDSZ	MSG_STR_OSQBRKT_SIZE + \
283 		MSG_BND_NEEDED_SIZE + \
284 		MSG_BND_REFER_SIZE + \
285 		MSG_STR_CSQBRKT_SIZE
286 
287 void
288 Dbg_file_bind_entry(Bnd_desc *bdp)
289 {
290 	char		string[BINDSZ];
291 	Rt_map		*clmp, *dlmp;
292 	uint_t		flags;
293 
294 	if (DBG_NOTCLASS(DBG_FILES))
295 		return;
296 	if (DBG_NOTDETAIL())
297 		return;
298 
299 	clmp = bdp->b_caller;
300 	dlmp = bdp->b_depend;
301 	flags = bdp->b_flags;
302 
303 	/*
304 	 * Evaluate the binding descriptors flags.
305 	 */
306 	if (flags) {
307 		(void) strcpy(string, MSG_ORIG(MSG_STR_OSQBRKT));
308 		if (flags & BND_NEEDED)
309 			(void) strcat(string, MSG_ORIG(MSG_BND_NEEDED));
310 		if (flags & BND_REFER)
311 			(void) strcat(string, MSG_ORIG(MSG_BND_REFER));
312 		(void) strcat(string, MSG_ORIG(MSG_STR_CSQBRKT));
313 	} else
314 		(void) strcpy(string, MSG_ORIG(MSG_STR_EMPTY));
315 
316 	/*
317 	 * Print the dependency together with the modes of the binding.
318 	 */
319 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
320 	dbg_print(MSG_INTL(MSG_FIL_BND_ADD), NAME(clmp));
321 	dbg_print(MSG_INTL(MSG_FIL_BND_FILE), NAME(dlmp), string);
322 }
323 
324 void
325 Dbg_file_dlopen(const char *name, const char *from, int mode)
326 {
327 	if (DBG_NOTCLASS(DBG_FILES))
328 		return;
329 
330 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
331 	dbg_print(MSG_INTL(MSG_FIL_DLOPEN), name, from,
332 	    conv_dlmode_str(mode, 1));
333 }
334 
335 void
336 Dbg_file_dlclose(const char *name, int flag)
337 {
338 	const char	*str;
339 
340 	if (DBG_NOTCLASS(DBG_FILES))
341 		return;
342 
343 	if (flag == DBG_DLCLOSE_IGNORE)
344 		str = MSG_INTL(MSG_STR_IGNORE);
345 	else
346 		str = MSG_ORIG(MSG_STR_EMPTY);
347 
348 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
349 	dbg_print(MSG_INTL(MSG_FIL_DLCLOSE), name, str);
350 }
351 
352 void
353 Dbg_file_dldump(const char *ipath, const char *opath, int flags)
354 {
355 	if (DBG_NOTCLASS(DBG_FILES))
356 		return;
357 
358 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
359 	dbg_print(MSG_INTL(MSG_FIL_DLDUMP), ipath, opath,
360 		conv_dlflag_str(flags, 0));
361 }
362 
363 void
364 Dbg_file_lazyload(const char *file, const char *from, const char *symname)
365 {
366 	if (DBG_NOTCLASS(DBG_FILES))
367 		return;
368 
369 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
370 	dbg_print(MSG_INTL(MSG_FIL_LAZYLOAD), file, from,
371 	    _Dbg_sym_dem(symname));
372 }
373 
374 void
375 Dbg_file_nl()
376 {
377 	if (DBG_NOTCLASS(DBG_FILES))
378 		return;
379 	if (DBG_NOTDETAIL())
380 		return;
381 
382 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
383 }
384 
385 void
386 Dbg_file_preload(const char *name)
387 {
388 	if (DBG_NOTCLASS(DBG_FILES))
389 		return;
390 
391 	dbg_print(MSG_INTL(MSG_FIL_PRELOAD), name);
392 }
393 
394 void
395 Dbg_file_needed(const char *name, const char *parent)
396 {
397 	if (DBG_NOTCLASS(DBG_FILES))
398 		return;
399 
400 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
401 	dbg_print(MSG_INTL(MSG_FIL_NEEDED), name, parent);
402 }
403 
404 void
405 Dbg_file_filter(const char *filter, const char *filtee, int config)
406 {
407 	if (DBG_NOTCLASS(DBG_FILES))
408 		return;
409 
410 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
411 	if (config)
412 		dbg_print(MSG_INTL(MSG_FIL_FILTER_1), filter, filtee);
413 	else
414 		dbg_print(MSG_INTL(MSG_FIL_FILTER_2), filter, filtee);
415 }
416 
417 void
418 Dbg_file_filtee(const char *filter, const char *filtee, int audit)
419 {
420 	if (audit) {
421 		if (DBG_NOTCLASS(DBG_AUDITING | DBG_FILES))
422 			return;
423 
424 		dbg_print(MSG_ORIG(MSG_STR_EMPTY));
425 		dbg_print(MSG_INTL(MSG_FIL_FILTEE_3), filtee);
426 	} else {
427 		if (DBG_NOTCLASS(DBG_FILES))
428 			return;
429 
430 		dbg_print(MSG_ORIG(MSG_STR_EMPTY));
431 		if (filter)
432 			dbg_print(MSG_INTL(MSG_FIL_FILTEE_1), filtee, filter);
433 		else
434 			dbg_print(MSG_INTL(MSG_FIL_FILTEE_2), filtee);
435 	}
436 }
437 
438 void
439 Dbg_file_fixname(const char *oname, const char *nname)
440 {
441 	if (DBG_NOTCLASS(DBG_FILES))
442 		return;
443 
444 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
445 	dbg_print(MSG_INTL(MSG_FIL_FIXNAME), oname, nname);
446 }
447 
448 void
449 Dbg_file_output(Ofl_desc *ofl)
450 {
451 	const char	*prefix = MSG_ORIG(MSG_PTH_OBJECT);
452 	char		*oname, *nname, *ofile;
453 	int		fd;
454 
455 	if (DBG_NOTCLASS(DBG_FILES))
456 		return;
457 	if (DBG_NOTDETAIL())
458 		return;
459 
460 	/*
461 	 * Obtain the present input object filename for concatenation to the
462 	 * prefix name.
463 	 */
464 	oname = (char *)ofl->ofl_name;
465 	if ((ofile = strrchr(oname, '/')) == NULL)
466 		ofile = oname;
467 	else
468 		ofile++;
469 
470 	/*
471 	 * Concatenate the prefix with the object filename, open the file and
472 	 * write out the present Elf memory image.  As this is debugging we
473 	 * ignore all errors.
474 	 */
475 	if ((nname = (char *)malloc(strlen(prefix) + strlen(ofile) + 1)) != 0) {
476 		(void) strcpy(nname, prefix);
477 		(void) strcat(nname, ofile);
478 		if ((fd = open(nname, O_RDWR | O_CREAT | O_TRUNC,
479 		    0666)) != -1) {
480 			(void) write(fd, ofl->ofl_ehdr, ofl->ofl_size);
481 			close(fd);
482 		}
483 		free(nname);
484 	}
485 }
486 
487 void
488 Dbg_file_config_dis(const char *config, int features)
489 {
490 	const char	*str;
491 	int		error = features & ~CONF_FEATMSK;
492 
493 	if (error == DBG_CONF_IGNORE)
494 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_1);
495 	else if (error == DBG_CONF_VERSION)
496 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_2);
497 	else if (error == DBG_CONF_PRCFAIL)
498 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_3);
499 	else if (error == DBG_CONF_CORRUPT)
500 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_4);
501 	else
502 		str = conv_config_str(features);
503 
504 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
505 	dbg_print(MSG_INTL(MSG_FIL_CONFIG_ERR), config, str);
506 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
507 }
508 
509 void
510 Dbg_file_config_obj(const char *dir, const char *file, const char *config)
511 {
512 	char	*name, _name[PATH_MAX];
513 
514 	if (DBG_NOTCLASS(DBG_FILES))
515 		return;
516 
517 	if (file) {
518 		(void) snprintf(_name, PATH_MAX, MSG_ORIG(MSG_FMT_PATH),
519 		    dir, file);
520 		name = _name;
521 	} else
522 		name = (char *)dir;
523 
524 	dbg_print(MSG_INTL(MSG_FIL_CONFIG), name, config);
525 }
526 
527 #if	!defined(_ELF64)
528 
529 const Msg
530 reject[] = {
531 	MSG_STR_EMPTY,
532 	MSG_REJ_MACH,		/* MSG_INTL(MSG_REJ_MACH) */
533 	MSG_REJ_CLASS,		/* MSG_INTL(MSG_REJ_CLASS) */
534 	MSG_REJ_DATA,		/* MSG_INTL(MSG_REJ_DATA) */
535 	MSG_REJ_TYPE,		/* MSG_INTL(MSG_REJ_TYPE) */
536 	MSG_REJ_BADFLAG,	/* MSG_INTL(MSG_REJ_BADFLAG) */
537 	MSG_REJ_MISFLAG,	/* MSG_INTL(MSG_REJ_MISFLAG) */
538 	MSG_REJ_VERSION,	/* MSG_INTL(MSG_REJ_VERSION) */
539 	MSG_REJ_HAL,		/* MSG_INTL(MSG_REJ_HAL) */
540 	MSG_REJ_US3,		/* MSG_INTL(MSG_REJ_US3) */
541 	MSG_REJ_STR,		/* MSG_INTL(MSG_REJ_STR) */
542 	MSG_REJ_UNKFILE,	/* MSG_INTL(MSG_REJ_UNKFILE) */
543 	MSG_REJ_HWCAP_1,	/* MSG_INTL(MSG_REJ_HWCAP_1) */
544 };
545 
546 void
547 Dbg_file_rejected(Rej_desc *rej)
548 {
549 	if (DBG_NOTCLASS(DBG_FILES))
550 		return;
551 
552 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
553 	dbg_print(MSG_INTL(reject[rej->rej_type]), rej->rej_name ?
554 	    rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN), conv_reject_str(rej));
555 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
556 }
557 
558 void
559 Dbg_file_del_rescan(void)
560 {
561 	if (DBG_NOTCLASS(DBG_FILES))
562 		return;
563 
564 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
565 	dbg_print(MSG_INTL(MSG_FIL_DEL_RESCAN));
566 }
567 
568 void
569 Dbg_file_ar_rescan(void)
570 {
571 	if (DBG_NOTCLASS(DBG_FILES))
572 		return;
573 
574 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
575 	dbg_print(MSG_INTL(MSG_FIL_AR_RESCAN));
576 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
577 }
578 
579 void
580 Dbg_file_mode_promote(const char *file, int mode)
581 {
582 	if (DBG_NOTCLASS(DBG_FILES))
583 		return;
584 
585 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
586 	dbg_print(MSG_INTL(MSG_FIL_PROMOTE), file, conv_dlmode_str(mode, 0));
587 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
588 }
589 
590 void
591 Dbg_file_cntl(Lm_list *lml, Aliste flmco, Aliste tlmco)
592 {
593 	Lm_cntl	*lmc;
594 	Aliste	off;
595 
596 	if (DBG_NOTCLASS(DBG_FILES))
597 		return;
598 	if (DBG_NOTDETAIL())
599 		return;
600 
601 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
602 	dbg_print(MSG_INTL(MSG_CNTL_TITLE), EC_XWORD(flmco), EC_XWORD(tlmco));
603 
604 	for (ALIST_TRAVERSE(lml->lm_lists, off, lmc)) {
605 		Rt_map	*lmp;
606 
607 		for (lmp = lmc->lc_head; lmp; lmp = (Rt_map *)NEXT(lmp))
608 			dbg_print(MSG_ORIG(MSG_CNTL_ENTRY), EC_XWORD(off),
609 			    NAME(lmp));
610 	}
611 	dbg_print(MSG_ORIG(MSG_STR_EMPTY));
612 }
613 #endif
614