xref: /illumos-gate/usr/src/cmd/sgs/libld/common/debug.c (revision 5aefb655)
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	<stdio.h>
29 #include	<stdarg.h>
30 #include	<strings.h>
31 #include	<dlfcn.h>
32 #include	<debug.h>
33 #include	"msg.h"
34 
35 /*
36  * dbg_setup() can be called a number of times.  The typical use through
37  * LD_OPTIONS, results in dbg_setup() being called as the first argument to
38  * ld(1).  It's also possible to pass debugging tokens through the compiler,
39  * for example -Wl,-Dlibs -Wl-Ddetail, in which case multiple dbg_setup()
40  * calls are made.
41  *
42  * A distinction is also made between diagnostics being requested before any
43  * other ld(1) options are read, or whether the debugging options occur
44  * between other options on the command line.  In the latter case, the
45  * debugging options can be used to isolate diagnostics around one or more
46  * input files.  The "phase" argument allows us to select which phase of
47  * dbg_setup() processing we should isolate ourselves to.
48  *
49  * dbg_print() can require the output filename for use in the diagnostics
50  * created.  Save the address of the output filename pointer for this use.
51  */
52 static const char	**Name = 0;
53 static int		Phase = 0;
54 
55 uintptr_t
56 dbg_setup(const char *options, Dbg_desc *dbp, const char **name, int phase)
57 {
58 	if (Phase == 0)
59 		Phase = phase;
60 	else if (Phase != phase)
61 		return (0);
62 
63 	Name = name;
64 
65 	/*
66 	 * Call the debugging setup routine to initialize the mask and
67 	 * debug function array.
68 	 */
69 	return (Dbg_setup(options, dbp));
70 }
71 
72 /* PRINTFLIKE2 */
73 void
74 dbg_print(Lm_list *lml, const char *format, ...)
75 {
76 	static char	*prestr = 0;
77 	va_list		args;
78 
79 #if	defined(lint)
80 	/*
81 	 * The lml argument is only meaningful for diagnostics sent to ld.so.1.
82 	 * Supress the lint error by making a dummy assignment.
83 	 */
84 	lml = 0;
85 #endif
86 	/*
87 	 * Knock off any newline indicator to signify that a diagnostic has
88 	 * been processed.
89 	 */
90 	dbg_desc->d_extra &= ~DBG_E_STDNL;
91 
92 	if (DBG_ISSNAME()) {
93 		/*
94 		 * If the debugging options have requested each diagnostic line
95 		 * be prepended by a name create a prefix string.
96 		 */
97 		if ((prestr == 0) && *Name) {
98 			const char	*name, *cls;
99 			size_t		len;
100 
101 			/*
102 			 * Select the fullname or basename of the output file
103 			 * being created.
104 			 */
105 			if (DBG_ISFNAME())
106 				name = *Name;
107 			else {
108 				if ((name =
109 				    strrchr(*Name, '/')) == 0)
110 					name = *Name;
111 				else
112 					name++;
113 			}
114 			len = strlen(name) +
115 			    strlen(MSG_INTL(MSG_DBG_NAME_FMT)) + 1;
116 
117 			/*
118 			 * Add the output file class if required.
119 			 */
120 			if (DBG_ISCLASS()) {
121 #if	defined(_ELF64)
122 				len += MSG_DBG_CLS64_FMT_SIZE;
123 				cls = MSG_ORIG(MSG_DBG_CLS64_FMT);
124 #else
125 				len += MSG_DBG_CLS32_FMT_SIZE;
126 				cls = MSG_ORIG(MSG_DBG_CLS32_FMT);
127 #endif
128 			}
129 
130 			/*
131 			 * Allocate a string to build the prefix.
132 			 */
133 			if ((prestr = malloc(len)) == 0)
134 				prestr = (char *)MSG_INTL(MSG_DBG_DFLT_FMT);
135 			else {
136 				(void) snprintf(prestr, len,
137 				    MSG_INTL(MSG_DBG_NAME_FMT), name);
138 				if (DBG_ISCLASS())
139 					(void) strcat(prestr, cls);
140 			}
141 		}
142 		if (prestr)
143 			(void) fputs(prestr, stderr);
144 		else
145 			(void) fputs(MSG_INTL(MSG_DBG_AOUT_FMT), stderr);
146 	} else
147 		(void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), stderr);
148 
149 	va_start(args, format);
150 	(void) vfprintf(stderr, format, args);
151 	(void) fprintf(stderr, MSG_ORIG(MSG_STR_NL));
152 	va_end(args);
153 }
154