dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / libld / common / debug.c
blob246535927f29bc87ad861faf269a09e7050162cc
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #include <strings.h>
30 #include <dlfcn.h>
31 #include <debug.h>
32 #include <conv.h>
33 #include "msg.h"
34 #include "_libld.h"
37 * dbg_setup() can be called a number of times. The typical use through
38 * LD_OPTIONS, results in dbg_setup() being called as the first argument to
39 * ld(1). It's also possible to pass debugging tokens through the compiler,
40 * for example -Wl,-Dlibs -Wl-Ddetail, in which case multiple dbg_setup()
41 * calls are made.
43 * A distinction is also made between diagnostics being requested before any
44 * other ld(1) options are read, or whether the debugging options occur
45 * between other options on the command line. In the latter case, the
46 * debugging options can be used to isolate diagnostics around one or more
47 * input files. The "phase" argument allows us to select which phase of
48 * dbg_setup() processing we should isolate ourselves to.
50 * dbg_print() can require the output filename for use in the diagnostics
51 * created. Save the address of the output filename pointer for this use.
53 static const char **Name = NULL;
54 static int Phase = 0;
56 /* Debug file output state */
57 static struct {
58 FILE *fptr; /* File to send debug output */
59 int close_needed; /* True if explicitly opened stream */
60 } dbg_ofile;
64 * If there is an explicitly opened debug file, close it and reset the state.
66 void
67 dbg_cleanup(void)
69 if (dbg_ofile.close_needed) {
70 (void) fclose(dbg_ofile.fptr);
71 dbg_ofile.close_needed = 0;
72 dbg_ofile.fptr = stderr;
77 * Process debug tokens. Returns True (1) on success, and False (0)
78 * on failure.
80 int
81 dbg_setup(Ofl_desc *ofl, const char *options, int phase)
83 const char *ofile;
85 if (Phase == 0)
86 Phase = phase;
87 else if (Phase != phase)
88 return (1);
90 Name = &ofl->ofl_name;
93 * Call the debugging setup routine to initialize the mask and
94 * debug function array.
96 if (Dbg_setup(DBG_CALLER_LD, options, dbg_desc, &ofile) == 0)
97 return (0);
100 * If output= token was used, close the old file if necessary
101 * and open a new one if the file name is not NULL.
103 if (ofile) {
104 dbg_cleanup();
105 if (*ofile != '\0') {
106 FILE *fptr = fopen(ofile, MSG_ORIG(MSG_DBG_FOPEN_MODE));
107 if (fptr == NULL) {
108 int err = errno;
110 ld_eprintf(ofl, ERR_FATAL,
111 MSG_INTL(MSG_SYS_OPEN), ofile,
112 strerror(err));
113 return (0);
114 } else {
115 dbg_ofile.fptr = fptr;
116 dbg_ofile.close_needed = 1;
122 * Now that the output file is established, identify the linker
123 * package, and generate help output if the user specified the
124 * debug help token.
126 Dbg_version();
127 if (dbg_desc->d_extra & DBG_E_HELP)
128 Dbg_help();
130 return (1);
133 /* PRINTFLIKE2 */
134 void
135 dbg_print(Lm_list *lml, const char *format, ...)
137 static char *prestr = NULL;
138 va_list args;
140 if (dbg_ofile.fptr == NULL)
141 dbg_ofile.fptr = stderr;
144 * Knock off any newline indicator to signify that a diagnostic has
145 * been processed.
147 dbg_desc->d_extra &= ~DBG_E_STDNL;
149 if (DBG_ISSNAME()) {
151 * If the debugging options have requested each diagnostic line
152 * be prepended by a name create a prefix string.
154 if ((prestr == NULL) && *Name) {
155 const char *name, *cls;
156 size_t len;
159 * Select the fullname or basename of the output file
160 * being created.
162 if (DBG_ISFNAME())
163 name = *Name;
164 else {
165 if ((name =
166 strrchr(*Name, '/')) == NULL)
167 name = *Name;
168 else
169 name++;
171 len = strlen(name) +
172 strlen(MSG_INTL(MSG_DBG_NAME_FMT)) + 1;
175 * Add the output file class if required.
177 if (DBG_ISCLASS()) {
178 #if defined(_ELF64)
179 len += MSG_DBG_CLS64_FMT_SIZE;
180 cls = MSG_ORIG(MSG_DBG_CLS64_FMT);
181 #else
182 len += MSG_DBG_CLS32_FMT_SIZE;
183 cls = MSG_ORIG(MSG_DBG_CLS32_FMT);
184 #endif
188 * Allocate a string to build the prefix.
190 if ((prestr = libld_malloc(len)) == NULL)
191 prestr = (char *)MSG_INTL(MSG_DBG_DFLT_FMT);
192 else {
193 (void) snprintf(prestr, len,
194 MSG_INTL(MSG_DBG_NAME_FMT), name);
195 if (DBG_ISCLASS())
196 (void) strcat(prestr, cls);
199 (void) fputs(prestr ? prestr : MSG_INTL(MSG_DBG_AOUT_FMT),
200 dbg_ofile.fptr);
201 } else
202 (void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), dbg_ofile.fptr);
204 if (DBG_ISTIME()) {
205 Conv_time_buf_t buf;
206 struct timeval new;
208 if (gettimeofday(&new, NULL) == 0) {
209 if (DBG_ISTTIME())
210 (void) fputs(conv_time(&DBG_TOTALTIME, &new,
211 &buf), stderr);
212 if (DBG_ISDTIME())
213 (void) fputs(conv_time(&DBG_DELTATIME, &new,
214 &buf), stderr);
216 DBG_DELTATIME = new;
220 va_start(args, format);
221 (void) vfprintf(dbg_ofile.fptr, format, args);
222 (void) fprintf(dbg_ofile.fptr, MSG_ORIG(MSG_STR_NL));
223 va_end(args);