Home | History | Annotate | Download | only in os
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <sys/types.h>
     29 #include <sys/cmn_err.h>
     30 #include <sys/modctl.h>
     31 #include <sys/kobj.h>
     32 #include <sys/kobj_impl.h>
     33 #include <sys/promif.h>
     34 #include <sys/promimpl.h>
     35 #include <sys/reboot.h>
     36 #include <sys/bootconf.h>
     37 #include <sys/systm.h>		/* strstr */
     38 #include <sys/machsystm.h>	/* obpdebug */
     39 
     40 #define	FDEBUGFILE	"misc/forthdebug"
     41 #define	INSTALL_DBP	"kdbg-words dbp-install previous"
     42 #define	SYMBOL_END	"END OF SYMBOL"
     43 
     44 #ifdef DEBUG
     45 static int forthdebug	= 1;
     46 #else
     47 static int forthdebug	= 0;
     48 #endif /* DEBUG */
     49 
     50 static int forthdebug_dbp = 0;
     51 int forthdebug_supported = 1;
     52 int modreloc_flag = KOBJ_RELOCATED;
     53 
     54 /*
     55  * basic_sym[] holds all essential symbols the symbol lookup
     56  * service requires. Forthdebug stub names appears in forthdebug
     57  * as place holders. They are replaced with the value of corresponding
     58  * kernel variables. For example, "modules-val-here" in forthdebug
     59  * is replaced with the address of "modules" variable.
     60  *
     61  * To improve performance, we mandate the records be in the same
     62  * sequence they appear in forthdebug, i.e "modules-val-here" is
     63  * ahead of "primaries-v-here" in misc/forthdebug.
     64  *
     65  * The last record must be all 0 to indicate end of the array.
     66  */
     67 static char *basic_sym[] = {
     68 	/* kernel variable */	/* forthdebug stub name - must be 16 chars */
     69 	"modules",		"modules-val-here",
     70 	"primaries",		"primaries-v-here",
     71 	"modreloc_flag",	"modreloc-flagval",
     72 	0,			0
     73 };
     74 
     75 static void fdbp_hook() {} /* null function for defer breakpoint operation */
     76 
     77 /*ARGSUSED*/
     78 static void fdbp_snoop(unsigned int i, struct modctl *modctl_p)
     79 {
     80 	promif_preprom();
     81 	fdbp_hook();
     82 	promif_postprom();
     83 }
     84 
     85 static kobj_notify_list_t knl_load = {
     86 	fdbp_snoop, KOBJ_NOTIFY_MODLOADED, 0, 0
     87 };
     88 
     89 static kobj_notify_list_t knl_unload = {
     90 	fdbp_snoop, KOBJ_NOTIFY_MODUNLOADING, 0, 0
     91 };
     92 
     93 void
     94 forthdebug_init(void)
     95 {
     96 	char *fth_buf, *buf_p;
     97 	ulong_t modsym;
     98 	int i, sz;
     99 	uint64_t fsz;
    100 	struct _buf *file;
    101 
    102 	if (!forthdebug_supported) {
    103 		(void) modload("misc", "obpsym");
    104 		return;
    105 	}
    106 
    107 	forthdebug_dbp |= boothowto & RB_FORTHDEBUGDBP;
    108 	forthdebug |= (boothowto & RB_FORTHDEBUG) | forthdebug_dbp;
    109 
    110 	file = kobj_open_path(FDEBUGFILE, 1, 1);
    111 	if (file == (struct _buf *)-1) {
    112 		cmn_err(CE_CONT, "Can't open %s\n", FDEBUGFILE);
    113 		return;
    114 	}
    115 
    116 	i = kobj_get_filesize(file, &fsz);
    117 	if (i || !fsz) {
    118 		cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n",
    119 		    FDEBUGFILE, i, (long long)fsz);
    120 		goto err_stat;
    121 	}
    122 
    123 	fth_buf = (char *)kobj_zalloc(fsz + 1, KM_SLEEP);
    124 	sz = kobj_read_file(file, fth_buf, fsz, 0); /* entire file */
    125 	if (sz < 0) {
    126 		cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE);
    127 		goto done;
    128 	}
    129 	ASSERT(fsz == sz);
    130 	fth_buf[sz] = 0;
    131 
    132 	/* resolve all essential symbols in basic_sym[] */
    133 	for (i = 0; basic_sym[i]; i += 2) {
    134 		buf_p = strstr(fth_buf, basic_sym[i + 1]);
    135 		modsym = kobj_getsymvalue(basic_sym[i], 0);
    136 		if (buf_p && modsym) {
    137 			(void) sprintf(buf_p, "%16p", (void *)modsym);
    138 			buf_p += 16;
    139 			*buf_p++ = ' ';	/* erase null char by sprintf */
    140 		} else {
    141 			cmn_err(CE_CONT,
    142 			    "forthdebug_init: No %s symbol(%p,%p), aborted\n",
    143 			    basic_sym[i], (void *)buf_p, (void *)modsym);
    144 			goto done;
    145 		}
    146 	}
    147 	if (!forthdebug) {	/* symbol lookup services only */
    148 		if (!(buf_p = strstr(fth_buf, SYMBOL_END))) {
    149 			cmn_err(CE_CONT, "No %s in forthdebug\n", SYMBOL_END);
    150 			goto done;
    151 		}
    152 		*buf_p = '\0';
    153 #ifdef DEBUG
    154 		cmn_err(CE_CONT, "symbol lookup service (%ld bytes)\n",
    155 		    (long)(buf_p - fth_buf));
    156 #endif /* DEBUG */
    157 		prom_interpret(fth_buf, 0, 0, 0, 0, 0);
    158 		goto done;
    159 	}
    160 
    161 	cmn_err(CE_CONT, "%s (%d bytes) ", FDEBUGFILE, sz);
    162 	prom_interpret(fth_buf, 0, 0, 0, 0, 0);
    163 	cmn_err(CE_CONT, "loaded\n");
    164 	obpdebug = 1;	/* backward compatibility */
    165 
    166 	if (forthdebug_dbp) {
    167 #ifdef NO_KOBJ_NOTIFY
    168 		modsym = kobj_getsymvalue("kobj_notify_add", 0);
    169 		(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_load);
    170 		(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_unload);
    171 #else
    172 		(void) kobj_notify_add(&knl_load);
    173 		(void) kobj_notify_add(&knl_unload);
    174 #endif	/* NO_KOBJ_NOTIFY */
    175 		prom_interpret(INSTALL_DBP, 0, 0, 0, 0, 0);
    176 		debug_enter("Defer breakpoint enabled. Add breakpoints, then");
    177 	}
    178 done:
    179 	kobj_free(fth_buf, fsz + 1);
    180 err_stat:
    181 	kobj_close_file(file);
    182 
    183 	if (boothowto & RB_HALT)
    184 		debug_enter("forthdebug: halt flag (-h) is set.\n");
    185 }
    186