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