17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55aefb655Srie * Common Development and Distribution License (the "License").
65aefb655Srie * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
215aefb655Srie
227c478bd9Sstevel@tonic-gate /*
23*1007fd6fSAli Bahrami * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdio.h>
275aefb655Srie #include <stdarg.h>
28e23c41c9SAli Bahrami #include <errno.h>
295aefb655Srie #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <dlfcn.h>
315aefb655Srie #include <debug.h>
322017c965SRod Evans #include <conv.h>
335aefb655Srie #include "msg.h"
34*1007fd6fSAli Bahrami #include "_libld.h"
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate /*
375aefb655Srie * dbg_setup() can be called a number of times. The typical use through
385aefb655Srie * LD_OPTIONS, results in dbg_setup() being called as the first argument to
395aefb655Srie * ld(1). It's also possible to pass debugging tokens through the compiler,
405aefb655Srie * for example -Wl,-Dlibs -Wl-Ddetail, in which case multiple dbg_setup()
415aefb655Srie * calls are made.
425aefb655Srie *
435aefb655Srie * A distinction is also made between diagnostics being requested before any
445aefb655Srie * other ld(1) options are read, or whether the debugging options occur
455aefb655Srie * between other options on the command line. In the latter case, the
465aefb655Srie * debugging options can be used to isolate diagnostics around one or more
475aefb655Srie * input files. The "phase" argument allows us to select which phase of
485aefb655Srie * dbg_setup() processing we should isolate ourselves to.
495aefb655Srie *
505aefb655Srie * dbg_print() can require the output filename for use in the diagnostics
515aefb655Srie * created. Save the address of the output filename pointer for this use.
527c478bd9Sstevel@tonic-gate */
536b3ba5bdSAli Bahrami static const char **Name = NULL;
545aefb655Srie static int Phase = 0;
557c478bd9Sstevel@tonic-gate
56e23c41c9SAli Bahrami /* Debug file output state */
57e23c41c9SAli Bahrami static struct {
58e23c41c9SAli Bahrami FILE *fptr; /* File to send debug output */
59e23c41c9SAli Bahrami int close_needed; /* True if explicitly opened stream */
60e23c41c9SAli Bahrami } dbg_ofile = {
61e23c41c9SAli Bahrami stderr,
62e23c41c9SAli Bahrami 0
63e23c41c9SAli Bahrami };
64e23c41c9SAli Bahrami
65e23c41c9SAli Bahrami
66e23c41c9SAli Bahrami /*
67e23c41c9SAli Bahrami * If there is an explicitly opened debug file, close it and reset the state.
68e23c41c9SAli Bahrami */
69e23c41c9SAli Bahrami void
dbg_cleanup(void)70e23c41c9SAli Bahrami dbg_cleanup(void)
717c478bd9Sstevel@tonic-gate {
72e23c41c9SAli Bahrami if (dbg_ofile.close_needed) {
73e23c41c9SAli Bahrami (void) fclose(dbg_ofile.fptr);
74e23c41c9SAli Bahrami dbg_ofile.close_needed = 0;
75e23c41c9SAli Bahrami dbg_ofile.fptr = stderr;
76e23c41c9SAli Bahrami }
77e23c41c9SAli Bahrami }
78e23c41c9SAli Bahrami
79e23c41c9SAli Bahrami /*
80e23c41c9SAli Bahrami * Process debug tokens. Returns True (1) on success, and False (0)
81e23c41c9SAli Bahrami * on failure.
82e23c41c9SAli Bahrami */
83e23c41c9SAli Bahrami int
dbg_setup(Ofl_desc * ofl,const char * options,int phase)84e23c41c9SAli Bahrami dbg_setup(Ofl_desc *ofl, const char *options, int phase)
85e23c41c9SAli Bahrami {
86e23c41c9SAli Bahrami const char *ofile;
87e23c41c9SAli Bahrami
885aefb655Srie if (Phase == 0)
895aefb655Srie Phase = phase;
905aefb655Srie else if (Phase != phase)
91e23c41c9SAli Bahrami return (1);
927c478bd9Sstevel@tonic-gate
93e23c41c9SAli Bahrami Name = &ofl->ofl_name;
945aefb655Srie
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate * Call the debugging setup routine to initialize the mask and
977c478bd9Sstevel@tonic-gate * debug function array.
987c478bd9Sstevel@tonic-gate */
99e23c41c9SAli Bahrami if (Dbg_setup(DBG_CALLER_LD, options, dbg_desc, &ofile) == 0)
100e23c41c9SAli Bahrami return (0);
101e23c41c9SAli Bahrami
102e23c41c9SAli Bahrami /*
103e23c41c9SAli Bahrami * If output= token was used, close the old file if necessary
104e23c41c9SAli Bahrami * and open a new one if the file name is not NULL.
105e23c41c9SAli Bahrami */
106e23c41c9SAli Bahrami if (ofile) {
107e23c41c9SAli Bahrami dbg_cleanup();
108e23c41c9SAli Bahrami if (*ofile != '\0') {
109e23c41c9SAli Bahrami FILE *fptr = fopen(ofile, MSG_ORIG(MSG_DBG_FOPEN_MODE));
110e23c41c9SAli Bahrami if (fptr == NULL) {
111e23c41c9SAli Bahrami int err = errno;
112e23c41c9SAli Bahrami
113*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
114e23c41c9SAli Bahrami MSG_INTL(MSG_SYS_OPEN), ofile,
115e23c41c9SAli Bahrami strerror(err));
116e23c41c9SAli Bahrami return (0);
117e23c41c9SAli Bahrami } else {
118e23c41c9SAli Bahrami dbg_ofile.fptr = fptr;
119e23c41c9SAli Bahrami dbg_ofile.close_needed = 1;
120e23c41c9SAli Bahrami }
121e23c41c9SAli Bahrami }
122e23c41c9SAli Bahrami }
123e23c41c9SAli Bahrami
124e23c41c9SAli Bahrami /*
12569112eddSAli Bahrami * Now that the output file is established, identify the linker
12669112eddSAli Bahrami * package, and generate help output if the user specified the
12769112eddSAli Bahrami * debug help token.
128e23c41c9SAli Bahrami */
12969112eddSAli Bahrami Dbg_version();
130e23c41c9SAli Bahrami if (dbg_desc->d_extra & DBG_E_HELP)
131e23c41c9SAli Bahrami Dbg_help();
132e23c41c9SAli Bahrami
133e23c41c9SAli Bahrami return (1);
1345aefb655Srie }
1355aefb655Srie
1365aefb655Srie /* PRINTFLIKE2 */
1375aefb655Srie void
dbg_print(Lm_list * lml,const char * format,...)1385aefb655Srie dbg_print(Lm_list *lml, const char *format, ...)
1395aefb655Srie {
1406b3ba5bdSAli Bahrami static char *prestr = NULL;
1415aefb655Srie va_list args;
1425aefb655Srie
1435aefb655Srie #if defined(lint)
1445aefb655Srie /*
1455aefb655Srie * The lml argument is only meaningful for diagnostics sent to ld.so.1.
1465aefb655Srie * Supress the lint error by making a dummy assignment.
1475aefb655Srie */
1486b3ba5bdSAli Bahrami lml = NULL;
1495aefb655Srie #endif
1505aefb655Srie /*
1515aefb655Srie * Knock off any newline indicator to signify that a diagnostic has
1525aefb655Srie * been processed.
1535aefb655Srie */
1545aefb655Srie dbg_desc->d_extra &= ~DBG_E_STDNL;
1555aefb655Srie
1565aefb655Srie if (DBG_ISSNAME()) {
1575aefb655Srie /*
1585aefb655Srie * If the debugging options have requested each diagnostic line
1595aefb655Srie * be prepended by a name create a prefix string.
1605aefb655Srie */
1616b3ba5bdSAli Bahrami if ((prestr == NULL) && *Name) {
1625aefb655Srie const char *name, *cls;
1635aefb655Srie size_t len;
1645aefb655Srie
1655aefb655Srie /*
1665aefb655Srie * Select the fullname or basename of the output file
1675aefb655Srie * being created.
1685aefb655Srie */
1695aefb655Srie if (DBG_ISFNAME())
1705aefb655Srie name = *Name;
1715aefb655Srie else {
1725aefb655Srie if ((name =
1736b3ba5bdSAli Bahrami strrchr(*Name, '/')) == NULL)
1745aefb655Srie name = *Name;
1755aefb655Srie else
1765aefb655Srie name++;
1775aefb655Srie }
1785aefb655Srie len = strlen(name) +
1795aefb655Srie strlen(MSG_INTL(MSG_DBG_NAME_FMT)) + 1;
1805aefb655Srie
1815aefb655Srie /*
1825aefb655Srie * Add the output file class if required.
1835aefb655Srie */
1845aefb655Srie if (DBG_ISCLASS()) {
1855aefb655Srie #if defined(_ELF64)
1865aefb655Srie len += MSG_DBG_CLS64_FMT_SIZE;
1875aefb655Srie cls = MSG_ORIG(MSG_DBG_CLS64_FMT);
1885aefb655Srie #else
1895aefb655Srie len += MSG_DBG_CLS32_FMT_SIZE;
1905aefb655Srie cls = MSG_ORIG(MSG_DBG_CLS32_FMT);
1915aefb655Srie #endif
1925aefb655Srie }
1935aefb655Srie
1945aefb655Srie /*
1955aefb655Srie * Allocate a string to build the prefix.
1965aefb655Srie */
1976b3ba5bdSAli Bahrami if ((prestr = libld_malloc(len)) == NULL)
1985aefb655Srie prestr = (char *)MSG_INTL(MSG_DBG_DFLT_FMT);
1995aefb655Srie else {
2005aefb655Srie (void) snprintf(prestr, len,
2015aefb655Srie MSG_INTL(MSG_DBG_NAME_FMT), name);
2025aefb655Srie if (DBG_ISCLASS())
2035aefb655Srie (void) strcat(prestr, cls);
2045aefb655Srie }
2055aefb655Srie }
206e23c41c9SAli Bahrami (void) fputs(prestr ? prestr : MSG_INTL(MSG_DBG_AOUT_FMT),
207e23c41c9SAli Bahrami dbg_ofile.fptr);
2085aefb655Srie } else
209e23c41c9SAli Bahrami (void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), dbg_ofile.fptr);
2105aefb655Srie
2112017c965SRod Evans if (DBG_ISTIME()) {
2122017c965SRod Evans Conv_time_buf_t buf;
2132017c965SRod Evans struct timeval new;
2142017c965SRod Evans
2152017c965SRod Evans if (gettimeofday(&new, NULL) == 0) {
2162017c965SRod Evans if (DBG_ISTTIME())
2172017c965SRod Evans (void) fputs(conv_time(&DBG_TOTALTIME, &new,
2182017c965SRod Evans &buf), stderr);
2192017c965SRod Evans if (DBG_ISDTIME())
2202017c965SRod Evans (void) fputs(conv_time(&DBG_DELTATIME, &new,
2212017c965SRod Evans &buf), stderr);
2222017c965SRod Evans
2232017c965SRod Evans DBG_DELTATIME = new;
2242017c965SRod Evans }
2252017c965SRod Evans }
2262017c965SRod Evans
2275aefb655Srie va_start(args, format);
228e23c41c9SAli Bahrami (void) vfprintf(dbg_ofile.fptr, format, args);
229e23c41c9SAli Bahrami (void) fprintf(dbg_ofile.fptr, MSG_ORIG(MSG_STR_NL));
2305aefb655Srie va_end(args);
2317c478bd9Sstevel@tonic-gate }
232