10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51618Srie * Common Development and Distribution License (the "License").
61618Srie * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211618Srie
220Sstevel@tonic-gate /*
23*13074SAli.Bahrami@Oracle.COM * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdio.h>
271618Srie #include <stdarg.h>
289406SAli.Bahrami@Sun.COM #include <errno.h>
291618Srie #include <strings.h>
300Sstevel@tonic-gate #include <dlfcn.h>
311618Srie #include <debug.h>
329577SRod.Evans@Sun.COM #include <conv.h>
331618Srie #include "msg.h"
34*13074SAli.Bahrami@Oracle.COM #include "_libld.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate /*
371618Srie * dbg_setup() can be called a number of times. The typical use through
381618Srie * LD_OPTIONS, results in dbg_setup() being called as the first argument to
391618Srie * ld(1). It's also possible to pass debugging tokens through the compiler,
401618Srie * for example -Wl,-Dlibs -Wl-Ddetail, in which case multiple dbg_setup()
411618Srie * calls are made.
421618Srie *
431618Srie * A distinction is also made between diagnostics being requested before any
441618Srie * other ld(1) options are read, or whether the debugging options occur
451618Srie * between other options on the command line. In the latter case, the
461618Srie * debugging options can be used to isolate diagnostics around one or more
471618Srie * input files. The "phase" argument allows us to select which phase of
481618Srie * dbg_setup() processing we should isolate ourselves to.
491618Srie *
501618Srie * dbg_print() can require the output filename for use in the diagnostics
511618Srie * created. Save the address of the output filename pointer for this use.
520Sstevel@tonic-gate */
538608SAli.Bahrami@Sun.COM static const char **Name = NULL;
541618Srie static int Phase = 0;
550Sstevel@tonic-gate
569406SAli.Bahrami@Sun.COM /* Debug file output state */
579406SAli.Bahrami@Sun.COM static struct {
589406SAli.Bahrami@Sun.COM FILE *fptr; /* File to send debug output */
599406SAli.Bahrami@Sun.COM int close_needed; /* True if explicitly opened stream */
609406SAli.Bahrami@Sun.COM } dbg_ofile = {
619406SAli.Bahrami@Sun.COM stderr,
629406SAli.Bahrami@Sun.COM 0
639406SAli.Bahrami@Sun.COM };
649406SAli.Bahrami@Sun.COM
659406SAli.Bahrami@Sun.COM
669406SAli.Bahrami@Sun.COM /*
679406SAli.Bahrami@Sun.COM * If there is an explicitly opened debug file, close it and reset the state.
689406SAli.Bahrami@Sun.COM */
699406SAli.Bahrami@Sun.COM void
dbg_cleanup(void)709406SAli.Bahrami@Sun.COM dbg_cleanup(void)
710Sstevel@tonic-gate {
729406SAli.Bahrami@Sun.COM if (dbg_ofile.close_needed) {
739406SAli.Bahrami@Sun.COM (void) fclose(dbg_ofile.fptr);
749406SAli.Bahrami@Sun.COM dbg_ofile.close_needed = 0;
759406SAli.Bahrami@Sun.COM dbg_ofile.fptr = stderr;
769406SAli.Bahrami@Sun.COM }
779406SAli.Bahrami@Sun.COM }
789406SAli.Bahrami@Sun.COM
799406SAli.Bahrami@Sun.COM /*
809406SAli.Bahrami@Sun.COM * Process debug tokens. Returns True (1) on success, and False (0)
819406SAli.Bahrami@Sun.COM * on failure.
829406SAli.Bahrami@Sun.COM */
839406SAli.Bahrami@Sun.COM int
dbg_setup(Ofl_desc * ofl,const char * options,int phase)849406SAli.Bahrami@Sun.COM dbg_setup(Ofl_desc *ofl, const char *options, int phase)
859406SAli.Bahrami@Sun.COM {
869406SAli.Bahrami@Sun.COM const char *ofile;
879406SAli.Bahrami@Sun.COM
881618Srie if (Phase == 0)
891618Srie Phase = phase;
901618Srie else if (Phase != phase)
919406SAli.Bahrami@Sun.COM return (1);
920Sstevel@tonic-gate
939406SAli.Bahrami@Sun.COM Name = &ofl->ofl_name;
941618Srie
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Call the debugging setup routine to initialize the mask and
970Sstevel@tonic-gate * debug function array.
980Sstevel@tonic-gate */
999406SAli.Bahrami@Sun.COM if (Dbg_setup(DBG_CALLER_LD, options, dbg_desc, &ofile) == 0)
1009406SAli.Bahrami@Sun.COM return (0);
1019406SAli.Bahrami@Sun.COM
1029406SAli.Bahrami@Sun.COM /*
1039406SAli.Bahrami@Sun.COM * If output= token was used, close the old file if necessary
1049406SAli.Bahrami@Sun.COM * and open a new one if the file name is not NULL.
1059406SAli.Bahrami@Sun.COM */
1069406SAli.Bahrami@Sun.COM if (ofile) {
1079406SAli.Bahrami@Sun.COM dbg_cleanup();
1089406SAli.Bahrami@Sun.COM if (*ofile != '\0') {
1099406SAli.Bahrami@Sun.COM FILE *fptr = fopen(ofile, MSG_ORIG(MSG_DBG_FOPEN_MODE));
1109406SAli.Bahrami@Sun.COM if (fptr == NULL) {
1119406SAli.Bahrami@Sun.COM int err = errno;
1129406SAli.Bahrami@Sun.COM
113*13074SAli.Bahrami@Oracle.COM ld_eprintf(ofl, ERR_FATAL,
1149406SAli.Bahrami@Sun.COM MSG_INTL(MSG_SYS_OPEN), ofile,
1159406SAli.Bahrami@Sun.COM strerror(err));
1169406SAli.Bahrami@Sun.COM return (0);
1179406SAli.Bahrami@Sun.COM } else {
1189406SAli.Bahrami@Sun.COM dbg_ofile.fptr = fptr;
1199406SAli.Bahrami@Sun.COM dbg_ofile.close_needed = 1;
1209406SAli.Bahrami@Sun.COM }
1219406SAli.Bahrami@Sun.COM }
1229406SAli.Bahrami@Sun.COM }
1239406SAli.Bahrami@Sun.COM
1249406SAli.Bahrami@Sun.COM /*
12511734SAli.Bahrami@Sun.COM * Now that the output file is established, identify the linker
12611734SAli.Bahrami@Sun.COM * package, and generate help output if the user specified the
12711734SAli.Bahrami@Sun.COM * debug help token.
1289406SAli.Bahrami@Sun.COM */
12911734SAli.Bahrami@Sun.COM Dbg_version();
1309406SAli.Bahrami@Sun.COM if (dbg_desc->d_extra & DBG_E_HELP)
1319406SAli.Bahrami@Sun.COM Dbg_help();
1329406SAli.Bahrami@Sun.COM
1339406SAli.Bahrami@Sun.COM return (1);
1340Sstevel@tonic-gate }
1351618Srie
1361618Srie /* PRINTFLIKE2 */
1371618Srie void
dbg_print(Lm_list * lml,const char * format,...)1381618Srie dbg_print(Lm_list *lml, const char *format, ...)
1391618Srie {
1408608SAli.Bahrami@Sun.COM static char *prestr = NULL;
1411618Srie va_list args;
1421618Srie
1431618Srie #if defined(lint)
1441618Srie /*
1451618Srie * The lml argument is only meaningful for diagnostics sent to ld.so.1.
1461618Srie * Supress the lint error by making a dummy assignment.
1471618Srie */
1488608SAli.Bahrami@Sun.COM lml = NULL;
1491618Srie #endif
1501618Srie /*
1511618Srie * Knock off any newline indicator to signify that a diagnostic has
1521618Srie * been processed.
1531618Srie */
1541618Srie dbg_desc->d_extra &= ~DBG_E_STDNL;
1551618Srie
1561618Srie if (DBG_ISSNAME()) {
1571618Srie /*
1581618Srie * If the debugging options have requested each diagnostic line
1591618Srie * be prepended by a name create a prefix string.
1601618Srie */
1618608SAli.Bahrami@Sun.COM if ((prestr == NULL) && *Name) {
1621618Srie const char *name, *cls;
1631618Srie size_t len;
1641618Srie
1651618Srie /*
1661618Srie * Select the fullname or basename of the output file
1671618Srie * being created.
1681618Srie */
1691618Srie if (DBG_ISFNAME())
1701618Srie name = *Name;
1711618Srie else {
1721618Srie if ((name =
1738608SAli.Bahrami@Sun.COM strrchr(*Name, '/')) == NULL)
1741618Srie name = *Name;
1751618Srie else
1761618Srie name++;
1771618Srie }
1781618Srie len = strlen(name) +
1791618Srie strlen(MSG_INTL(MSG_DBG_NAME_FMT)) + 1;
1801618Srie
1811618Srie /*
1821618Srie * Add the output file class if required.
1831618Srie */
1841618Srie if (DBG_ISCLASS()) {
1851618Srie #if defined(_ELF64)
1861618Srie len += MSG_DBG_CLS64_FMT_SIZE;
1871618Srie cls = MSG_ORIG(MSG_DBG_CLS64_FMT);
1881618Srie #else
1891618Srie len += MSG_DBG_CLS32_FMT_SIZE;
1901618Srie cls = MSG_ORIG(MSG_DBG_CLS32_FMT);
1911618Srie #endif
1921618Srie }
1931618Srie
1941618Srie /*
1951618Srie * Allocate a string to build the prefix.
1961618Srie */
1978608SAli.Bahrami@Sun.COM if ((prestr = libld_malloc(len)) == NULL)
1981618Srie prestr = (char *)MSG_INTL(MSG_DBG_DFLT_FMT);
1991618Srie else {
2001618Srie (void) snprintf(prestr, len,
2011618Srie MSG_INTL(MSG_DBG_NAME_FMT), name);
2021618Srie if (DBG_ISCLASS())
2031618Srie (void) strcat(prestr, cls);
2041618Srie }
2051618Srie }
2069406SAli.Bahrami@Sun.COM (void) fputs(prestr ? prestr : MSG_INTL(MSG_DBG_AOUT_FMT),
2079406SAli.Bahrami@Sun.COM dbg_ofile.fptr);
2081618Srie } else
2099406SAli.Bahrami@Sun.COM (void) fputs(MSG_INTL(MSG_DBG_DFLT_FMT), dbg_ofile.fptr);
2101618Srie
2119577SRod.Evans@Sun.COM if (DBG_ISTIME()) {
2129577SRod.Evans@Sun.COM Conv_time_buf_t buf;
2139577SRod.Evans@Sun.COM struct timeval new;
2149577SRod.Evans@Sun.COM
2159577SRod.Evans@Sun.COM if (gettimeofday(&new, NULL) == 0) {
2169577SRod.Evans@Sun.COM if (DBG_ISTTIME())
2179577SRod.Evans@Sun.COM (void) fputs(conv_time(&DBG_TOTALTIME, &new,
2189577SRod.Evans@Sun.COM &buf), stderr);
2199577SRod.Evans@Sun.COM if (DBG_ISDTIME())
2209577SRod.Evans@Sun.COM (void) fputs(conv_time(&DBG_DELTATIME, &new,
2219577SRod.Evans@Sun.COM &buf), stderr);
2229577SRod.Evans@Sun.COM
2239577SRod.Evans@Sun.COM DBG_DELTATIME = new;
2249577SRod.Evans@Sun.COM }
2259577SRod.Evans@Sun.COM }
2269577SRod.Evans@Sun.COM
2271618Srie va_start(args, format);
2289406SAli.Bahrami@Sun.COM (void) vfprintf(dbg_ofile.fptr, format, args);
2299406SAli.Bahrami@Sun.COM (void) fprintf(dbg_ofile.fptr, MSG_ORIG(MSG_STR_NL));
2301618Srie va_end(args);
2311618Srie }
232