xref: /onnv-gate/usr/src/cmd/sgs/libld/common/debug.c (revision 13074:787bf65954d0)
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