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