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 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 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 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