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