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 5*5412Smb158278 * Common Development and Distribution License (the "License"). 6*5412Smb158278 * 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 /* 22*5412Smb158278 * 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 750Sstevel@tonic-gate static void fdbp_hook() {} /* null function for defer breakpoint operation */ 760Sstevel@tonic-gate 770Sstevel@tonic-gate /*ARGSUSED*/ 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 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; 990Sstevel@tonic-gate struct bootstat bstat; 1000Sstevel@tonic-gate struct _buf *file; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate if (!forthdebug_supported) { 103*5412Smb158278 if (obpdebug) 104*5412Smb158278 (void) modload("misc", "obpsym"); 1050Sstevel@tonic-gate return; 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate forthdebug_dbp |= boothowto & RB_FORTHDEBUGDBP; 1090Sstevel@tonic-gate forthdebug |= (boothowto & RB_FORTHDEBUG) | forthdebug_dbp; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate file = kobj_open_path(FDEBUGFILE, 1, 1); 1120Sstevel@tonic-gate if (file == (struct _buf *)-1) { 1130Sstevel@tonic-gate cmn_err(CE_CONT, "Can't open %s\n", FDEBUGFILE); 1140Sstevel@tonic-gate return; 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate i = BOP_FSTAT(bootops, file->_fd, &bstat); 1180Sstevel@tonic-gate if (i || !bstat.st_size) { 1190Sstevel@tonic-gate cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n", 120*5412Smb158278 FDEBUGFILE, i, (long long)bstat.st_size); 1210Sstevel@tonic-gate goto err_stat; 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate fth_buf = (char *)kobj_zalloc(bstat.st_size + 1, KM_SLEEP); 1250Sstevel@tonic-gate sz = kobj_read_file(file, fth_buf, bstat.st_size, 0); /* entire file */ 1260Sstevel@tonic-gate if (sz < 0) { 1270Sstevel@tonic-gate cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE); 1280Sstevel@tonic-gate goto done; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate ASSERT(bstat.st_size == sz); 1310Sstevel@tonic-gate fth_buf[sz] = 0; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* resolve all essential symbols in basic_sym[] */ 1340Sstevel@tonic-gate for (i = 0; basic_sym[i]; i += 2) { 1350Sstevel@tonic-gate buf_p = strstr(fth_buf, basic_sym[i + 1]); 1360Sstevel@tonic-gate modsym = kobj_getsymvalue(basic_sym[i], 0); 1370Sstevel@tonic-gate if (buf_p && modsym) { 1380Sstevel@tonic-gate (void) sprintf(buf_p, "%16p", (void *)modsym); 1390Sstevel@tonic-gate buf_p += 16; 1400Sstevel@tonic-gate *buf_p++ = ' '; /* erase null char by sprintf */ 1410Sstevel@tonic-gate } else { 1420Sstevel@tonic-gate cmn_err(CE_CONT, 1430Sstevel@tonic-gate "forthdebug_init: No %s symbol(%p,%p), aborted\n", 1440Sstevel@tonic-gate basic_sym[i], (void *)buf_p, (void *)modsym); 1450Sstevel@tonic-gate goto done; 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate if (!forthdebug) { /* symbol lookup services only */ 1490Sstevel@tonic-gate if (!(buf_p = strstr(fth_buf, SYMBOL_END))) { 1500Sstevel@tonic-gate cmn_err(CE_CONT, "No %s in forthdebug\n", SYMBOL_END); 1510Sstevel@tonic-gate goto done; 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate *buf_p = '\0'; 1540Sstevel@tonic-gate #ifdef DEBUG 1550Sstevel@tonic-gate cmn_err(CE_CONT, "symbol lookup service (%ld bytes)\n", 156*5412Smb158278 (long)(buf_p - fth_buf)); 1570Sstevel@tonic-gate #endif /* DEBUG */ 1580Sstevel@tonic-gate prom_interpret(fth_buf, 0, 0, 0, 0, 0); 1590Sstevel@tonic-gate goto done; 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate cmn_err(CE_CONT, "%s (%d bytes) ", FDEBUGFILE, sz); 1630Sstevel@tonic-gate prom_interpret(fth_buf, 0, 0, 0, 0, 0); 1640Sstevel@tonic-gate cmn_err(CE_CONT, "loaded\n"); 1650Sstevel@tonic-gate obpdebug = 1; /* backward compatibility */ 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate if (forthdebug_dbp) { 1680Sstevel@tonic-gate #ifdef NO_KOBJ_NOTIFY 1690Sstevel@tonic-gate modsym = kobj_getsymvalue("kobj_notify_add", 0); 1700Sstevel@tonic-gate (void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_load); 1710Sstevel@tonic-gate (void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_unload); 1720Sstevel@tonic-gate #else 1730Sstevel@tonic-gate (void) kobj_notify_add(&knl_load); 1740Sstevel@tonic-gate (void) kobj_notify_add(&knl_unload); 1750Sstevel@tonic-gate #endif /* NO_KOBJ_NOTIFY */ 1760Sstevel@tonic-gate prom_interpret(INSTALL_DBP, 0, 0, 0, 0, 0); 1770Sstevel@tonic-gate debug_enter("Defer breakpoint enabled. Add breakpoints, then"); 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate done: 1800Sstevel@tonic-gate kobj_free(fth_buf, bstat.st_size + 1); 1810Sstevel@tonic-gate err_stat: 1820Sstevel@tonic-gate kobj_close_file(file); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (boothowto & RB_HALT) 1850Sstevel@tonic-gate debug_enter("forthdebug: halt flag (-h) is set.\n"); 1860Sstevel@tonic-gate } 187