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 /* 23cce0e03bSab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*7257d1b4Sraf #pragma ident "%Z%%M% %I% %E% SMI" 285aefb655Srie 29*7257d1b4Sraf #include <libintl.h> 30*7257d1b4Sraf #include <sys/varargs.h> 31*7257d1b4Sraf #include <stdio.h> 32*7257d1b4Sraf #include <string.h> 33*7257d1b4Sraf #include <stdlib.h> 34*7257d1b4Sraf #include <alist.h> 35*7257d1b4Sraf #include <debug.h> 36*7257d1b4Sraf #include <_debug.h> 37*7257d1b4Sraf #include <msg.h> 387c478bd9Sstevel@tonic-gate 395aefb655Srie /* 405aefb655Srie * Define a debug descriptor. Note, although this provides the default 415aefb655Srie * definition to which most users bind, ld.so.1 must provide its own definition, 425aefb655Srie * and thus interposition is expected. This item should be defined NODIRECT. 435aefb655Srie */ 445aefb655Srie static Dbg_desc _dbg_desc = { 0, 0, 0 }; 455aefb655Srie Dbg_desc *dbg_desc = &_dbg_desc; 467c478bd9Sstevel@tonic-gate 475aefb655Srie int _Dbg_cnt = 0; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 505aefb655Srie * Debugging initialization and processing. The dbg_options[] array defines 517c478bd9Sstevel@tonic-gate * a set of option strings that can be specified using the -D flag or from an 525aefb655Srie * environment variable. For each option, a class is enabled in the d_class 535aefb655Srie * bit mask, or an extra flag is enabled in the d_extra bit mask. 547c478bd9Sstevel@tonic-gate */ 555aefb655Srie DBG_options _Dbg_options[] = { 565aefb655Srie {MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL}, 575aefb655Srie {MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG}, 585aefb655Srie {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, 595aefb655Srie {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, 605aefb655Srie {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, 615aefb655Srie {MSG_ORIG(MSG_TOK_LMID), 0, DBG_E_LMID}, 625aefb655Srie 635aefb655Srie {MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL, 0}, 645aefb655Srie {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, 655aefb655Srie {MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0}, 665aefb655Srie {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, 675aefb655Srie {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, 685aefb655Srie {MSG_ORIG(MSG_TOK_FILES), DBG_C_FILES, 0}, 695aefb655Srie {MSG_ORIG(MSG_TOK_HELP), DBG_C_HELP, 0}, 705aefb655Srie {MSG_ORIG(MSG_TOK_LIBS), DBG_C_LIBS, 0}, 715aefb655Srie {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, 725aefb655Srie {MSG_ORIG(MSG_TOK_RELOC), DBG_C_RELOC, 0}, 735aefb655Srie {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, 745aefb655Srie {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, 755aefb655Srie {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, 765aefb655Srie {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_C_SYMBOLS, 0}, 775aefb655Srie {MSG_ORIG(MSG_TOK_TLS), DBG_C_TLS, 0}, 785aefb655Srie {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, 795aefb655Srie {MSG_ORIG(MSG_TOK_VERSIONS), DBG_C_VERSIONS, 0}, 805aefb655Srie {MSG_ORIG(MSG_TOK_GOT), DBG_C_GOT, 0}, 815aefb655Srie {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, 825aefb655Srie {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, 835aefb655Srie {MSG_ORIG(MSG_TOK_STATS), DBG_C_STATS, 0}, 845aefb655Srie {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, 857c478bd9Sstevel@tonic-gate #ifdef DEMANGLE 865aefb655Srie {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, 877c478bd9Sstevel@tonic-gate #endif 885aefb655Srie {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, 895aefb655Srie {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, 907c478bd9Sstevel@tonic-gate {NULL, NULL}, 917c478bd9Sstevel@tonic-gate }; 927c478bd9Sstevel@tonic-gate 935aefb655Srie /* 945aefb655Srie * Tokens may also define identifiers for diagnostics. Presently, only ld.so.1 955aefb655Srie * uses these strings to identify, or isolate its output to selected link-map 965aefb655Srie * lists. See ld.so.1:dbg_print(). 975aefb655Srie */ 985aefb655Srie const char *_Dbg_strs[] = { 995aefb655Srie MSG_ORIG(MSG_TOK_BASE), MSG_ORIG(MSG_TOK_LDSO), 1005aefb655Srie MSG_ORIG(MSG_TOK_NEWLM), NULL 1015aefb655Srie }; 1025aefb655Srie 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Provide a debugging usage message 1057c478bd9Sstevel@tonic-gate */ 1065aefb655Srie void 1075aefb655Srie Dbg_usage() 1087c478bd9Sstevel@tonic-gate { 1095aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1105aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_A)); 1115aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_B)); 1125aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_C)); 1135aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_D)); 1145aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_E)); 1155aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_F)); 1165aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_G)); 1175aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_H)); 1185aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_I)); 1195aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1205aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_J)); 1215aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_K)); 1225aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_L)); 1235aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_M)); 1245aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1255aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_N)); 1265aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_O)); 1275aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1285aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_P)); 1295aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_Q)); 1305aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_R)); 1315aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_S)); 1325aefb655Srie 1335aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1345aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_A)); 1355aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_B)); 1365aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_C)); 1375aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_D)); 1385aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_E)); 1395aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_F)); 1405aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_G)); 1415aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_H)); 1425aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1435aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_I)); 1445aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1455aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_J)); 1465aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_K)); 1475aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1485aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_L)); 1495aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1505aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_M)); 1515aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_N)); 1525aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_O)); 1535aefb655Srie 1545aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1555aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1565aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_ARGS)); 1575aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_AUDIT)); 1585aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BASIC)); 1595aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BINDINGS)); 1605aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BINDINGS_2)); 1615aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_CAP)); 1625aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_DETAIL)); 1637c478bd9Sstevel@tonic-gate #ifdef DEMANGLE 1645aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_DEMANGLE)); 1657c478bd9Sstevel@tonic-gate #endif 1665aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_ENTRY)); 1675aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_FILES)); 1685aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_GOT)); 1695aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_HELP)); 1705aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_INIT)); 1715aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LIBS)); 1725aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LIBS_2)); 1735aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LMID)); 1745aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LONG)); 1755aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_MAP)); 1765aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_MOVE)); 1775aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RELOC)); 1785aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SECTIONS)); 1795aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS)); 1805aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS_2)); 1815aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STATS)); 1825aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STRTAB)); 1835aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STRTAB_2)); 1845aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SUPPORT)); 1855aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS)); 1865aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS_2)); 1875aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_TLS)); 1885aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNUSED)); 1895aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNUSED_2)); 1905aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_VERSIONS)); 1915aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 1925aefb655Srie } 1935aefb655Srie 1945aefb655Srie /* 1955aefb655Srie * Messaging support - funnel everything through dgettext() as this provides 1965aefb655Srie * the real binding to libc. 1975aefb655Srie */ 1985aefb655Srie const char * 1995aefb655Srie _liblddbg_msg(Msg mid) 2005aefb655Srie { 2015aefb655Srie return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * Validate and enable the appropriate debugging classes. 2067c478bd9Sstevel@tonic-gate */ 2075aefb655Srie uintptr_t 2085aefb655Srie Dbg_setup(const char *string, Dbg_desc *dbp) 2097c478bd9Sstevel@tonic-gate { 2105aefb655Srie char *name, *_name; /* buffer in which to perform */ 2115aefb655Srie /* strtok_r() operations. */ 2127c478bd9Sstevel@tonic-gate char *lasts; 2137c478bd9Sstevel@tonic-gate const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if ((_name = (char *)malloc(strlen(string) + 1)) == 0) 2165aefb655Srie return (S_ERROR); 2177c478bd9Sstevel@tonic-gate (void) strcpy(_name, string); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * The token should be of the form "-Dtok,tok,tok,...". Separate the 2217c478bd9Sstevel@tonic-gate * pieces and build up the appropriate mask, unrecognized options are 2227c478bd9Sstevel@tonic-gate * flagged. 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 2257c478bd9Sstevel@tonic-gate do { 2265aefb655Srie DBG_options *opt; 2275aefb655Srie const char *str; 2285aefb655Srie Boolean set, found = FALSE; 2295aefb655Srie int ndx = 0; 2305aefb655Srie 2317c478bd9Sstevel@tonic-gate if (name[0] == '!') { 2327c478bd9Sstevel@tonic-gate set = FALSE; 2337c478bd9Sstevel@tonic-gate name++; 2345aefb655Srie } else 2355aefb655Srie set = TRUE; 2365aefb655Srie 2375aefb655Srie /* 2385aefb655Srie * First, determine if the token represents a class or 2395aefb655Srie * extra. 2405aefb655Srie */ 2415aefb655Srie for (opt = _Dbg_options; opt->o_name != NULL; opt++) { 2425aefb655Srie if (strcmp(name, opt->o_name) != 0) 2435aefb655Srie continue; 2445aefb655Srie 2455aefb655Srie if (set == TRUE) { 246cce0e03bSab if (opt->o_class) 247cce0e03bSab dbp->d_class |= opt->o_class; 248cce0e03bSab if (opt->o_extra) 249cce0e03bSab dbp->d_extra |= opt->o_extra; 2505aefb655Srie } else { 251cce0e03bSab if (opt->o_class) 252cce0e03bSab dbp->d_class &= ~(opt->o_class); 253cce0e03bSab if (opt->o_extra) 254cce0e03bSab dbp->d_extra &= ~(opt->o_extra); 2555aefb655Srie } 2565aefb655Srie found = TRUE; 2575aefb655Srie break; 2587c478bd9Sstevel@tonic-gate } 2595aefb655Srie if (found == TRUE) 2605aefb655Srie continue; 2615aefb655Srie 2625aefb655Srie /* 2635aefb655Srie * Second, determine if the token represents a known 2645aefb655Srie * diagnostic identifier. Note, newlm identifiers are 2655aefb655Srie * typically followed by a numeric id, for example 2665aefb655Srie * newlm1, newlm2 ... Thus we only compare the 2675aefb655Srie * initial text of the string. 2685aefb655Srie */ 2695aefb655Srie while ((str = _Dbg_strs[ndx++]) != NULL) { 2705aefb655Srie char *tup; 2715aefb655Srie 2725aefb655Srie if (strncmp(name, str, strlen(str)) != 0) 2735aefb655Srie continue; 2745aefb655Srie 2755aefb655Srie /* 2765aefb655Srie * Translate lmid identifier to uppercase. 2775aefb655Srie */ 2785aefb655Srie for (tup = name; *tup; tup++) { 2795aefb655Srie if ((*tup >= 'a') && (*tup <= 'z')) 2805aefb655Srie *tup = *tup - ('a' - 'A'); 2817c478bd9Sstevel@tonic-gate } 2825aefb655Srie 2835aefb655Srie /* 2845aefb655Srie * Save this lmid. The whole token buffer has 2855aefb655Srie * been reallocated, so these names will remain 2865aefb655Srie * once this routine returns. 2875aefb655Srie */ 288cce0e03bSab if (aplist_append(&dbp->d_list, name, 289cce0e03bSab AL_CNT_DEBUG) == 0) 2905aefb655Srie return (S_ERROR); 2915aefb655Srie 2925aefb655Srie found = TRUE; 2935aefb655Srie break; 2947c478bd9Sstevel@tonic-gate } 2955aefb655Srie 2967c478bd9Sstevel@tonic-gate if (found == FALSE) 2975aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); 2985aefb655Srie 2997c478bd9Sstevel@tonic-gate } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * If the debug help option was specified dump a usage message. If 3045aefb655Srie * this is the only debug class, return an indication that the user 3057c478bd9Sstevel@tonic-gate * should exit. 3067c478bd9Sstevel@tonic-gate */ 3075aefb655Srie if ((_Dbg_cnt++ == 0) && (dbp->d_class & DBG_C_HELP)) { 3085aefb655Srie Dbg_usage(); 3095aefb655Srie if (dbp->d_class == DBG_C_HELP) 3105aefb655Srie return (0); 3117c478bd9Sstevel@tonic-gate } 3125aefb655Srie return (1); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* 3165aefb655Srie * Define our own printing routine. This provides a basic fallback, as ld(1) 3175aefb655Srie * and ld.so.1(1) provide their own routines that augment their diagnostic 3185aefb655Srie * output, and direct the output to stderr. This item should be defined 3195aefb655Srie * NODIRECT. 3207c478bd9Sstevel@tonic-gate */ 3215aefb655Srie /* PRINTFLIKE2 */ 3227c478bd9Sstevel@tonic-gate void 3235aefb655Srie dbg_print(Lm_list *lml, const char *format, ...) 3247c478bd9Sstevel@tonic-gate { 3255aefb655Srie va_list ap; 3267c478bd9Sstevel@tonic-gate 3275aefb655Srie #if defined(lint) 3285aefb655Srie /* 3295aefb655Srie * The lml argument is only meaningful for diagnostics sent to ld.so.1. 3305aefb655Srie * Supress the lint error by making a dummy assignment. 3315aefb655Srie */ 3325aefb655Srie lml = 0; 3335aefb655Srie #endif 3345aefb655Srie va_start(ap, format); 3355aefb655Srie (void) vprintf(format, ap); 3365aefb655Srie (void) printf(MSG_ORIG(MSG_STR_NL)); 3375aefb655Srie va_end(ap); 3387c478bd9Sstevel@tonic-gate } 339