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 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include	<sys/auxv.h>
28 #include	<string.h>
29 #include	<unistd.h>
30 #include	<fcntl.h>
31 #include	<limits.h>
32 #include	<stdio.h>
33 #include	<libld.h>
34 #include	<rtld.h>
35 #include	<conv.h>
36 #include	"msg.h"
37 #include	"_debug.h"
38 
39 void
40 Dbg_file_analyze(Rt_map *lmp)
41 {
42 	Conv_dl_mode_buf_t	dl_mode_buf;
43 	Lm_list			*lml = LIST(lmp);
44 
45 	if (DBG_NOTCLASS(DBG_C_FILES))
46 		return;
47 
48 	Dbg_util_nl(lml, DBG_NL_STD);
49 	dbg_print(lml, MSG_INTL(MSG_FIL_ANALYZE), NAME(lmp),
50 	    conv_dl_mode(MODE(lmp), 1, &dl_mode_buf));
51 }
52 
53 void
54 Dbg_file_mmapobj(Lm_list *lml, const char *name, mmapobj_result_t *ompp,
55     uint_t onum)
56 {
57 	mmapobj_result_t	*mpp;
58 	uint_t			mnum;
59 
60 	if (DBG_NOTCLASS(DBG_C_FILES))
61 		return;
62 	if (DBG_NOTDETAIL())
63 		return;
64 
65 	Dbg_util_nl(lml, DBG_NL_STD);
66 	dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ), name, onum);
67 
68 	for (mnum = 0, mpp = ompp; mnum < onum; mnum++, mpp++) {
69 		const char	*str;
70 		uint_t		type = MR_GET_TYPE(mpp->mr_flags);
71 
72 		if (type == MR_PADDING)
73 			str = MSG_ORIG(MSG_MR_PADDING);
74 		else if (type == MR_HDR_ELF)
75 			str = MSG_ORIG(MSG_MR_HDR_ELF);
76 		else if (type == MR_HDR_AOUT)
77 			str = MSG_ORIG(MSG_MR_HDR_AOUT);
78 		else
79 			str = MSG_ORIG(MSG_STR_EMPTY);
80 
81 		dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ_1), mnum,
82 		    EC_NATPTR(mpp->mr_addr), EC_OFF(mpp->mr_fsize), str);
83 		dbg_print(lml, MSG_INTL(MSG_FIL_MMAPOBJ_2),
84 		    EC_OFF(mpp->mr_offset), EC_OFF(mpp->mr_msize));
85 	}
86 	Dbg_util_nl(lml, DBG_NL_STD);
87 }
88 
89 void
90 Dbg_file_aout(Lm_list *lml, const char *name, Addr addr, size_t size,
91     const char *lmid, Aliste lmco)
92 {
93 	if (DBG_NOTCLASS(DBG_C_FILES))
94 		return;
95 
96 	dbg_print(lml, MSG_INTL(MSG_FIL_AOUT), name);
97 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(addr), EC_OFF(size));
98 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
99 }
100 
101 void
102 Dbg_file_elf(Lm_list *lml, const char *name, Addr addr, size_t size,
103     const char *lmid, Aliste lmco)
104 {
105 	const char	*str;
106 
107 	if (DBG_NOTCLASS(DBG_C_FILES))
108 		return;
109 
110 	if (addr == 0)
111 		str = MSG_INTL(MSG_STR_TEMPORARY);
112 	else
113 		str = MSG_ORIG(MSG_STR_EMPTY);
114 
115 	dbg_print(lml, MSG_INTL(MSG_FIL_ELF), name, str);
116 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(addr), EC_OFF(size));
117 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
118 }
119 
120 void
121 Dbg_file_ldso(Rt_map *lmp, char **envp, auxv_t *auxv, const char *lmid,
122     Aliste lmco)
123 {
124 	Lm_list	*lml = LIST(lmp);
125 
126 	if (DBG_NOTCLASS(DBG_C_FILES))
127 		return;
128 
129 	Dbg_util_nl(lml, DBG_NL_STD);
130 	dbg_print(lml, MSG_INTL(MSG_FIL_LDSO), PATHNAME(lmp));
131 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_AS), EC_ADDR(ADDR(lmp)),
132 	    EC_OFF(MSIZE(lmp)));
133 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_EA), EC_NATPTR(envp),
134 	    EC_NATPTR(auxv));
135 	dbg_print(lml, MSG_INTL(MSG_FIL_DATA_LL), lmid, EC_XWORD(lmco));
136 	Dbg_util_nl(lml, DBG_NL_STD);
137 }
138 
139 
140 void
141 Dbg_file_prot(Rt_map *lmp, int prot)
142 {
143 	Lm_list	*lml = LIST(lmp);
144 
145 	if (DBG_NOTCLASS(DBG_C_FILES))
146 		return;
147 
148 	Dbg_util_nl(lml, DBG_NL_STD);
149 	dbg_print(lml, MSG_INTL(MSG_FIL_PROT), NAME(lmp), (prot ? '+' : '-'));
150 }
151 
152 void
153 Dbg_file_delete(Rt_map *lmp)
154 {
155 	Lm_list	*lml = LIST(lmp);
156 
157 	if (DBG_NOTCLASS(DBG_C_FILES))
158 		return;
159 
160 	Dbg_util_nl(lml, DBG_NL_STD);
161 	dbg_print(lml, MSG_INTL(MSG_FIL_DELETE), NAME(lmp));
162 }
163 
164 static int	hdl_title = 0;
165 static Msg	hdl_str = 0;
166 
167 void
168 Dbg_file_hdl_title(int type)
169 {
170 	static const Msg titles[] = {
171 		MSG_FIL_HDL_CREATE,	/* MSG_INTL(MSG_FIL_HDL_CREATE) */
172 		MSG_FIL_HDL_ADD,	/* MSG_INTL(MSG_FIL_HDL_ADD) */
173 		MSG_FIL_HDL_DELETE,	/* MSG_INTL(MSG_FIL_HDL_DELETE) */
174 		MSG_FIL_HDL_ORPHAN,	/* MSG_INTL(MSG_FIL_HDL_ORPHAN) */
175 		MSG_FIL_HDL_REINST,	/* MSG_INTL(MSG_FIL_HDL_REINST) */
176 	};
177 
178 	if (DBG_NOTCLASS(DBG_C_FILES))
179 		return;
180 	if (DBG_NOTDETAIL())
181 		return;
182 
183 	/*
184 	 * Establish a binding title for later use in Dbg_file_hdl_action.
185 	 */
186 	if (type <= DBG_HDL_REINST) {
187 		hdl_str = titles[type];
188 		hdl_title = 1;
189 	} else {
190 		hdl_str = 0;
191 		hdl_title = 0;
192 	}
193 }
194 
195 void
196 Dbg_file_hdl_collect(Grp_hdl *ghp, const char *name)
197 {
198 	Conv_grphdl_flags_buf_t	grphdl_flags_buf;
199 	Lm_list		*lml = ghp->gh_ownlml;
200 	const char	*str;
201 
202 	if (DBG_NOTCLASS(DBG_C_FILES))
203 		return;
204 	if (DBG_NOTDETAIL())
205 		return;
206 
207 	if (ghp->gh_ownlmp)
208 		str = NAME(ghp->gh_ownlmp);
209 	else
210 		str = MSG_INTL(MSG_STR_ORPHAN);
211 
212 	if (hdl_title) {
213 		hdl_title = 0;
214 		Dbg_util_nl(lml, DBG_NL_STD);
215 	}
216 	if (name)
217 		dbg_print(lml, MSG_INTL(MSG_FIL_HDL_RETAIN), str, name);
218 	else
219 		dbg_print(lml, MSG_INTL(MSG_FIL_HDL_COLLECT), str,
220 		    conv_grphdl_flags(ghp->gh_flags, &grphdl_flags_buf));
221 }
222 
223 void
224 Dbg_file_hdl_action(Grp_hdl *ghp, Rt_map *lmp, int type, uint_t flags)
225 {
226 	Conv_grpdesc_flags_buf_t grpdesc_flags_buf;
227 	const char	*mode, *group;
228 	Lm_list		*lml = LIST(lmp);
229 	Msg		str;
230 
231 	static const Msg fmt[] = {
232 		MSG_FIL_DEP_ADD,	/* MSG_INTL(MSG_FIL_DEP_ADD) */
233 		MSG_FIL_DEP_UPDATE,	/* MSG_INTL(MSG_FIL_DEP_UPDATE) */
234 		MSG_FIL_DEP_DELETE,	/* MSG_INTL(MSG_FIL_DEP_DELETE) */
235 		MSG_FIL_DEP_REMOVE,	/* MSG_INTL(MSG_FIL_DEP_REMOVE) */
236 		MSG_FIL_DEP_REMAIN,	/* MSG_INTL(MSG_FIL_DEP_REMAIN) */
237 		MSG_FIL_DEP_ORPHAN,	/* MSG_INTL(MSG_FIL_DEP_ORPHAN) */
238 		MSG_FIL_DEP_REINST,	/* MSG_INTL(MSG_FIL_DEP_REINST) */
239 	};
240 	if (DBG_NOTCLASS(DBG_C_FILES))
241 		return;
242 	if (DBG_NOTDETAIL())
243 		return;
244 
245 	if (hdl_title) {
246 		Dbg_util_nl(lml, DBG_NL_STD);
247 		if (hdl_str) {
248 			Conv_grphdl_flags_buf_t grphdl_flags_buf;
249 			const char	*name;
250 
251 			/*
252 			 * Protect ourselves in case this handle has no
253 			 * originating owner.
254 			 */
255 			if (ghp->gh_ownlmp)
256 				name = NAME(ghp->gh_ownlmp);
257 			else
258 				name = MSG_INTL(MSG_STR_UNKNOWN);
259 
260 			dbg_print(lml, MSG_INTL(hdl_str), name,
261 			    conv_grphdl_flags(ghp->gh_flags, &grphdl_flags_buf),
262 			    EC_NATPTR(ghp));
263 		}
264 		hdl_title = 0;
265 	}
266 
267 	/*
268 	 * Establish a binding descriptor format string.
269 	 */
270 	if (type > DBG_DEP_REINST)
271 		return;
272 
273 	str = fmt[type];
274 
275 	if (((type == DBG_DEP_ADD) || (type == DBG_DEP_UPDATE)) && flags)
276 		group = conv_grpdesc_flags(flags, &grpdesc_flags_buf);
277 	else
278 		group = MSG_ORIG(MSG_STR_EMPTY);
279 
280 	if ((MODE(lmp) & (RTLD_GLOBAL | RTLD_NODELETE)) ==
281 	    (RTLD_GLOBAL | RTLD_NODELETE))
282 		mode = MSG_ORIG(MSG_MODE_GLOBNODEL);
283 	else if (MODE(lmp) & RTLD_GLOBAL)
284 		mode = MSG_ORIG(MSG_MODE_GLOB);
285 	else if (MODE(lmp) & RTLD_NODELETE)
286 		mode = MSG_ORIG(MSG_MODE_NODEL);
287 	else
288 		mode = MSG_ORIG(MSG_STR_EMPTY);
289 
290 	dbg_print(lml, MSG_INTL(str), NAME(lmp), mode, group);
291 }
292 
293 void
294 Dbg_file_bind_entry(Lm_list *lml, Bnd_desc *bdp)
295 {
296 	Conv_bnd_type_buf_t bnd_type_buf;
297 
298 	if (DBG_NOTCLASS(DBG_C_FILES))
299 		return;
300 	if (DBG_NOTDETAIL())
301 		return;
302 
303 	/*
304 	 * Print the dependency together with the modes of the binding.
305 	 */
306 	Dbg_util_nl(lml, DBG_NL_STD);
307 	dbg_print(lml, MSG_INTL(MSG_FIL_BND_ADD), NAME(bdp->b_caller));
308 	dbg_print(lml, MSG_INTL(MSG_FIL_BND_FILE), NAME(bdp->b_depend),
309 	    conv_bnd_type(bdp->b_flags, &bnd_type_buf));
310 }
311 
312 void
313 Dbg_file_bindings(Rt_map *lmp, int flag)
314 {
315 	Conv_bnd_obj_buf_t	bnd_obj_buf;
316 	Conv_bnd_type_buf_t	bnd_type_buf;
317 	const char	*str;
318 	Rt_map		*tlmp;
319 	Lm_list		*lml = LIST(lmp);
320 	int		next = 0;
321 
322 	if (DBG_NOTCLASS(DBG_C_INIT))
323 		return;
324 	if (DBG_NOTDETAIL())
325 		return;
326 
327 	if (flag & RT_SORT_REV)
328 		str = MSG_ORIG(MSG_SCN_INIT);
329 	else
330 		str = MSG_ORIG(MSG_SCN_FINI);
331 
332 	Dbg_util_nl(lml, DBG_NL_STD);
333 	dbg_print(lml, MSG_INTL(MSG_FIL_DEP_TITLE), str,
334 	    conv_bnd_obj(lml->lm_flags, &bnd_obj_buf));
335 
336 	/* LINTED */
337 	for (tlmp = lmp; tlmp; tlmp = (Rt_map *)NEXT(tlmp)) {
338 		Bnd_desc	*bdp;
339 		Aliste		idx;
340 
341 		/*
342 		 * For .init processing, only collect objects that have been
343 		 * relocated and haven't already been collected.
344 		 * For .fini processing, only collect objects that have had
345 		 * their .init collected, and haven't already been .fini
346 		 * collected.
347 		 */
348 		if (flag & RT_SORT_REV) {
349 			if ((FLAGS(tlmp) & (FLG_RT_RELOCED |
350 			    FLG_RT_INITCLCT)) != FLG_RT_RELOCED)
351 				continue;
352 
353 		} else {
354 			if ((flag & RT_SORT_DELETE) &&
355 			    ((FLAGS(tlmp) & FLG_RT_DELETE) == 0))
356 				continue;
357 			if (((FLAGS(tlmp) &
358 			    (FLG_RT_INITCLCT | FLG_RT_FINICLCT)) ==
359 			    FLG_RT_INITCLCT) == 0)
360 				continue;
361 		}
362 
363 		if (next++)
364 			Dbg_util_nl(lml, DBG_NL_STD);
365 
366 		if (DEPENDS(tlmp) == NULL)
367 			dbg_print(lml, MSG_INTL(MSG_FIL_DEP_NONE), NAME(tlmp));
368 		else {
369 			dbg_print(lml, MSG_INTL(MSG_FIL_DEP_ENT), NAME(tlmp));
370 
371 			for (APLIST_TRAVERSE(DEPENDS(tlmp), idx, bdp)) {
372 				dbg_print(lml, MSG_INTL(MSG_FIL_BND_FILE),
373 				    NAME(bdp->b_depend),
374 				    conv_bnd_type(bdp->b_flags,
375 				    &bnd_type_buf));
376 			}
377 		}
378 	}
379 	Dbg_util_nl(lml, DBG_NL_STD);
380 }
381 
382 void
383 Dbg_file_bindings_done(Lm_list *lml)
384 {
385 	if (DBG_NOTCLASS(DBG_C_INIT))
386 		return;
387 	if (DBG_NOTDETAIL())
388 		return;
389 
390 	DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
391 }
392 
393 void
394 Dbg_file_dlopen(Rt_map *clmp, const char *name, int *in_nfavl, int mode)
395 {
396 	Conv_dl_mode_buf_t	dl_mode_buf;
397 	Lm_list			*lml = LIST(clmp);
398 	const char		*retry;
399 
400 	if (DBG_NOTCLASS(DBG_C_FILES))
401 		return;
402 
403 	/*
404 	 * The core functionality of dlopen() can be called twice.  The first
405 	 * attempt can be affected by path names that exist in the "not-found"
406 	 * AVL tree.  Should a "not-found" path name be found, a second attempt
407 	 * is made to locate the required file (in_nfavl is NULL).  This fall-
408 	 * back provides for file system changes while a process executes.
409 	 */
410 	if (in_nfavl)
411 		retry = MSG_ORIG(MSG_STR_EMPTY);
412 	else
413 		retry = MSG_INTL(MSG_STR_RETRY);
414 
415 	Dbg_util_nl(lml, DBG_NL_STD);
416 	dbg_print(lml, MSG_INTL(MSG_FIL_DLOPEN), name, NAME(clmp), retry,
417 	    conv_dl_mode(mode, 0, &dl_mode_buf));
418 }
419 
420 void
421 Dbg_file_dlclose(Lm_list *lml, const char *name, int flag)
422 {
423 	const char	*str;
424 
425 	if (DBG_NOTCLASS(DBG_C_FILES))
426 		return;
427 
428 	if (flag == DBG_DLCLOSE_IGNORE)
429 		str = MSG_INTL(MSG_STR_IGNORE);
430 	else
431 		str = MSG_ORIG(MSG_STR_EMPTY);
432 
433 	Dbg_util_nl(lml, DBG_NL_STD);
434 	dbg_print(lml, MSG_INTL(MSG_FIL_DLCLOSE), name, str);
435 }
436 
437 void
438 Dbg_file_dldump(Rt_map *lmp, const char *path, int flags)
439 {
440 	Conv_dl_flag_buf_t	dl_flag_buf;
441 	Lm_list			*lml = LIST(lmp);
442 
443 	if (DBG_NOTCLASS(DBG_C_FILES))
444 		return;
445 
446 	Dbg_util_nl(lml, DBG_NL_STD);
447 	dbg_print(lml, MSG_INTL(MSG_FIL_DLDUMP), NAME(lmp), path,
448 	    conv_dl_flag(flags, 0, &dl_flag_buf));
449 }
450 
451 void
452 Dbg_file_lazyload(Rt_map *clmp, const char *fname, const char *sname)
453 {
454 	Lm_list	*lml = LIST(clmp);
455 
456 	if (DBG_NOTCLASS(DBG_C_FILES))
457 		return;
458 
459 	Dbg_util_nl(lml, DBG_NL_STD);
460 	dbg_print(lml, MSG_INTL(MSG_FIL_LAZYLOAD), fname, NAME(clmp),
461 	    Dbg_demangle_name(sname));
462 }
463 
464 void
465 Dbg_file_preload(Lm_list *lml, const char *name)
466 {
467 	if (DBG_NOTCLASS(DBG_C_FILES))
468 		return;
469 
470 	Dbg_util_nl(lml, DBG_NL_STD);
471 	dbg_print(lml, MSG_INTL(MSG_FIL_PRELOAD), name);
472 }
473 
474 void
475 Dbg_file_needed(Rt_map *lmp, const char *name)
476 {
477 	Lm_list	*lml = LIST(lmp);
478 
479 	if (DBG_NOTCLASS(DBG_C_FILES))
480 		return;
481 
482 	Dbg_util_nl(lml, DBG_NL_STD);
483 	dbg_print(lml, MSG_INTL(MSG_FIL_NEEDED), name, NAME(lmp));
484 }
485 
486 void
487 Dbg_file_filter(Lm_list *lml, const char *filter, const char *filtee,
488     int config)
489 {
490 	if (DBG_NOTCLASS(DBG_C_FILES))
491 		return;
492 
493 	Dbg_util_nl(lml, DBG_NL_STD);
494 	if (config)
495 		dbg_print(lml, MSG_INTL(MSG_FIL_FILTER_1), filter, filtee);
496 	else
497 		dbg_print(lml, MSG_INTL(MSG_FIL_FILTER_2), filter, filtee);
498 }
499 
500 void
501 Dbg_file_filtee(Lm_list *lml, const char *filter, const char *filtee, int audit)
502 {
503 	if (audit) {
504 		if (DBG_NOTCLASS(DBG_C_AUDITING | DBG_C_FILES))
505 			return;
506 
507 		Dbg_util_nl(lml, DBG_NL_STD);
508 		dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_3), filtee);
509 	} else {
510 		if (DBG_NOTCLASS(DBG_C_FILES))
511 			return;
512 
513 		Dbg_util_nl(lml, DBG_NL_STD);
514 		if (filter)
515 			dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_1), filtee,
516 			    filter);
517 		else
518 			dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_2), filtee);
519 	}
520 }
521 
522 void
523 Dbg_file_fixname(Lm_list *lml, const char *oname, const char *nname)
524 {
525 	if (DBG_NOTCLASS(DBG_C_FILES))
526 		return;
527 
528 	Dbg_util_nl(lml, DBG_NL_STD);
529 	dbg_print(lml, MSG_INTL(MSG_FIL_FIXNAME), oname, nname);
530 }
531 
532 void
533 Dbg_file_output(Ofl_desc *ofl)
534 {
535 	const char	*prefix = MSG_ORIG(MSG_PTH_OBJECT);
536 	char		*oname, *nname, *ofile;
537 	int		fd;
538 
539 	if (DBG_NOTCLASS(DBG_C_FILES))
540 		return;
541 	if (DBG_NOTDETAIL())
542 		return;
543 
544 	/*
545 	 * Obtain the present input object filename for concatenation to the
546 	 * prefix name.
547 	 */
548 	oname = (char *)ofl->ofl_name;
549 	if ((ofile = strrchr(oname, '/')) == NULL)
550 		ofile = oname;
551 	else
552 		ofile++;
553 
554 	/*
555 	 * Concatenate the prefix with the object filename, open the file and
556 	 * write out the present Elf memory image.  As this is debugging we
557 	 * ignore all errors.
558 	 */
559 	if ((nname = malloc(strlen(prefix) + strlen(ofile) + 1)) != 0) {
560 		(void) strcpy(nname, prefix);
561 		(void) strcat(nname, ofile);
562 		if ((fd = open(nname, O_RDWR | O_CREAT | O_TRUNC,
563 		    0666)) != -1) {
564 			(void) write(fd, ofl->ofl_nehdr, ofl->ofl_size);
565 			(void) close(fd);
566 		}
567 		free(nname);
568 	}
569 }
570 
571 void
572 Dbg_file_config_dis(Lm_list *lml, const char *config, int features)
573 {
574 	Conv_config_feat_buf_t	config_feat_buf;
575 	const char		*str;
576 
577 	switch (features & ~CONF_FEATMSK) {
578 	case DBG_CONF_IGNORE:
579 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_1);
580 		break;
581 	case DBG_CONF_VERSION:
582 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_2);
583 		break;
584 	case DBG_CONF_PRCFAIL:
585 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_3);
586 		break;
587 	case DBG_CONF_CORRUPT:
588 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_4);
589 		break;
590 	case DBG_CONF_ABIMISMATCH:
591 		str = MSG_INTL(MSG_FIL_CONFIG_ERR_5);
592 		break;
593 	default:
594 		str = conv_config_feat(features, &config_feat_buf);
595 		break;
596 	}
597 
598 	Dbg_util_nl(lml, DBG_NL_FRC);
599 	dbg_print(lml, MSG_INTL(MSG_FIL_CONFIG_ERR), config, str);
600 	Dbg_util_nl(lml, DBG_NL_FRC);
601 }
602 
603 void
604 Dbg_file_config_obj(Lm_list *lml, const char *dir, const char *file,
605     const char *config)
606 {
607 	char	*name, _name[PATH_MAX];
608 
609 	if (DBG_NOTCLASS(DBG_C_FILES))
610 		return;
611 
612 	if (file) {
613 		(void) snprintf(_name, PATH_MAX, MSG_ORIG(MSG_FMT_PATH),
614 		    dir, file);
615 		name = _name;
616 	} else
617 		name = (char *)dir;
618 
619 	dbg_print(lml, MSG_INTL(MSG_FIL_CONFIG), name, config);
620 }
621 
622 void
623 Dbg_file_del_rescan(Lm_list *lml)
624 {
625 	if (DBG_NOTCLASS(DBG_C_FILES))
626 		return;
627 
628 	Dbg_util_nl(lml, DBG_NL_STD);
629 	dbg_print(lml, MSG_INTL(MSG_FIL_DEL_RESCAN));
630 }
631 
632 void
633 Dbg_file_mode_promote(Rt_map *lmp, int mode)
634 {
635 	Conv_dl_mode_buf_t	dl_mode_buf;
636 	Lm_list			*lml = LIST(lmp);
637 
638 	if (DBG_NOTCLASS(DBG_C_FILES))
639 		return;
640 
641 	Dbg_util_nl(lml, DBG_NL_STD);
642 	dbg_print(lml, MSG_INTL(MSG_FIL_PROMOTE), NAME(lmp),
643 	    conv_dl_mode(mode, 0, &dl_mode_buf));
644 	Dbg_util_nl(lml, DBG_NL_STD);
645 }
646 
647 void
648 Dbg_file_cntl(Lm_list *lml, Aliste flmco, Aliste tlmco)
649 {
650 	Lm_cntl	*lmc;
651 	Aliste	off;
652 
653 	if (DBG_NOTCLASS(DBG_C_FILES))
654 		return;
655 	if (DBG_NOTDETAIL())
656 		return;
657 
658 	Dbg_util_nl(lml, DBG_NL_STD);
659 	dbg_print(lml, MSG_INTL(MSG_CNTL_TITLE), EC_XWORD(flmco),
660 	    EC_XWORD(tlmco));
661 
662 	for (ALIST_TRAVERSE_BY_OFFSET(lml->lm_lists, off, lmc)) {
663 		Rt_map	*lmp;
664 
665 		/* LINTED */
666 		for (lmp = lmc->lc_head; lmp; lmp = (Rt_map *)NEXT(lmp))
667 			dbg_print(lml, MSG_ORIG(MSG_CNTL_ENTRY), EC_XWORD(off),
668 			    NAME(lmp));
669 	}
670 	Dbg_util_nl(lml, DBG_NL_STD);
671 }
672 
673 /*
674  * Report archive rescan operation.
675  *	argv_start_ndx, argv_end_ndx - Index range of command line arguments
676  *		from which archives are to be reprocessed.
677  */
678 void
679 Dbg_file_ar_rescan(Lm_list *lml, int argv_start_ndx, int argv_end_ndx)
680 {
681 	if (DBG_NOTCLASS(DBG_C_FILES))
682 		return;
683 
684 	Dbg_util_nl(lml, DBG_NL_STD);
685 	dbg_print(lml, MSG_INTL(MSG_FIL_AR_RESCAN),
686 	    argv_start_ndx, argv_end_ndx);
687 	Dbg_util_nl(lml, DBG_NL_STD);
688 }
689 
690 void
691 Dbg_file_ar(Lm_list *lml, const char *name, int again)
692 {
693 	const char	*str;
694 
695 	if (DBG_NOTCLASS(DBG_C_FILES))
696 		return;
697 
698 	if (again)
699 		str = MSG_INTL(MSG_STR_AGAIN);
700 	else
701 		str = MSG_ORIG(MSG_STR_EMPTY);
702 
703 	Dbg_util_nl(lml, DBG_NL_STD);
704 	dbg_print(lml, MSG_INTL(MSG_FIL_ARCHIVE), name, str);
705 }
706 
707 void
708 Dbg_file_generic(Lm_list *lml, Ifl_desc *ifl)
709 {
710 	Conv_inv_buf_t inv_buf;
711 
712 	if (DBG_NOTCLASS(DBG_C_FILES))
713 		return;
714 
715 	Dbg_util_nl(lml, DBG_NL_STD);
716 	dbg_print(lml, MSG_INTL(MSG_FIL_BASIC), ifl->ifl_name,
717 	    conv_ehdr_type(ifl->ifl_ehdr->e_ident[EI_OSABI],
718 	    ifl->ifl_ehdr->e_type, 0, &inv_buf));
719 }
720 
721 static const Msg
722 reject[] = {
723 	MSG_STR_EMPTY,
724 	MSG_REJ_MACH,		/* MSG_INTL(MSG_REJ_MACH) */
725 	MSG_REJ_CLASS,		/* MSG_INTL(MSG_REJ_CLASS) */
726 	MSG_REJ_DATA,		/* MSG_INTL(MSG_REJ_DATA) */
727 	MSG_REJ_TYPE,		/* MSG_INTL(MSG_REJ_TYPE) */
728 	MSG_REJ_BADFLAG,	/* MSG_INTL(MSG_REJ_BADFLAG) */
729 	MSG_REJ_MISFLAG,	/* MSG_INTL(MSG_REJ_MISFLAG) */
730 	MSG_REJ_VERSION,	/* MSG_INTL(MSG_REJ_VERSION) */
731 	MSG_REJ_HAL,		/* MSG_INTL(MSG_REJ_HAL) */
732 	MSG_REJ_US3,		/* MSG_INTL(MSG_REJ_US3) */
733 	MSG_REJ_STR,		/* MSG_INTL(MSG_REJ_STR) */
734 	MSG_REJ_UNKFILE,	/* MSG_INTL(MSG_REJ_UNKFILE) */
735 	MSG_REJ_HWCAP_1,	/* MSG_INTL(MSG_REJ_HWCAP_1) */
736 };
737 
738 void
739 Dbg_file_rejected(Lm_list *lml, Rej_desc *rej, Half mach)
740 {
741 	Conv_reject_desc_buf_t rej_buf;
742 
743 	if (DBG_NOTCLASS(DBG_C_FILES))
744 		return;
745 
746 	Dbg_util_nl(lml, DBG_NL_STD);
747 	dbg_print(lml, MSG_INTL(reject[rej->rej_type]), rej->rej_name ?
748 	    rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN),
749 	    conv_reject_desc(rej, &rej_buf, mach));
750 	Dbg_util_nl(lml, DBG_NL_STD);
751 }
752 
753 void
754 Dbg_file_reuse(Lm_list *lml, const char *nname, const char *oname)
755 {
756 	if (DBG_NOTCLASS(DBG_C_FILES))
757 		return;
758 
759 	dbg_print(lml, MSG_INTL(MSG_FIL_REUSE), nname, oname);
760 }
761 
762 void
763 Dbg_file_skip(Lm_list *lml, const char *oname, const char *nname)
764 {
765 	if (DBG_NOTCLASS(DBG_C_FILES))
766 		return;
767 
768 	if (oname && strcmp(nname, oname))
769 		dbg_print(lml, MSG_INTL(MSG_FIL_SKIP_1), nname, oname);
770 	else
771 		dbg_print(lml, MSG_INTL(MSG_FIL_SKIP_2), nname);
772 }
773 
774 void
775 Dbg_file_modified(Lm_list *lml, const char *obj, const char *oname,
776     const char *nname, int ofd, int nfd, Elf *oelf, Elf *nelf)
777 {
778 	const char	*str;
779 
780 	if (DBG_NOTCLASS(DBG_C_FILES | DBG_C_SUPPORT))
781 		return;
782 	if (DBG_NOTDETAIL())
783 		return;
784 
785 	Dbg_util_nl(lml, DBG_NL_STD);
786 	dbg_print(lml, MSG_INTL(MSG_FIL_MODIFIED), oname, obj);
787 
788 	if (nname != oname)
789 		dbg_print(lml, MSG_INTL(MSG_FIL_NAMECHANGE), nname);
790 	if (nfd != ofd) {
791 		if (nfd == -1)
792 			str = MSG_INTL(MSG_FIL_IGNORE);
793 		else
794 			str = MSG_ORIG(MSG_STR_EMPTY);
795 		dbg_print(lml, MSG_INTL(MSG_FIL_FDCHANGE), ofd, nfd, str);
796 	}
797 	if (nelf != oelf) {
798 		if (nelf == 0)
799 			str = MSG_INTL(MSG_FIL_IGNORE);
800 		else
801 			str = MSG_ORIG(MSG_STR_EMPTY);
802 		dbg_print(lml, MSG_INTL(MSG_FIL_ELFCHANGE), EC_NATPTR(oelf),
803 		    EC_NATPTR(nelf), str);
804 	}
805 	Dbg_util_nl(lml, DBG_NL_STD);
806 }
807 
808 void
809 Dbg_file_cleanup(Lm_list *lml, const char *name, Aliste lmco)
810 {
811 	if (DBG_NOTCLASS(DBG_C_FILES))
812 		return;
813 
814 	Dbg_util_nl(lml, DBG_NL_STD);
815 	dbg_print(lml, MSG_INTL(MSG_FIL_CLEANUP), name, EC_XWORD(lmco));
816 }
817