xref: /titanic_51/usr/src/uts/sun4/os/forthdebug.c (revision 986fd29a0dc13f7608ef7f508f6e700bd7bc2720)
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
511021a81Smb158278  * Common Development and Distribution License (the "License").
611021a81Smb158278  * 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  */
217c478bd9Sstevel@tonic-gate /*
2211021a81Smb158278  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
307c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
317c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
327c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
337c478bd9Sstevel@tonic-gate #include <sys/promif.h>
347c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
357c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
367c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
377c478bd9Sstevel@tonic-gate #include <sys/systm.h>		/* strstr */
387c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>	/* obpdebug */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #define	FDEBUGFILE	"misc/forthdebug"
417c478bd9Sstevel@tonic-gate #define	INSTALL_DBP	"kdbg-words dbp-install previous"
427c478bd9Sstevel@tonic-gate #define	SYMBOL_END	"END OF SYMBOL"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifdef DEBUG
457c478bd9Sstevel@tonic-gate static int forthdebug	= 1;
467c478bd9Sstevel@tonic-gate #else
477c478bd9Sstevel@tonic-gate static int forthdebug	= 0;
487c478bd9Sstevel@tonic-gate #endif /* DEBUG */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate static int forthdebug_dbp = 0;
517c478bd9Sstevel@tonic-gate int forthdebug_supported = 1;
527c478bd9Sstevel@tonic-gate int modreloc_flag = KOBJ_RELOCATED;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * basic_sym[] holds all essential symbols the symbol lookup
567c478bd9Sstevel@tonic-gate  * service requires. Forthdebug stub names appears in forthdebug
577c478bd9Sstevel@tonic-gate  * as place holders. They are replaced with the value of corresponding
587c478bd9Sstevel@tonic-gate  * kernel variables. For example, "modules-val-here" in forthdebug
597c478bd9Sstevel@tonic-gate  * is replaced with the address of "modules" variable.
607c478bd9Sstevel@tonic-gate  *
617c478bd9Sstevel@tonic-gate  * To improve performance, we mandate the records be in the same
627c478bd9Sstevel@tonic-gate  * sequence they appear in forthdebug, i.e "modules-val-here" is
637c478bd9Sstevel@tonic-gate  * ahead of "primaries-v-here" in misc/forthdebug.
647c478bd9Sstevel@tonic-gate  *
657c478bd9Sstevel@tonic-gate  * The last record must be all 0 to indicate end of the array.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate static char *basic_sym[] = {
687c478bd9Sstevel@tonic-gate 	/* kernel variable */	/* forthdebug stub name - must be 16 chars */
697c478bd9Sstevel@tonic-gate 	"modules",		"modules-val-here",
707c478bd9Sstevel@tonic-gate 	"primaries",		"primaries-v-here",
717c478bd9Sstevel@tonic-gate 	"modreloc_flag",	"modreloc-flagval",
727c478bd9Sstevel@tonic-gate 	0,			0
737c478bd9Sstevel@tonic-gate };
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static void fdbp_hook() {} /* null function for defer breakpoint operation */
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
787c478bd9Sstevel@tonic-gate static void fdbp_snoop(unsigned int i, struct modctl *modctl_p)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 	promif_preprom();
817c478bd9Sstevel@tonic-gate 	fdbp_hook();
827c478bd9Sstevel@tonic-gate 	promif_postprom();
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static kobj_notify_list_t knl_load = {
867c478bd9Sstevel@tonic-gate 	fdbp_snoop, KOBJ_NOTIFY_MODLOADED, 0, 0
877c478bd9Sstevel@tonic-gate };
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static kobj_notify_list_t knl_unload = {
907c478bd9Sstevel@tonic-gate 	fdbp_snoop, KOBJ_NOTIFY_MODUNLOADING, 0, 0
917c478bd9Sstevel@tonic-gate };
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate void
947c478bd9Sstevel@tonic-gate forthdebug_init(void)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	char *fth_buf, *buf_p;
977c478bd9Sstevel@tonic-gate 	ulong_t modsym;
987c478bd9Sstevel@tonic-gate 	int i, sz;
99*986fd29aSsetje 	uint64_t fsz;
1007c478bd9Sstevel@tonic-gate 	struct _buf *file;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	if (!forthdebug_supported) {
1037c478bd9Sstevel@tonic-gate 		(void) modload("misc", "obpsym");
1047c478bd9Sstevel@tonic-gate 		return;
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	forthdebug_dbp |= boothowto & RB_FORTHDEBUGDBP;
1087c478bd9Sstevel@tonic-gate 	forthdebug |= (boothowto & RB_FORTHDEBUG) | forthdebug_dbp;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	file = kobj_open_path(FDEBUGFILE, 1, 1);
1117c478bd9Sstevel@tonic-gate 	if (file == (struct _buf *)-1) {
1127c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Can't open %s\n", FDEBUGFILE);
1137c478bd9Sstevel@tonic-gate 		return;
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
116*986fd29aSsetje 	i = kobj_get_filesize(file, &fsz);
117*986fd29aSsetje 	if (i || !fsz) {
1187c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n",
119*986fd29aSsetje 		    FDEBUGFILE, i, (long long)fsz);
1207c478bd9Sstevel@tonic-gate 		goto err_stat;
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
123*986fd29aSsetje 	fth_buf = (char *)kobj_zalloc(fsz + 1, KM_SLEEP);
124*986fd29aSsetje 	sz = kobj_read_file(file, fth_buf, fsz, 0); /* entire file */
1257c478bd9Sstevel@tonic-gate 	if (sz < 0) {
1267c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE);
1277c478bd9Sstevel@tonic-gate 		goto done;
1287c478bd9Sstevel@tonic-gate 	}
129*986fd29aSsetje 	ASSERT(fsz == sz);
1307c478bd9Sstevel@tonic-gate 	fth_buf[sz] = 0;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/* resolve all essential symbols in basic_sym[] */
1337c478bd9Sstevel@tonic-gate 	for (i = 0; basic_sym[i]; i += 2) {
1347c478bd9Sstevel@tonic-gate 		buf_p = strstr(fth_buf, basic_sym[i + 1]);
1357c478bd9Sstevel@tonic-gate 		modsym = kobj_getsymvalue(basic_sym[i], 0);
1367c478bd9Sstevel@tonic-gate 		if (buf_p && modsym) {
1377c478bd9Sstevel@tonic-gate 			(void) sprintf(buf_p, "%16p", (void *)modsym);
1387c478bd9Sstevel@tonic-gate 			buf_p += 16;
1397c478bd9Sstevel@tonic-gate 			*buf_p++ = ' ';	/* erase null char by sprintf */
1407c478bd9Sstevel@tonic-gate 		} else {
1417c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
1427c478bd9Sstevel@tonic-gate 			    "forthdebug_init: No %s symbol(%p,%p), aborted\n",
1437c478bd9Sstevel@tonic-gate 			    basic_sym[i], (void *)buf_p, (void *)modsym);
1447c478bd9Sstevel@tonic-gate 			goto done;
1457c478bd9Sstevel@tonic-gate 		}
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 	if (!forthdebug) {	/* symbol lookup services only */
1487c478bd9Sstevel@tonic-gate 		if (!(buf_p = strstr(fth_buf, SYMBOL_END))) {
1497c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "No %s in forthdebug\n", SYMBOL_END);
1507c478bd9Sstevel@tonic-gate 			goto done;
1517c478bd9Sstevel@tonic-gate 		}
1527c478bd9Sstevel@tonic-gate 		*buf_p = '\0';
1537c478bd9Sstevel@tonic-gate #ifdef DEBUG
1547c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "symbol lookup service (%ld bytes)\n",
1557c478bd9Sstevel@tonic-gate 		    (long)(buf_p - fth_buf));
1567c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1577c478bd9Sstevel@tonic-gate 		prom_interpret(fth_buf, 0, 0, 0, 0, 0);
1587c478bd9Sstevel@tonic-gate 		goto done;
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "%s (%d bytes) ", FDEBUGFILE, sz);
1627c478bd9Sstevel@tonic-gate 	prom_interpret(fth_buf, 0, 0, 0, 0, 0);
1637c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "loaded\n");
1647c478bd9Sstevel@tonic-gate 	obpdebug = 1;	/* backward compatibility */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (forthdebug_dbp) {
1677c478bd9Sstevel@tonic-gate #ifdef NO_KOBJ_NOTIFY
1687c478bd9Sstevel@tonic-gate 		modsym = kobj_getsymvalue("kobj_notify_add", 0);
1697c478bd9Sstevel@tonic-gate 		(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_load);
1707c478bd9Sstevel@tonic-gate 		(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_unload);
1717c478bd9Sstevel@tonic-gate #else
1727c478bd9Sstevel@tonic-gate 		(void) kobj_notify_add(&knl_load);
1737c478bd9Sstevel@tonic-gate 		(void) kobj_notify_add(&knl_unload);
1747c478bd9Sstevel@tonic-gate #endif	/* NO_KOBJ_NOTIFY */
1757c478bd9Sstevel@tonic-gate 		prom_interpret(INSTALL_DBP, 0, 0, 0, 0, 0);
1767c478bd9Sstevel@tonic-gate 		debug_enter("Defer breakpoint enabled. Add breakpoints, then");
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate done:
179*986fd29aSsetje 	kobj_free(fth_buf, fsz + 1);
1807c478bd9Sstevel@tonic-gate err_stat:
1817c478bd9Sstevel@tonic-gate 	kobj_close_file(file);
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	if (boothowto & RB_HALT)
1847c478bd9Sstevel@tonic-gate 		debug_enter("forthdebug: halt flag (-h) is set.\n");
1857c478bd9Sstevel@tonic-gate }
186