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
55412Smb158278 * Common Development and Distribution License (the "License").
65412Smb158278 * 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 */
210Sstevel@tonic-gate /*
225412Smb158278 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/cmn_err.h>
300Sstevel@tonic-gate #include <sys/modctl.h>
310Sstevel@tonic-gate #include <sys/kobj.h>
320Sstevel@tonic-gate #include <sys/kobj_impl.h>
330Sstevel@tonic-gate #include <sys/promif.h>
340Sstevel@tonic-gate #include <sys/promimpl.h>
350Sstevel@tonic-gate #include <sys/reboot.h>
360Sstevel@tonic-gate #include <sys/bootconf.h>
370Sstevel@tonic-gate #include <sys/systm.h> /* strstr */
380Sstevel@tonic-gate #include <sys/machsystm.h> /* obpdebug */
390Sstevel@tonic-gate
400Sstevel@tonic-gate #define FDEBUGFILE "misc/forthdebug"
410Sstevel@tonic-gate #define INSTALL_DBP "kdbg-words dbp-install previous"
420Sstevel@tonic-gate #define SYMBOL_END "END OF SYMBOL"
430Sstevel@tonic-gate
440Sstevel@tonic-gate #ifdef DEBUG
450Sstevel@tonic-gate static int forthdebug = 1;
460Sstevel@tonic-gate #else
470Sstevel@tonic-gate static int forthdebug = 0;
480Sstevel@tonic-gate #endif /* DEBUG */
490Sstevel@tonic-gate
500Sstevel@tonic-gate static int forthdebug_dbp = 0;
510Sstevel@tonic-gate int forthdebug_supported = 1;
520Sstevel@tonic-gate int modreloc_flag = KOBJ_RELOCATED;
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * basic_sym[] holds all essential symbols the symbol lookup
560Sstevel@tonic-gate * service requires. Forthdebug stub names appears in forthdebug
570Sstevel@tonic-gate * as place holders. They are replaced with the value of corresponding
580Sstevel@tonic-gate * kernel variables. For example, "modules-val-here" in forthdebug
590Sstevel@tonic-gate * is replaced with the address of "modules" variable.
600Sstevel@tonic-gate *
610Sstevel@tonic-gate * To improve performance, we mandate the records be in the same
620Sstevel@tonic-gate * sequence they appear in forthdebug, i.e "modules-val-here" is
630Sstevel@tonic-gate * ahead of "primaries-v-here" in misc/forthdebug.
640Sstevel@tonic-gate *
650Sstevel@tonic-gate * The last record must be all 0 to indicate end of the array.
660Sstevel@tonic-gate */
670Sstevel@tonic-gate static char *basic_sym[] = {
680Sstevel@tonic-gate /* kernel variable */ /* forthdebug stub name - must be 16 chars */
690Sstevel@tonic-gate "modules", "modules-val-here",
700Sstevel@tonic-gate "primaries", "primaries-v-here",
710Sstevel@tonic-gate "modreloc_flag", "modreloc-flagval",
720Sstevel@tonic-gate 0, 0
730Sstevel@tonic-gate };
740Sstevel@tonic-gate
fdbp_hook()750Sstevel@tonic-gate static void fdbp_hook() {} /* null function for defer breakpoint operation */
760Sstevel@tonic-gate
770Sstevel@tonic-gate /*ARGSUSED*/
fdbp_snoop(unsigned int i,struct modctl * modctl_p)780Sstevel@tonic-gate static void fdbp_snoop(unsigned int i, struct modctl *modctl_p)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate promif_preprom();
810Sstevel@tonic-gate fdbp_hook();
820Sstevel@tonic-gate promif_postprom();
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate static kobj_notify_list_t knl_load = {
860Sstevel@tonic-gate fdbp_snoop, KOBJ_NOTIFY_MODLOADED, 0, 0
870Sstevel@tonic-gate };
880Sstevel@tonic-gate
890Sstevel@tonic-gate static kobj_notify_list_t knl_unload = {
900Sstevel@tonic-gate fdbp_snoop, KOBJ_NOTIFY_MODUNLOADING, 0, 0
910Sstevel@tonic-gate };
920Sstevel@tonic-gate
930Sstevel@tonic-gate void
forthdebug_init(void)940Sstevel@tonic-gate forthdebug_init(void)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate char *fth_buf, *buf_p;
970Sstevel@tonic-gate ulong_t modsym;
980Sstevel@tonic-gate int i, sz;
99*5648Ssetje uint64_t fsz;
1000Sstevel@tonic-gate struct _buf *file;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if (!forthdebug_supported) {
1035493Smb158278 (void) modload("misc", "obpsym");
1040Sstevel@tonic-gate return;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate forthdebug_dbp |= boothowto & RB_FORTHDEBUGDBP;
1080Sstevel@tonic-gate forthdebug |= (boothowto & RB_FORTHDEBUG) | forthdebug_dbp;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate file = kobj_open_path(FDEBUGFILE, 1, 1);
1110Sstevel@tonic-gate if (file == (struct _buf *)-1) {
1120Sstevel@tonic-gate cmn_err(CE_CONT, "Can't open %s\n", FDEBUGFILE);
1130Sstevel@tonic-gate return;
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
116*5648Ssetje i = kobj_get_filesize(file, &fsz);
117*5648Ssetje if (i || !fsz) {
1180Sstevel@tonic-gate cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n",
119*5648Ssetje FDEBUGFILE, i, (long long)fsz);
1200Sstevel@tonic-gate goto err_stat;
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate
123*5648Ssetje fth_buf = (char *)kobj_zalloc(fsz + 1, KM_SLEEP);
124*5648Ssetje sz = kobj_read_file(file, fth_buf, fsz, 0); /* entire file */
1250Sstevel@tonic-gate if (sz < 0) {
1260Sstevel@tonic-gate cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE);
1270Sstevel@tonic-gate goto done;
1280Sstevel@tonic-gate }
129*5648Ssetje ASSERT(fsz == sz);
1300Sstevel@tonic-gate fth_buf[sz] = 0;
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* resolve all essential symbols in basic_sym[] */
1330Sstevel@tonic-gate for (i = 0; basic_sym[i]; i += 2) {
1340Sstevel@tonic-gate buf_p = strstr(fth_buf, basic_sym[i + 1]);
1350Sstevel@tonic-gate modsym = kobj_getsymvalue(basic_sym[i], 0);
1360Sstevel@tonic-gate if (buf_p && modsym) {
1370Sstevel@tonic-gate (void) sprintf(buf_p, "%16p", (void *)modsym);
1380Sstevel@tonic-gate buf_p += 16;
1390Sstevel@tonic-gate *buf_p++ = ' '; /* erase null char by sprintf */
1400Sstevel@tonic-gate } else {
1410Sstevel@tonic-gate cmn_err(CE_CONT,
1420Sstevel@tonic-gate "forthdebug_init: No %s symbol(%p,%p), aborted\n",
1430Sstevel@tonic-gate basic_sym[i], (void *)buf_p, (void *)modsym);
1440Sstevel@tonic-gate goto done;
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate if (!forthdebug) { /* symbol lookup services only */
1480Sstevel@tonic-gate if (!(buf_p = strstr(fth_buf, SYMBOL_END))) {
1490Sstevel@tonic-gate cmn_err(CE_CONT, "No %s in forthdebug\n", SYMBOL_END);
1500Sstevel@tonic-gate goto done;
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate *buf_p = '\0';
1530Sstevel@tonic-gate #ifdef DEBUG
1540Sstevel@tonic-gate cmn_err(CE_CONT, "symbol lookup service (%ld bytes)\n",
1555412Smb158278 (long)(buf_p - fth_buf));
1560Sstevel@tonic-gate #endif /* DEBUG */
1570Sstevel@tonic-gate prom_interpret(fth_buf, 0, 0, 0, 0, 0);
1580Sstevel@tonic-gate goto done;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate cmn_err(CE_CONT, "%s (%d bytes) ", FDEBUGFILE, sz);
1620Sstevel@tonic-gate prom_interpret(fth_buf, 0, 0, 0, 0, 0);
1630Sstevel@tonic-gate cmn_err(CE_CONT, "loaded\n");
1640Sstevel@tonic-gate obpdebug = 1; /* backward compatibility */
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate if (forthdebug_dbp) {
1670Sstevel@tonic-gate #ifdef NO_KOBJ_NOTIFY
1680Sstevel@tonic-gate modsym = kobj_getsymvalue("kobj_notify_add", 0);
1690Sstevel@tonic-gate (void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_load);
1700Sstevel@tonic-gate (void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_unload);
1710Sstevel@tonic-gate #else
1720Sstevel@tonic-gate (void) kobj_notify_add(&knl_load);
1730Sstevel@tonic-gate (void) kobj_notify_add(&knl_unload);
1740Sstevel@tonic-gate #endif /* NO_KOBJ_NOTIFY */
1750Sstevel@tonic-gate prom_interpret(INSTALL_DBP, 0, 0, 0, 0, 0);
1760Sstevel@tonic-gate debug_enter("Defer breakpoint enabled. Add breakpoints, then");
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate done:
179*5648Ssetje kobj_free(fth_buf, fsz + 1);
1800Sstevel@tonic-gate err_stat:
1810Sstevel@tonic-gate kobj_close_file(file);
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate if (boothowto & RB_HALT)
1840Sstevel@tonic-gate debug_enter("forthdebug: halt flag (-h) is set.\n");
1850Sstevel@tonic-gate }
186